# aliases
all : tinygo
# Default build and source directories, as created by `make llvm-build`.
LLVM_BUILDDIR ?= llvm-build
CLANG_SRC ?= llvm-project/clang
LLD_SRC ?= llvm-project/lld
# Go binary and GOROOT to select
GO ?= go
export GOROOT = $( shell $( GO) env GOROOT)
# md5sum binary
MD5SUM = md5sum
# Python binary
PYTHON ?= python
# tinygo binary for tests
TINYGO ?= tinygo
# Use CCACHE for LLVM if possible
i f n e q ( , $( shell which ccache ) )
LLVM_OPTION += '-DLLVM_CCACHE_BUILD=ON'
e n d i f
# Allow enabling LLVM assertions
i f e q ( 1 , $( ASSERT ) )
LLVM_OPTION += '-DLLVM_ENABLE_ASSERTIONS=ON'
e l s e
LLVM_OPTION += '-DLLVM_ENABLE_ASSERTIONS=OFF'
e n d i f
.PHONY : all tinygo test $( LLVM_BUILDDIR ) llvm -source clean fmt gen -device gen -device -nrf gen -device -avr
LLVM_COMPONENTS = all-targets analysis asmparser asmprinter bitreader bitwriter codegen core coroutines debuginfodwarf executionengine instrumentation interpreter ipo irreader linker lto mc mcjit objcarcopts option profiledata scalaropts support target
i f e q ( $( OS ) , W i n d o w s _ N T )
EXE = .exe
START_GROUP = -Wl,--start-group
END_GROUP = -Wl,--end-group
# LLVM compiled using MinGW on Windows appears to have problems with threads.
# Without this flag, linking results in errors like these:
# libLLVMSupport.a(Threading.cpp.obj):Threading.cpp:(.text+0x55): undefined reference to `std::thread::hardware_concurrency()'
LLVM_OPTION += -DLLVM_ENABLE_THREADS= OFF
CGO_LDFLAGS += -static -static-libgcc -static-libstdc++
CGO_LDFLAGS_EXTRA += -lversion
# Build libclang manually because the CMake-based build system on Windows
# doesn't allow building libclang as a static library.
LIBCLANG_PATH = $( abspath build/libclang-custom.a)
LIBCLANG_FILES = $( abspath $( wildcard $( LLVM_BUILDDIR) /tools/clang/tools/libclang/CMakeFiles/libclang.dir/*.cpp.obj) )
# Add the libclang dependency to the tinygo binary target.
tinygo : $( LIBCLANG_PATH )
test : $( LIBCLANG_PATH )
# Build libclang.
$(LIBCLANG_PATH) : $( LIBCLANG_FILES )
@mkdir -p build
ar rcs $( LIBCLANG_PATH) $^
e l s e i f e q ( $( shell uname -s ) , D a r w i n )
MD5SUM = md5
LIBCLANG_PATH = $( abspath $( LLVM_BUILDDIR) ) /lib/libclang.a
e l s e
LIBCLANG_PATH = $( abspath $( LLVM_BUILDDIR) ) /lib/libclang.a
START_GROUP = -Wl,--start-group
END_GROUP = -Wl,--end-group
e n d i f
CLANG_LIBS = $( START_GROUP) -lclangAnalysis -lclangARCMigrate -lclangAST -lclangASTMatchers -lclangBasic -lclangCodeGen -lclangCrossTU -lclangDriver -lclangDynamicASTMatchers -lclangEdit -lclangFormat -lclangFrontend -lclangFrontendTool -lclangHandleCXX -lclangHandleLLVM -lclangIndex -lclangLex -lclangParse -lclangRewrite -lclangRewriteFrontend -lclangSema -lclangSerialization -lclangStaticAnalyzerCheckers -lclangStaticAnalyzerCore -lclangStaticAnalyzerFrontend -lclangTooling -lclangToolingASTDiff -lclangToolingCore -lclangToolingInclusions $( END_GROUP) -lstdc++
LLD_LIBS = $( START_GROUP) -llldCOFF -llldCommon -llldCore -llldDriver -llldELF -llldMachO -llldMinGW -llldReaderWriter -llldWasm -llldYAML $( END_GROUP)
# For static linking.
i f n e q ( "$(wildcard $(LLVM_BUILDDIR)/bin/llvm-config*)" , "" )
CGO_CPPFLAGS = $( shell $( LLVM_BUILDDIR) /bin/llvm-config --cppflags) -I$( abspath $( CLANG_SRC) ) /include -I$( abspath $( LLD_SRC) ) /include
CGO_CXXFLAGS = -std= c++11
CGO_LDFLAGS += $( LIBCLANG_PATH) -std= c++11 -L$( abspath $( LLVM_BUILDDIR) /lib) $( CLANG_LIBS) $( LLD_LIBS) $( shell $( LLVM_BUILDDIR) /bin/llvm-config --ldflags --libs --system-libs $( LLVM_COMPONENTS) ) -lstdc++ $( CGO_LDFLAGS_EXTRA)
e n d i f
clean :
@rm -rf build
FMT_PATHS = ./*.go cgo compiler interp ir loader src/device/arm src/examples src/machine src/os src/reflect src/runtime src/sync src/syscall src/internal/reflectlite transform
fmt :
@gofmt -l -w $( FMT_PATHS)
fmt-check :
@unformatted= $$ ( gofmt -l $( FMT_PATHS) ) ; [ -z " $$ unformatted " ] && exit 0; echo "Unformatted:" ; for fn in $$ unformatted; do echo " $$ fn " ; done ; exit 1
gen-device : gen -device -avr gen -device -nrf gen -device -sam gen -device -sifive gen -device -stm 32
gen-device-avr :
$( PYTHON) ./tools/gen-device-avr.py lib/avr/packs/atmega src/device/avr/
$( PYTHON) ./tools/gen-device-avr.py lib/avr/packs/tiny src/device/avr/
GO111MODULE = off $( GO) fmt ./src/device/avr
gen-device-nrf :
$( PYTHON) ./tools/gen-device-svd.py lib/nrfx/mdk/ src/device/nrf/ --source= https://github.com/NordicSemiconductor/nrfx/tree/master/mdk
GO111MODULE = off $( GO) fmt ./src/device/nrf
gen-device-sam :
$( PYTHON) ./tools/gen-device-svd.py lib/cmsis-svd/data/Atmel/ src/device/sam/ --source= https://github.com/posborne/cmsis-svd/tree/master/data/Atmel
GO111MODULE = off $( GO) fmt ./src/device/sam
gen-device-sifive :
$( PYTHON) ./tools/gen-device-svd.py lib/cmsis-svd/data/SiFive-Community/ src/device/sifive/ --source= https://github.com/AdaCore/svd2ada/tree/master/CMSIS-SVD/SiFive-Community
GO111MODULE = off $( GO) fmt ./src/device/sifive
gen-device-stm32 :
$( PYTHON) ./tools/gen-device-svd.py lib/cmsis-svd/data/STMicro/ src/device/stm32/ --source= https://github.com/posborne/cmsis-svd/tree/master/data/STMicro
GO111MODULE = off $( GO) fmt ./src/device/stm32
# Get LLVM sources.
llvm-project/README.md :
git clone -b release/8.x https://github.com/llvm/llvm-project
llvm-source : llvm -project /README .md
# Configure LLVM.
TINYGO_SOURCE_DIR = $( shell pwd )
$(LLVM_BUILDDIR)/build.ninja : llvm -source
mkdir -p $( LLVM_BUILDDIR) ; cd $( LLVM_BUILDDIR) ; cmake -G Ninja $( TINYGO_SOURCE_DIR) /llvm-project/llvm "-DLLVM_TARGETS_TO_BUILD=X86;ARM;AArch64;WebAssembly" "-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=AVR;RISCV" -DCMAKE_BUILD_TYPE= Release -DLIBCLANG_BUILD_STATIC= ON -DLLVM_ENABLE_TERMINFO= OFF -DLLVM_ENABLE_ZLIB= OFF -DLLVM_ENABLE_PROJECTS= "clang;lld" -DLLVM_TOOL_CLANG_TOOLS_EXTRA_BUILD= OFF $( LLVM_OPTION)
# Build LLVM.
$(LLVM_BUILDDIR) : $( LLVM_BUILDDIR ) /build .ninja
cd $( LLVM_BUILDDIR) ; ninja
# 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 -o build/tinygo$( EXE) -tags byollvm .
test :
CGO_CPPFLAGS = " $( CGO_CPPFLAGS) " CGO_CXXFLAGS = " $( CGO_CXXFLAGS) " CGO_LDFLAGS = " $( CGO_LDFLAGS) " $( GO) test -v -tags byollvm ./interp ./transform .
tinygo-test :
cd tests/tinygotest && tinygo test
.PHONY : smoketest
smoketest :
# test all examples
$( TINYGO) build -size short -o test.hex -target= pca10040 examples/blinky1
@$( MD5SUM) test.hex
$( TINYGO) build -size short -o test.hex -target= pca10040 examples/adc
@$( MD5SUM) test.hex
$( TINYGO) build -size short -o test.hex -target= pca10040 examples/blinkm
@$( MD5SUM) test.hex
$( TINYGO) build -size short -o test.hex -target= pca10040 examples/blinky2
@$( MD5SUM) test.hex
$( TINYGO) build -size short -o test.hex -target= pca10040 examples/button
@$( MD5SUM) test.hex
$( TINYGO) build -size short -o test.hex -target= pca10040 examples/button2
@$( MD5SUM) test.hex
$( TINYGO) build -size short -o test.hex -target= pca10040 examples/echo
@$( MD5SUM) test.hex
$( TINYGO) build -size short -o test.hex -target= circuitplay-express examples/i2s
@$( MD5SUM) test.hex
$( TINYGO) build -size short -o test.hex -target= pca10040 examples/mcp3008
@$( MD5SUM) test.hex
$( TINYGO) build -size short -o test.hex -target= microbit examples/microbit-blink
@$( MD5SUM) test.hex
$( TINYGO) build -size short -o test.hex -target= pca10040 examples/pwm
@$( MD5SUM) test.hex
$( TINYGO) build -size short -o test.hex -target= pca10040 examples/serial
@$( MD5SUM) test.hex
$( TINYGO) build -size short -o test.hex -target= pca10040 examples/systick
@$( MD5SUM) test.hex
$( TINYGO) build -size short -o test.hex -target= pca10040 examples/test
@$( MD5SUM) test.hex
# test all targets/boards
$( TINYGO) build -o test.wasm -tags= pca10040 examples/blinky2
$( TINYGO) build -size short -o test.hex -target= microbit examples/echo
@$( MD5SUM) test.hex
$( TINYGO) build -size short -o test.hex -target= nrf52840-mdk examples/blinky1
@$( MD5SUM) test.hex
$( TINYGO) build -size short -o test.hex -target= pca10031 examples/blinky1
@$( MD5SUM) test.hex
$( TINYGO) build -size short -o test.hex -target= bluepill examples/blinky1
@$( MD5SUM) test.hex
$( TINYGO) build -size short -o test.hex -target= reelboard examples/blinky1
@$( MD5SUM) test.hex
$( TINYGO) build -size short -o test.hex -target= reelboard examples/blinky2
@$( MD5SUM) test.hex
$( TINYGO) build -size short -o test.hex -target= pca10056 examples/blinky1
@$( MD5SUM) test.hex
$( TINYGO) build -size short -o test.hex -target= pca10056 examples/blinky2
@$( MD5SUM) test.hex
$( TINYGO) build -size short -o test.hex -target= itsybitsy-m0 examples/blinky1
@$( MD5SUM) test.hex
$( TINYGO) build -size short -o test.hex -target= feather-m0 examples/blinky1
@$( MD5SUM) test.hex
$( TINYGO) build -size short -o test.hex -target= trinket-m0 examples/blinky1
@$( MD5SUM) test.hex
$( TINYGO) build -size short -o test.hex -target= circuitplay-express examples/blinky1
@$( MD5SUM) test.hex
$( TINYGO) build -size short -o test.hex -target= stm32f4disco examples/blinky1
@$( MD5SUM) test.hex
$( TINYGO) build -size short -o test.hex -target= stm32f4disco examples/blinky2
@$( MD5SUM) test.hex
$( TINYGO) build -size short -o test.hex -target= circuitplay-express examples/i2s
@$( MD5SUM) test.hex
$( TINYGO) build -size short -o test.gba -target= gameboy-advance examples/gba-display
@$( MD5SUM) test.gba
$( TINYGO) build -size short -o test.hex -target= itsybitsy-m4 examples/blinky1
@$( MD5SUM) test.hex
$( TINYGO) build -size short -o test.hex -target= nucleo-f103rb examples/blinky1
@$( MD5SUM) test.hex
$( TINYGO) build -size short -o test.hex -target= pinetime-devkit0 examples/blinky1
@$( MD5SUM) test.hex
i f n e q ( $( AVR ) , 0 )
$( TINYGO) build -size short -o test.hex -target= arduino examples/blinky1
@$( MD5SUM) test.hex
$( TINYGO) build -size short -o test.hex -target= digispark examples/blinky1
@$( MD5SUM) test.hex
e n d i f
i f n e q ( $( RISCV ) , 0 )
$( TINYGO) build -size short -o test.hex -target= hifive1b examples/blinky1
@$( MD5SUM) test.hex
e n d i f
$( TINYGO) build -o wasm.wasm -target= wasm examples/wasm/export
$( TINYGO) build -o wasm.wasm -target= wasm examples/wasm/main
release : tinygo gen -device
@mkdir -p build/release/tinygo/bin
@mkdir -p build/release/tinygo/lib/clang/include
@mkdir -p build/release/tinygo/lib/CMSIS/CMSIS
@mkdir -p build/release/tinygo/lib/compiler-rt/lib
@mkdir -p build/release/tinygo/lib/nrfx
@mkdir -p build/release/tinygo/pkg/armv6m-none-eabi
@mkdir -p build/release/tinygo/pkg/armv7m-none-eabi
@mkdir -p build/release/tinygo/pkg/armv7em-none-eabi
@echo copying source files
@cp -p build/tinygo$( EXE) build/release/tinygo/bin
@cp -p $( abspath $( CLANG_SRC) ) /lib/Headers/*.h build/release/tinygo/lib/clang/include
@cp -rp lib/CMSIS/CMSIS/Include build/release/tinygo/lib/CMSIS/CMSIS
@cp -rp lib/CMSIS/README.md build/release/tinygo/lib/CMSIS
@cp -rp lib/compiler-rt/lib/builtins build/release/tinygo/lib/compiler-rt/lib
@cp -rp lib/compiler-rt/LICENSE.TXT build/release/tinygo/lib/compiler-rt
@cp -rp lib/compiler-rt/README.txt build/release/tinygo/lib/compiler-rt
@cp -rp lib/nrfx/* build/release/tinygo/lib/nrfx
@cp -rp src build/release/tinygo/src
@cp -rp targets build/release/tinygo/targets
./build/tinygo build-builtins -target= armv6m-none-eabi -o build/release/tinygo/pkg/armv6m-none-eabi/compiler-rt.a
./build/tinygo build-builtins -target= armv7m-none-eabi -o build/release/tinygo/pkg/armv7m-none-eabi/compiler-rt.a
./build/tinygo build-builtins -target= armv7em-none-eabi -o build/release/tinygo/pkg/armv7em-none-eabi/compiler-rt.a
tar -czf build/release.tar.gz -C build/release tinygo