Skip to content

Commit 75c2f7a

Browse files
committed
Build GHC with Zig CC and control glibc target version
The key change here is that the GHC/Stack build path now goes through Zig CC. Once Zig is the compiler driver in that path, we can explicitly choose which GNU libc version we target instead of inheriting whatever happens to be on the build host. On Linux, the Zig wrapper scripts accept ACTON_ZIG_GLIBC_VERSION and derive a -target of the form <host-arch>-linux-gnu.<major.minor> from zig env, so we do not hard-code CPU architecture while still pinning a glibc baseline. If an explicit target is already supplied, it takes precedence. macOS behavior is unchanged. The Makefile now defaults ACTON_ZIG_GLIBC_VERSION to 2.27 on Linux and exports it, and the dev guide documents the knob. In practice this gives us deliberate control over glibc compatibility for the compiler build products.
1 parent c2837c0 commit 75c2f7a

4 files changed

Lines changed: 140 additions & 5 deletions

File tree

Makefile

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ CXX=$(ZIG) c++
2222
export CC
2323
export CXX
2424

25+
# We use Zig CC & C++ for doing Stack / GHC builds
26+
STACK=CC="tools/zig-cc.sh" CXX="tools/zig-cxx.sh" CFLAGS= ACTON_REAL_LD="$(TD)/compiler/tools/zig-cc.sh" stack --with-gcc=$(TD)/compiler/tools/zig-cc.sh
27+
2528
# Determine which xargs we have. BSD xargs does not have --no-run-if-empty,
2629
# rather, it is the default behavior so the argument is superfluous. We check if
2730
# we are using GNU xargs by trying to run xargs --version and grep for 'GNU', if
@@ -65,6 +68,8 @@ endif
6568
# -- Linux ---------------------------------------------------------------------
6669
ifeq ($(shell uname -s),Linux)
6770
OS:=linux
71+
ACTON_ZIG_GLIBC_VERSION ?= 2.27
72+
export ACTON_ZIG_GLIBC_VERSION
6873
ifeq ($(shell uname -m),x86_64)
6974
ACTONC_TARGET := --target x86_64-linux-gnu.2.27
7075
else ifeq ($(shell uname -m),aarch64)
@@ -119,17 +124,15 @@ test-backend: $(BACKEND_TESTS)
119124
# /compiler ----------------------------------------------
120125
ACTONC_HS=$(wildcard compiler/lib/src/*.hs compiler/lib/src/*/*.hs compiler/acton/*.hs compiler/acton/*/*.hs)
121126
ACTONLSP_HS=$(wildcard compiler/lsp-server/*.hs)
122-
# NOTE: we're unsetting CC & CXX to avoid using zig cc & zig c++ for stack /
123-
# ghc, which doesn't seem to work properly
124127
dist/bin/acton: compiler/lib/package.yaml.in compiler/acton/package.yaml.in compiler/lsp-server/package.yaml.in compiler/stack.yaml $(ACTONC_HS) $(ACTONLSP_HS) version.mk
125128
mkdir -p dist/bin
126129
rm -f dist/bin/actonc
127130
cd compiler && sed 's,^version: BUILD_VERSION,version: "$(VERSION)",' < lib/package.yaml.in > lib/package.yaml
128-
cd compiler && unset CC && unset CXX && unset CFLAGS && stack build acton lsp-server-acton --dry-run 2>&1 | grep "Nothing to build" || \
131+
cd compiler && $(STACK) build acton lsp-server-acton --dry-run 2>&1 | grep "Nothing to build" || \
129132
(sed 's,^version: BUILD_VERSION,version: "$(VERSION_INFO)",' < acton/package.yaml.in > acton/package.yaml \
130133
&& sed 's,^version: BUILD_VERSION,version: "$(VERSION_INFO)",' < lsp-server/package.yaml.in > lsp-server/package.yaml \
131-
&& stack build acton lsp-server-acton $(STACK_OPTS) --ghc-options='-j4 $(ACTC_GHC_OPTS)')
132-
cd compiler && unset CC && unset CXX && unset CFLAGS && stack --local-bin-path=../dist/bin install acton lsp-server-acton
134+
&& $(STACK) build acton lsp-server-acton $(STACK_OPTS) --ghc-options='-j4 $(ACTC_GHC_OPTS)')
135+
cd compiler && $(STACK) --local-bin-path=../dist/bin install acton lsp-server-acton
133136
# Keep actonc as a symlink for compatibility
134137
ln -sf acton dist/bin/actonc
135138

compiler/tools/zig-cc.sh

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#!/usr/bin/env sh
2+
set -eu
3+
4+
SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
5+
ROOT_DIR="$(CDPATH= cd -- "$SCRIPT_DIR/../.." && pwd)"
6+
ZIG_BIN="$ROOT_DIR/dist/zig/zig"
7+
8+
if [ ! -x "$ZIG_BIN" ]; then
9+
echo "error: expected Zig at $ZIG_BIN; run 'make dist/zig' first" >&2
10+
exit 1
11+
fi
12+
13+
has_explicit_target=false
14+
expect_target_arg=false
15+
for arg in "$@"; do
16+
if [ "$expect_target_arg" = true ]; then
17+
has_explicit_target=true
18+
expect_target_arg=false
19+
continue
20+
fi
21+
22+
case "$arg" in
23+
-target)
24+
expect_target_arg=true
25+
;;
26+
-target=*)
27+
has_explicit_target=true
28+
;;
29+
--target)
30+
expect_target_arg=true
31+
;;
32+
--target=*)
33+
has_explicit_target=true
34+
;;
35+
esac
36+
done
37+
38+
if [ "$(uname -s 2>/dev/null || true)" = "Linux" ] \
39+
&& [ -n "${ACTON_ZIG_GLIBC_VERSION:-}" ] \
40+
&& [ "$has_explicit_target" = false ]; then
41+
zig_host_target="$("$ZIG_BIN" env 2>/dev/null | awk -F'"' '/\.target = "/ {print $2; exit}')"
42+
if [ -z "$zig_host_target" ]; then
43+
echo "error: failed to derive Zig host target from '$ZIG_BIN env'" >&2
44+
exit 1
45+
fi
46+
47+
case "$zig_host_target" in
48+
*-gnu*)
49+
;;
50+
*)
51+
echo "error: requested ACTON_ZIG_GLIBC_VERSION but host target '$zig_host_target' is not GNU libc based" >&2
52+
exit 1
53+
;;
54+
esac
55+
56+
zig_host_arch="${zig_host_target%%-*}"
57+
if [ -z "$zig_host_arch" ]; then
58+
echo "error: failed to derive host architecture from Zig target '$zig_host_target'" >&2
59+
exit 1
60+
fi
61+
62+
exec "$ZIG_BIN" cc -target "$zig_host_arch-linux-gnu.${ACTON_ZIG_GLIBC_VERSION}" "$@"
63+
fi
64+
65+
exec "$ZIG_BIN" cc "$@"

compiler/tools/zig-cxx.sh

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#!/usr/bin/env sh
2+
set -eu
3+
4+
SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
5+
ROOT_DIR="$(CDPATH= cd -- "$SCRIPT_DIR/../.." && pwd)"
6+
ZIG_BIN="$ROOT_DIR/dist/zig/zig"
7+
8+
if [ ! -x "$ZIG_BIN" ]; then
9+
echo "error: expected Zig at $ZIG_BIN; run 'make dist/zig' first" >&2
10+
exit 1
11+
fi
12+
13+
has_explicit_target=false
14+
expect_target_arg=false
15+
for arg in "$@"; do
16+
if [ "$expect_target_arg" = true ]; then
17+
has_explicit_target=true
18+
expect_target_arg=false
19+
continue
20+
fi
21+
22+
case "$arg" in
23+
-target)
24+
expect_target_arg=true
25+
;;
26+
-target=*)
27+
has_explicit_target=true
28+
;;
29+
--target)
30+
expect_target_arg=true
31+
;;
32+
--target=*)
33+
has_explicit_target=true
34+
;;
35+
esac
36+
done
37+
38+
if [ "$(uname -s 2>/dev/null || true)" = "Linux" ] \
39+
&& [ -n "${ACTON_ZIG_GLIBC_VERSION:-}" ] \
40+
&& [ "$has_explicit_target" = false ]; then
41+
zig_host_target="$("$ZIG_BIN" env 2>/dev/null | awk -F'"' '/\.target = "/ {print $2; exit}')"
42+
if [ -z "$zig_host_target" ]; then
43+
echo "error: failed to derive Zig host target from '$ZIG_BIN env'" >&2
44+
exit 1
45+
fi
46+
47+
case "$zig_host_target" in
48+
*-gnu*)
49+
;;
50+
*)
51+
echo "error: requested ACTON_ZIG_GLIBC_VERSION but host target '$zig_host_target' is not GNU libc based" >&2
52+
exit 1
53+
;;
54+
esac
55+
56+
zig_host_arch="${zig_host_target%%-*}"
57+
if [ -z "$zig_host_arch" ]; then
58+
echo "error: failed to derive host architecture from Zig target '$zig_host_target'" >&2
59+
exit 1
60+
fi
61+
62+
exec "$ZIG_BIN" c++ -target "$zig_host_arch-linux-gnu.${ACTON_ZIG_GLIBC_VERSION}" "$@"
63+
fi
64+
65+
exec "$ZIG_BIN" c++ "$@"

docs/acton-dev-guide/src/getting_started/build.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,7 @@ dist/bin/actonc path/to/file.act # compatibility alias
3131
## Caching and build knobs
3232

3333
- `ZIG_LOCAL_CACHE_DIR` controls Zig's cache location (defaults to `~/.cache/acton/zig-local-cache` when `HOME` is set).
34+
- Stack uses `compiler/tools/zig-cc.sh` / `compiler/tools/zig-cxx.sh` so GHC/Cabal go through `dist/zig/zig`.
35+
- On Linux, set `ACTON_ZIG_GLIBC_VERSION=<major.minor>` to force Zig CC/C++ wrappers to pass `-target <host-arch>-linux-gnu.<major.minor>` (for example `2.35`).
3436
- `BUILD_RELEASE=1 make` stamps release versions; default builds get a timestamped version suffix.
3537
- On Linux, the Makefile pins the default target to glibc 2.27 for compatibility.

0 commit comments

Comments
 (0)