mirror of
https://github.com/tonistiigi/xx
synced 2025-12-24 12:47:51 +08:00
xx-go: zig support
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
This commit is contained in:
22
README.md
22
README.md
@@ -342,6 +342,28 @@ RUN go build -o hello hello.go && \
|
||||
xx-verify hello
|
||||
```
|
||||
|
||||
`xx-go` can also drive [Zig](https://ziglang.org/) as the underlying C
|
||||
toolchain for CGo builds. This can be useful when you want a single
|
||||
cross-compiling toolchain that works across multiple platforms, or when you
|
||||
already rely on Zig in your build pipeline.
|
||||
|
||||
Zig support is **opt-in** and is enabled by setting the `XX_GO_PREFER_C_COMPILER`
|
||||
environment variable to `zig`. When this variable is set and the `zig` binary
|
||||
is available in `PATH`, `xx-go` will configure CGo to use Zig as the C compiler
|
||||
for the current target.
|
||||
|
||||
```dockerfile
|
||||
FROM --platform=$BUILDPLATFORM golang:alpine
|
||||
RUN apk add zig
|
||||
# ...
|
||||
ARG TARGETPLATFORM
|
||||
RUN xx-apk add musl-dev
|
||||
ENV CGO_ENABLED=1
|
||||
ENV XX_GO_PREFER_C_COMPILER=zig
|
||||
RUN xx-go build -o hello ./hello.go && \
|
||||
xx-verify hello
|
||||
```
|
||||
|
||||
## Rust
|
||||
|
||||
Building Rust can be achieved with the `xx-cargo` wrapper that automatically
|
||||
|
||||
@@ -511,6 +511,96 @@ testHelloCGO() {
|
||||
assert_output --partial "PKG_CONFIG=$(xx-info triple)-pkg-config"
|
||||
}
|
||||
|
||||
testHelloCGOZig() {
|
||||
if ! supportZig; then
|
||||
skip "Zig not supported"
|
||||
fi
|
||||
export CGO_ENABLED=1
|
||||
export XX_GO_PREFER_C_COMPILER=zig
|
||||
add zig
|
||||
run xx-go build -x -o /tmp/a.out ./fixtures/hello_cgo.go
|
||||
assert_success
|
||||
run xx-verify /tmp/a.out
|
||||
assert_success
|
||||
if ! xx-info is-cross; then
|
||||
run /tmp/a.out
|
||||
assert_success
|
||||
assert_output "hello cgo"
|
||||
fi
|
||||
}
|
||||
|
||||
@test "native-hellocgo-zig" {
|
||||
unset TARGETARCH
|
||||
testHelloCGOZig
|
||||
}
|
||||
|
||||
@test "amd64-hellocgo-zig" {
|
||||
export TARGETARCH=amd64
|
||||
testHelloCGOZig
|
||||
}
|
||||
|
||||
@test "arm64-hellocgo-zig" {
|
||||
export TARGETARCH=arm64
|
||||
testHelloCGOZig
|
||||
}
|
||||
|
||||
@test "arm-hellocgo-zig" {
|
||||
export TARGETARCH=arm
|
||||
testHelloCGOZig
|
||||
}
|
||||
|
||||
@test "ppc64le-hellocgo-zig" {
|
||||
export TARGETARCH=ppc64le
|
||||
testHelloCGOZig
|
||||
}
|
||||
|
||||
@test "riscv64-hellocgo-zig" {
|
||||
if ! supportRiscVCGo; then
|
||||
skip "RISC-V CGO not supported"
|
||||
fi
|
||||
export TARGETARCH=riscv64
|
||||
testHelloCGOZig
|
||||
}
|
||||
|
||||
@test "loong64-hellocgo-zig" {
|
||||
if ! supportLoong64CGo; then
|
||||
skip "LOONGARCH64 not supported"
|
||||
fi
|
||||
if [ -f /etc/alpine-release ]; then
|
||||
# FIXME: loong64-hellocgo issue on alpine < 3.21
|
||||
# ld.lld: error: unknown emulation: elf64loongarch
|
||||
# ld.lld: error: /loongarch64-alpine-linux-musl/usr/lib/gcc/loongarch64-alpine-linux-musl/14.2.0/crtbeginS.o:(.text+0x0): unknown relocation (102) against symbol
|
||||
# error: unknown target triple 'loongarch64-alpine-linux-musl', please use -triple or -arch
|
||||
alpineRelease=$(cat /etc/alpine-release)
|
||||
if ! grep PRETTY_NAME /etc/os-release | cut -d '=' -f 2 | tr -d '"' | grep -q "edge$" || [ "$(semver compare "$alpineRelease" "3.21.0")" -lt 0 ]; then
|
||||
skip
|
||||
fi
|
||||
fi
|
||||
export TARGETARCH=loong64
|
||||
testHelloCGOZig
|
||||
}
|
||||
|
||||
@test "386-hellocgo-zig" {
|
||||
export TARGETARCH=386
|
||||
testHelloCGOZig
|
||||
}
|
||||
|
||||
@test "arm64-cgoenv-zig" {
|
||||
if ! supportZig; then
|
||||
skip "Zig not supported"
|
||||
fi
|
||||
export TARGETARCH=arm64
|
||||
export XX_GO_PREFER_C_COMPILER=zig
|
||||
export CGO_ENABLED=1
|
||||
|
||||
add zig
|
||||
# single/double quotes changed in between go versions
|
||||
run sh -c "xx-go env | sed 's/[\"'\'']//g'"
|
||||
assert_success
|
||||
assert_output --partial "CC=zig cc -target"
|
||||
assert_output --partial "CXX=zig c++ -target"
|
||||
}
|
||||
|
||||
@test "wrap-unwrap" {
|
||||
target="arm64"
|
||||
if [ "$(xx-info arch)" = "arm64" ]; then target="amd64"; fi
|
||||
@@ -535,3 +625,10 @@ testHelloCGO() {
|
||||
assert_success
|
||||
assert_output "$nativeArch"
|
||||
}
|
||||
|
||||
@test "clean-packages" {
|
||||
if ! supportZig; then
|
||||
skip "Zig not supported"
|
||||
fi
|
||||
del zig
|
||||
}
|
||||
|
||||
@@ -142,3 +142,7 @@ supportLoong64CGo() {
|
||||
supportRC() {
|
||||
command -v llvm-rc >/dev/null 2>&1
|
||||
}
|
||||
|
||||
supportZig() {
|
||||
[ -f /etc/alpine-release ] && versionGTE "$(xx-info os-version | cut -d'.' -f1-2)" "3.20"
|
||||
}
|
||||
|
||||
150
src/xx-go
150
src/xx-go
@@ -6,6 +6,9 @@ for l in $(xx-info env); do
|
||||
export "${l?}"
|
||||
done
|
||||
|
||||
: "${XX_GO_PREFER_C_COMPILER=clang}"
|
||||
: "${XX_ZIG_TRIPLE=unknown-unknown-none}"
|
||||
|
||||
export GOOS="${TARGETOS}"
|
||||
export GOARCH="${TARGETARCH}"
|
||||
|
||||
@@ -24,6 +27,28 @@ case "$TARGETARCH" in
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
if [ "$XX_LIBC" = "musl" ]; then
|
||||
XX_ZIG_TRIPLE="x86_64-linux-musl"
|
||||
else
|
||||
XX_ZIG_TRIPLE="x86_64-linux-gnu"
|
||||
fi
|
||||
if [ "$TARGETOS" = "darwin" ]; then
|
||||
XX_ZIG_TRIPLE="x86_64-macos-none"
|
||||
elif [ "$TARGETOS" = "windows" ]; then
|
||||
XX_ZIG_TRIPLE="x86_64-windows-gnu"
|
||||
fi
|
||||
;;
|
||||
"arm64")
|
||||
if [ "$XX_LIBC" = "musl" ]; then
|
||||
XX_ZIG_TRIPLE="aarch64-linux-musl"
|
||||
else
|
||||
XX_ZIG_TRIPLE="aarch64-linux-gnu"
|
||||
fi
|
||||
if [ "$TARGETOS" = "darwin" ]; then
|
||||
XX_ZIG_TRIPLE="aarch64-macos-none"
|
||||
elif [ "$TARGETOS" = "windows" ]; then
|
||||
XX_ZIG_TRIPLE="aarch64-windows-gnu"
|
||||
fi
|
||||
;;
|
||||
"arm")
|
||||
if [ -z "$GOARM" ]; then
|
||||
@@ -39,6 +64,94 @@ case "$TARGETARCH" in
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
if [ "$XX_LIBC" = "musl" ]; then
|
||||
XX_ZIG_TRIPLE="arm-linux-musleabihf"
|
||||
else
|
||||
XX_ZIG_TRIPLE="arm-linux-gnueabihf"
|
||||
fi
|
||||
if [ "$TARGETVARIANT" = "v6" ]; then
|
||||
if [ "$XX_LIBC" = "musl" ]; then
|
||||
XX_ZIG_TRIPLE="arm-linux-musleabi"
|
||||
else
|
||||
XX_ZIG_TRIPLE="arm-linux-gnueabi"
|
||||
fi
|
||||
fi
|
||||
if [ "$TARGETVARIANT" = "v5" ]; then
|
||||
if [ "$XX_LIBC" = "musl" ]; then
|
||||
XX_ZIG_TRIPLE="arm-linux-musleabi"
|
||||
else
|
||||
XX_ZIG_TRIPLE="arm-linux-gnueabi"
|
||||
fi
|
||||
fi
|
||||
if [ "$TARGETOS" = "windows" ]; then
|
||||
XX_ZIG_TRIPLE="arm-windows-gnu"
|
||||
fi
|
||||
;;
|
||||
"riscv64")
|
||||
if [ "$XX_LIBC" = "musl" ]; then
|
||||
XX_ZIG_TRIPLE="riscv64-linux-musl"
|
||||
else
|
||||
XX_ZIG_TRIPLE="riscv64-linux-gnu"
|
||||
fi
|
||||
;;
|
||||
"ppc64le")
|
||||
if [ "$XX_LIBC" = "musl" ]; then
|
||||
XX_ZIG_TRIPLE="powerpc64le-linux-musl"
|
||||
else
|
||||
XX_ZIG_TRIPLE="powerpc64le-linux-gnu"
|
||||
fi
|
||||
;;
|
||||
"s390x")
|
||||
if [ "$XX_LIBC" = "musl" ]; then
|
||||
XX_ZIG_TRIPLE="s390x-linux-musl"
|
||||
else
|
||||
XX_ZIG_TRIPLE="s390x-linux-gnu"
|
||||
fi
|
||||
;;
|
||||
"loong64")
|
||||
if [ "$XX_LIBC" = "musl" ]; then
|
||||
XX_ZIG_TRIPLE="loongarch64-linux-musl"
|
||||
else
|
||||
XX_ZIG_TRIPLE="loongarch64-linux-gnu"
|
||||
fi
|
||||
;;
|
||||
"386")
|
||||
if [ "$XX_LIBC" = "musl" ]; then
|
||||
XX_ZIG_TRIPLE="x86-linux-musl"
|
||||
else
|
||||
XX_ZIG_TRIPLE="x86-linux-gnu"
|
||||
fi
|
||||
if [ "$TARGETOS" = "windows" ]; then
|
||||
XX_ZIG_TRIPLE="x86-windows-gnu"
|
||||
fi
|
||||
;;
|
||||
"mips")
|
||||
if [ "$XX_LIBC" = "musl" ]; then
|
||||
XX_ZIG_TRIPLE="mips-linux-musl"
|
||||
else
|
||||
XX_ZIG_TRIPLE="mips-linux-gnueabi"
|
||||
fi
|
||||
;;
|
||||
"mipsle")
|
||||
if [ "$XX_LIBC" = "musl" ]; then
|
||||
XX_ZIG_TRIPLE="mipsel-linux-musl"
|
||||
else
|
||||
XX_ZIG_TRIPLE="mipsel-linux-gnueabi"
|
||||
fi
|
||||
;;
|
||||
"mips64")
|
||||
if [ "$XX_LIBC" = "musl" ]; then
|
||||
XX_ZIG_TRIPLE="mips64-linux-musl"
|
||||
else
|
||||
XX_ZIG_TRIPLE="mips64-linux-gnuabi64"
|
||||
fi
|
||||
;;
|
||||
"mips64le")
|
||||
if [ "$XX_LIBC" = "musl" ]; then
|
||||
XX_ZIG_TRIPLE="mips64el-linux-musl"
|
||||
else
|
||||
XX_ZIG_TRIPLE="mips64el-linux-gnuabi64"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -76,26 +189,33 @@ if command -v "$XX_TRIPLE-g++" >/dev/null 2>/dev/null; then
|
||||
cxx_set=1
|
||||
fi
|
||||
|
||||
if command -v clang >/dev/null 2>/dev/null; then
|
||||
triple=$(xx-clang --print-target-triple || true)
|
||||
if [ -n "$triple" ]; then
|
||||
export CC="$triple-clang"
|
||||
export CXX="$triple-clang++"
|
||||
if [ "$XX_GO_PREFER_C_COMPILER" = "clang" ]; then
|
||||
if command -v clang >/dev/null 2>/dev/null; then
|
||||
triple=$(xx-clang --print-target-triple || true)
|
||||
if [ -n "$triple" ]; then
|
||||
export CC="$triple-clang"
|
||||
export CXX="$triple-clang++"
|
||||
c_set=1
|
||||
cxx_set=1
|
||||
fi
|
||||
fi
|
||||
if command -v "$XX_TRIPLE-ar" >/dev/null 2>/dev/null; then
|
||||
export AR="$XX_TRIPLE-ar"
|
||||
ar_set=1
|
||||
fi
|
||||
if command -v "$XX_TRIPLE-pkg-config" >/dev/null 2>/dev/null; then
|
||||
export PKG_CONFIG="$XX_TRIPLE-pkg-config"
|
||||
pkgconfig_set=1
|
||||
fi
|
||||
elif [ "$XX_GO_PREFER_C_COMPILER" = "zig" ]; then
|
||||
if command -v "zig" >/dev/null 2>/dev/null; then
|
||||
export CC="zig cc -target $XX_ZIG_TRIPLE"
|
||||
c_set=1
|
||||
export CXX="zig c++ -target $XX_ZIG_TRIPLE"
|
||||
cxx_set=1
|
||||
fi
|
||||
fi
|
||||
|
||||
if command -v "$XX_TRIPLE-ar" >/dev/null 2>/dev/null; then
|
||||
export AR="$XX_TRIPLE-ar"
|
||||
ar_set=1
|
||||
fi
|
||||
|
||||
if command -v "$XX_TRIPLE-pkg-config" >/dev/null 2>/dev/null; then
|
||||
export PKG_CONFIG="$XX_TRIPLE-pkg-config"
|
||||
pkgconfig_set=1
|
||||
fi
|
||||
|
||||
if [ -z "$GOBIN" ] && [ -n "$GOPATH" ] && [ -n "$GOARCH" ] && [ -n "$GOOS" ]; then
|
||||
export PATH="${GOPATH}/bin/${GOOS}_${GOARCH}:${PATH}"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user