1

For one of my Github projects I'm releasing multi-arch container images for linux/amd64 and linux/arm64. One stage builds a Go fully standalone binary, but it absolutely needs CGO to do so. For the moment, this stage thus cannot be always running as a runner "native" stage, such as amd64 on Github. Instead, it is painfully slow due to the QEMU arm64 emulation on amd64 -- albeit part of the slowness is due to the free Github runners for public projects. On my personal 10yr-old i7 things go by much faster.

Typically, the first search engine result when searching for installing a cross-compiling tool chain on alpine with musl support is either Cross-compiling with musl Toolchains (ariya.io) or musl.cc itself. The big issue with this "solution" is that first, the packages from musl.cc are terribly outdated (11/2021), and second, are not a version pinnable package source either. Not least on a public project offering container images musl.cc is an absolute no-go. (Discussions about pinning issues with Alpine in general aside.)

Another high ranking hit is xentec/setup-cross-cc.sh, which I simply cannot get to work inside a Docker Alpine container, due to still unresolved does errors. I've seen the issues and the solution is allegedly a newer Docker, runc, and libseccomp -- which I all fulfill on my host system. So this obviously still isn't fixed correctly or has regressed.

I'm also aware of Golang cross compiling with CGO inside docker image -- without any helpful answer. In fact, some of the answers while on the surface looking legit are in their contents not really matching what has been questioned.

How can I build a cross-compiler toolchain of gcc + friends for Alpine-musl inside a (recent) Alpine Docker container?

Please note that I don't want to build (cross) apk Alpine packages. My ultimate Goal is to build Go binaries using cgo.

TheDiveO
  • 2,183
  • 2
  • 19
  • 38

1 Answers1

2

Happens that there actually already is a neat and clean solution: @tonistiigi/xx. However, this doesn't use gcc but clang/llvm instead. As it turns out, gcc and multi-arch are somewhat not best friends, as gcc comes from a time where the expectation was to have a single gcc that either builds for its host platform, or cross-compiles to exactly one other platform. But while this answer doesn't solve my original question, it solves my underlying need for cross-compilation in a different, but much easier way.

xx's documentation explicitly mentions Alpine and shows examples, not least for using Go / Cgo. See also my (canonical) answer here on SO, so I'm not duplicating everything here.

The gist is as follows:

FROM --platform=$BUILDPLATFORM tonistiigi/xx AS xx

FROM --platform=$BUILDPLATFORM golang:alpine
RUN apk add clang lld
COPY --from=xx / /
ARG TARGETPLATFORM
RUN xx-apk add musl-dev gcc
ENV CGO_ENABLED=1
RUN xx-go build -o hello ./hello.go && \
    xx-verify hello
TheDiveO
  • 2,183
  • 2
  • 19
  • 38