Instructions to cross-compile from macOS High Sierra to Raspberry Pi 3 Model B armv7l against musl libc
brew install FiloSottile/musl-cross/musl-cross --without-x86_64 --with-arm-hf
This will take some time (my installation took ~45 minutes), but afterwards, a number of compilers for musl will now be in /usr/local/bin. Specifically, the one that we're concerned with is
arm-linux-musleabihf-gcc which will replace the regular
gcc when we call
go build or
vgo build to generate a binary.
Create go code inclusive of cgo (i.e. import "C")
To compile a dynamic binary against musl libc for Rpi use the following build command:
env CC=arm-linux-musleabihf-gcc GOOS=linux GOARCH=arm GOARM=7 CGO_ENABLED=1 vgo build -o some_name /some/path/to/main.go
- To compile a static binary against musl libc for Rpi use the following build command:
env CC=arm-linux-musleabihf-gcc GOOS=linux GOARCH=arm GOARM=7 CGO_ENABLED=1 vgo build -o some_name --ldflags '-linkmode external -extldflags "-static"' /some/path/to/main.go
vgo build works, too!)
The difference in size between these two will be minimal, unlike when using glibc where there is a greater delta between dynamic binaries linking to glibc directly and static.
Also, if you fail to include
CGO_ENABLED=1 in the build command, compilation will fail. The compiler will ignore any files containing the
import "C" directive and an error on compilation will come up stating that go symbols are undefined. This bit was confusing and threw me off. I couldn't figure out why the compiler was complaining a go func was undefined. I ran the build using the
-x switch and realized that the particular file importing C was ignored. To ensure that these go files with cgo in them are included, you must explicitly tell the build command to enable cgo.
Copy or move binary output to Rpi via
Execute binary on Rpi. Ta da! It works! And your cgo code will call C using musl libc.