@@ -2,14 +2,27 @@ ARG BASE_VARIANT=alpine
22ARG GO_VERSION=1.17
33ARG XX_VERSION=1.1.0
44
5- ARG LIBGIT2_IMG=ghcr.io/fluxcd/golang-with-libgit2
6- ARG LIBGIT2_TAG=libgit2-1.1.1-4
5+ ARG LIBGIT2_IMG
6+ ARG LIBGIT2_TAG
77
8- FROM --platform=linux/amd64 ${LIBGIT2_IMG}:${LIBGIT2_TAG} as build-amd64
9- FROM --platform=linux/arm64 ${LIBGIT2_IMG}:${LIBGIT2_TAG} as build-arm64
10- FROM --platform=linux/arm/v7 ${LIBGIT2_IMG}:${LIBGIT2_TAG} as build-armv7
8+ FROM ${LIBGIT2_IMG}:${LIBGIT2_TAG} AS libgit2-libs
119
12- FROM --platform=$BUILDPLATFORM build-$TARGETARCH$TARGETVARIANT AS build
10+ FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx
11+
12+ FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-${BASE_VARIANT} as gostable
13+
14+ FROM gostable AS go-linux
15+
16+ # Build-base consists of build platform dependencies and xx.
17+ # These will be used at current arch to yield execute the cross compilations.
18+ FROM go-${TARGETOS} AS build-base
19+
20+ RUN apk add --no-cache clang lld pkgconfig
21+
22+ COPY --from=xx / /
23+
24+ # build-go-mod can still be cached at build platform architecture.
25+ FROM build-base as build-go-mod
1326
1427# Configure workspace
1528WORKDIR /workspace
@@ -24,26 +37,55 @@ COPY go.sum go.sum
2437# Cache modules
2538RUN go mod download
2639
27- RUN apk add clang lld pkgconfig ca-certificates
40+ # The musl-tool-chain layer is an adhoc solution
41+ # for the problem in which xx gets confused during compilation
42+ # and a) looks for gold linker and then b) cannot find musl's dynamic linker.
43+ FROM --platform=$BUILDPLATFORM alpine as musl-tool-chain
44+
45+ COPY --from=xx / /
46+
47+ RUN apk add bash curl tar
48+
49+ WORKDIR /workspace
50+ COPY hack/download-musl.sh .
2851
29- # Build the binary
30- ENV CGO_ENABLED=1
3152ARG TARGETPLATFORM
53+ ARG TARGETARCH
54+ RUN ROOT_DIR="$(pwd)" TARGET_ARCH="$(xx-info alpine-arch)" ENV_FILE=true \
55+ ./download-musl.sh
3256
33- RUN xx-apk add --no-cache \
34- musl-dev gcc lld binutils-gold
57+ # Build stage install per target platform
58+ # dependency and effectively cross compile the application.
59+ FROM build-go-mod as build
60+
61+ ARG TARGETPLATFORM
62+
63+ COPY --from=libgit2-libs /usr/local/ /usr/local/
64+
65+ # Some dependencies have to installed
66+ # for the target platform: https://github.com/tonistiigi/xx#go--cgo
67+ RUN xx-apk add musl-dev gcc lld
68+
69+ WORKDIR /workspace
70+
71+ # Copy source code
72+ COPY main.go main.go
73+ COPY controllers/ controllers/
74+ COPY pkg/ pkg/
75+ COPY internal/ internal/
76+
77+ COPY --from=musl-tool-chain /workspace/build /workspace/build
78+
79+ ARG TARGETPLATFORM
80+ ARG TARGETARCH
81+ ENV CGO_ENABLED=1
3582
36- # Performance related changes:
37- # - Use read-only bind instead of copying go source files.
38- # - Cache go packages.
39- RUN --mount=target=. \
40- --mount=type=cache,target=/root/.cache/go-build \
41- --mount=type=cache,target=/go/pkg \
42- export LIBRARY_PATH="/usr/local/$(xx-info triple)/lib:/usr/local/$(xx-info triple)/lib64:${LIBRARY_PATH}" && \
83+ # Instead of using xx-go, (cross) compile with vanilla go leveraging musl tool chain.
84+ RUN export $(cat build/musl/$(xx-info alpine-arch).env | xargs) && \
85+ export LIBRARY_PATH="/usr/local/$(xx-info triple):/usr/local/$(xx-info triple)/lib64" && \
4386 export PKG_CONFIG_PATH="/usr/local/$(xx-info triple)/lib/pkgconfig:/usr/local/$(xx-info triple)/lib64/pkgconfig" && \
44- export FLAGS="$(pkg-config --static --libs --cflags libssh2 openssl libgit2)" && \
45- CGO_LDFLAGS="${FLAGS} -static" \
46- xx-go build \
87+ export CGO_LDFLAGS="$(pkg-config --static --libs --cflags libssh2 openssl libgit2) -static" && \
88+ GOARCH=$TARGETARCH go build \
4789 -ldflags "-s -w" \
4890 -tags 'netgo,osusergo,static_build' \
4991 -o /source-controller -trimpath main.go;
0 commit comments