diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 90283c70..3ec1d633 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -84,7 +84,6 @@ jobs: run: make wasi-libc - name: Install fpm run: | - sudo apt-get install ruby ruby-dev sudo gem install --no-document fpm - name: Build TinyGo release run: | @@ -94,7 +93,7 @@ jobs: - name: Publish release artifact uses: actions/upload-artifact@v2 with: - name: release-double-zipped + name: linux-amd64-double-zipped path: | /tmp/tinygo.linux-amd64.tar.gz /tmp/tinygo_amd64.deb @@ -116,7 +115,7 @@ jobs: - name: Download release artifact uses: actions/download-artifact@v2 with: - name: release-double-zipped + name: linux-amd64-double-zipped - name: Extract release tarball run: | mkdir -p ~/lib @@ -242,3 +241,108 @@ jobs: - run: make smoketest - run: make wasmtest - run: make tinygo-baremetal + build-linux-arm: + # Build ARM Linux binaries, ready for release. + # This intentionally uses an older Linux image, so that we compile against + # an older glibc version and therefore are compatible with a wide range of + # Linux distributions. + # It is set to "needs: build-linux" because it modifies the release created + # in that process to avoid doing lots of duplicate work and to avoid + # complications around precompiled libraries such as compiler-rt shipped as + # part of the release tarball. + runs-on: ubuntu-18.04 + needs: build-linux + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Install apt dependencies + run: | + sudo apt-get install --no-install-recommends \ + qemu-user \ + g++-arm-linux-gnueabihf \ + libc6-dev-armhf-cross + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: '1.17' + - name: Cache Go + uses: actions/cache@v2 + with: + key: go-cache-linux-arm-v2-${{ hashFiles('go.mod') }} + path: | + ~/.cache/go-build + ~/go/pkg/mod + - name: Cache LLVM source + uses: actions/cache@v2 + id: cache-llvm-source + with: + key: llvm-source-14-linux-v1 + path: | + llvm-project/clang/lib/Headers + llvm-project/clang/include + llvm-project/compiler-rt + llvm-project/lld/include + llvm-project/llvm/include + - name: Download LLVM source + if: steps.cache-llvm-source.outputs.cache-hit != 'true' + run: make llvm-source + - name: Cache LLVM build + uses: actions/cache@v2 + id: cache-llvm-build + with: + key: llvm-build-14-linux-arm-v1 + path: llvm-build + - name: Build LLVM + if: steps.cache-llvm-build.outputs.cache-hit != 'true' + run: | + # fetch LLVM source + rm -rf llvm-project + make llvm-source + # Install build dependencies. + sudo apt-get install --no-install-recommends ninja-build + # build! + make llvm-build CROSS=arm-linux-gnueabihf + # Remove unnecessary object files (to reduce cache size). + find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \; + - name: Cache Binaryen + uses: actions/cache@v2 + id: cache-binaryen + with: + key: binaryen-linux-arm-v1 + path: build/wasm-opt + - name: Build Binaryen + if: steps.cache-binaryen.outputs.cache-hit != 'true' + run: | + sudo apt-get install --no-install-recommends ninja-build + git submodule update --init lib/binaryen + make CROSS=arm-linux-gnueabihf binaryen + - name: Install fpm + run: | + sudo gem install --no-document fpm + - name: Build TinyGo binary + run: | + make CROSS=arm-linux-gnueabihf + - name: Download amd64 release + uses: actions/download-artifact@v2 + with: + name: linux-amd64-double-zipped + - name: Extract amd64 release + run: | + mkdir -p build/release + tar -xf tinygo.linux-amd64.tar.gz -C build/release tinygo + - name: Modify release + run: | + cp -p build/tinygo build/release/tinygo/bin + cp -p build/wasm-opt build/release/tinygo/bin + - name: Create arm release + run: | + make release deb RELEASEONLY=1 DEB_ARCH=armhf + cp -p build/release.tar.gz /tmp/tinygo.linux-arm.tar.gz + cp -p build/release.deb /tmp/tinygo_armhf.deb + - name: Publish release artifact + uses: actions/upload-artifact@v2 + with: + name: linux-arm-double-zipped + path: | + /tmp/tinygo.linux-arm.tar.gz + /tmp/tinygo_armhf.deb diff --git a/Makefile b/Makefile index 12ad7a86..dc388c21 100644 --- a/Makefile +++ b/Makefile @@ -50,6 +50,29 @@ else LLVM_OPTION += '-DLLVM_ENABLE_ASSERTIONS=OFF' endif +# Cross compiling support. +ifneq ($(CROSS),) + CC = $(CROSS)-gcc + CXX = $(CROSS)-g++ + LLVM_OPTION += \ + -DCMAKE_C_COMPILER=$(CC) \ + -DCMAKE_CXX_COMPILER=$(CXX) \ + -DLLVM_DEFAULT_TARGET_TRIPLE=$(CROSS) \ + -DCROSS_TOOLCHAIN_FLAGS_NATIVE="-UCMAKE_C_COMPILER;-UCMAKE_CXX_COMPILER" + ifeq ($(CROSS), arm-linux-gnueabihf) + # Assume we're building on a Debian-like distro, with QEMU installed. + LLVM_CONFIG_PREFIX = qemu-arm -L /usr/arm-linux-gnueabihf/ + # The CMAKE_SYSTEM_NAME flag triggers cross compilation mode. + LLVM_OPTION += \ + -DCMAKE_SYSTEM_NAME=Linux \ + -DLLVM_TARGET_ARCH=ARM + GOENVFLAGS = GOARCH=arm CC=$(CC) CXX=$(CXX) CGO_ENABLED=1 + BINARYEN_OPTION += -DCMAKE_C_COMPILER=$(CC) -DCMAKE_CXX_COMPILER=$(CXX) + else + $(error Unknown cross compilation target: $(CROSS)) + endif +endif + .PHONY: all tinygo test $(LLVM_BUILDDIR) llvm-source clean fmt gen-device gen-device-nrf gen-device-nxp gen-device-avr gen-device-rp LLVM_COMPONENTS = all-targets analysis asmparser asmprinter bitreader bitwriter codegen core coroutines coverage debuginfodwarf debuginfopdb executionengine frontendopenmp instrumentation interpreter ipo irreader libdriver linker lto mc mcjit objcarcopts option profiledata scalaropts support target windowsmanifest @@ -110,9 +133,9 @@ NINJA_BUILD_TARGETS = clang llvm-config llvm-ar llvm-nm $(addprefix lib/lib,$(ad # For static linking. ifneq ("$(wildcard $(LLVM_BUILDDIR)/bin/llvm-config*)","") - CGO_CPPFLAGS+=$(shell $(LLVM_BUILDDIR)/bin/llvm-config --cppflags) -I$(abspath $(LLVM_BUILDDIR))/tools/clang/include -I$(abspath $(CLANG_SRC))/include -I$(abspath $(LLD_SRC))/include + CGO_CPPFLAGS+=$(shell $(LLVM_CONFIG_PREFIX) $(LLVM_BUILDDIR)/bin/llvm-config --cppflags) -I$(abspath $(LLVM_BUILDDIR))/tools/clang/include -I$(abspath $(CLANG_SRC))/include -I$(abspath $(LLD_SRC))/include CGO_CXXFLAGS=-std=c++14 - CGO_LDFLAGS+=-L$(abspath $(LLVM_BUILDDIR)/lib) -lclang $(CLANG_LIBS) $(LLD_LIBS) $(shell $(LLVM_BUILDDIR)/bin/llvm-config --ldflags --libs --system-libs $(LLVM_COMPONENTS)) -lstdc++ $(CGO_LDFLAGS_EXTRA) + CGO_LDFLAGS+=-L$(abspath $(LLVM_BUILDDIR)/lib) -lclang $(CLANG_LIBS) $(LLD_LIBS) $(shell $(LLVM_CONFIG_PREFIX) $(LLVM_BUILDDIR)/bin/llvm-config --ldflags --libs --system-libs $(LLVM_COMPONENTS)) -lstdc++ $(CGO_LDFLAGS_EXTRA) endif clean: @@ -208,8 +231,7 @@ lib/wasi-libc/sysroot/lib/wasm32-wasi/libc.a: # Build the Go compiler. tinygo: @if [ ! -f "$(LLVM_BUILDDIR)/bin/llvm-config" ]; then echo "Fetch and build LLVM first by running:"; echo " make llvm-source"; echo " make $(LLVM_BUILDDIR)"; exit 1; fi - CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) build -buildmode exe -o build/tinygo$(EXE) -tags byollvm -ldflags="-X github.com/tinygo-org/tinygo/goenv.GitSha1=`git rev-parse --short HEAD`" . - + CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GOENVFLAGS) $(GO) build -buildmode exe -o build/tinygo$(EXE) -tags byollvm -ldflags="-X github.com/tinygo-org/tinygo/goenv.GitSha1=`git rev-parse --short HEAD`" . test: wasi-libc CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=20m -buildmode exe -tags byollvm ./builder ./cgo ./compileopts ./compiler ./interp ./transform . @@ -694,12 +716,18 @@ endif ./build/tinygo build-library -target=cortex-m0plus -o build/release/tinygo/pkg/thumbv6m-unknown-unknown-eabi-cortex-m0plus/picolibc picolibc ./build/tinygo build-library -target=cortex-m4 -o build/release/tinygo/pkg/thumbv7em-unknown-unknown-eabi-cortex-m4/picolibc picolibc -release: build/release +release: tar -czf build/release.tar.gz -C build/release tinygo -deb: build/release +DEB_ARCH ?= native +deb: @mkdir -p build/release-deb/usr/local/bin @mkdir -p build/release-deb/usr/local/lib cp -ar build/release/tinygo build/release-deb/usr/local/lib/tinygo ln -sf ../lib/tinygo/bin/tinygo build/release-deb/usr/local/bin/tinygo - fpm -f -s dir -t deb -n tinygo -v $(shell grep "const Version = " goenv/version.go | awk '{print $$NF}') -m '@tinygo-org' --description='TinyGo is a Go compiler for small places.' --license='BSD 3-Clause' --url=https://tinygo.org/ --deb-changelog CHANGELOG.md -p build/release.deb -C ./build/release-deb + fpm -f -s dir -t deb -n tinygo -a $(DEB_ARCH) -v $(shell grep "const Version = " goenv/version.go | awk '{print $$NF}') -m '@tinygo-org' --description='TinyGo is a Go compiler for small places.' --license='BSD 3-Clause' --url=https://tinygo.org/ --deb-changelog CHANGELOG.md -p build/release.deb -C ./build/release-deb + +ifneq ($(RELEASEONLY), 1) +release: build/release +deb: build/release +endif