-
Notifications
You must be signed in to change notification settings - Fork 124
introduce zig cc cross-compilation setup for GitHub Actions and local development
#2535
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
jiridanek
wants to merge
22
commits into
main
Choose a base branch
from
jd_zig
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
699b709
see if I can mount /mnt on github actions too
jiridanek a754613
install zig
jiridanek 02e48bb
Add progress display for wget in Zig installation
jiridanek 8f99628
Configure sandbox to support cross-compilation with Zig for s390x-lin…
jiridanek 454049f
Fix Dockerfile.cpu mount check logic in `ubi9-python-3.12` runtime
jiridanek e5d2538
Modify sandbox to set `CC` and `CXX` as environment variables for Zig…
jiridanek d077f19
Simplify Zig paths in sandbox for cross-compilation environment varia…
jiridanek 48a4a52
Update target in sandbox for s390x to specify glibc version (2.34).
jiridanek 0c41a8a
Address deprecation warning and unsupported arg in s390x build process
jiridanek 2bf813d
Add wrapper scripts for Zig cross-compilation and adjust s390x sandbo…
jiridanek 728baa9
Add `zigcc` wrapper for s390x cross-compilation, including `Makefile`…
jiridanek 40b2c23
Update sandbox to correctly set `CC` and `CXX` for Zig, add cache bus…
jiridanek eea6333
Add `ninja-build` dependency for s390x and ppc64le in `ubi9-python-3.…
jiridanek 4a4c752
without zig, before 10 min
jiridanek 7ce40ed
Bump Zig to version 0.15.2 in Makefile
jiridanek 5cba801
with zig again
jiridanek ed37088
Remove `zigcc` wrapper script for s390x cross-compilation
jiridanek 9d4971e
Add dynamic target resolution for `zigcc` based on architecture
jiridanek b0cd250
Refactor `zigcc` to use environment-based architecture detection, enh…
jiridanek c441a6f
Clean up unused environment variables in `sandbox.py`.
jiridanek e51c1a0
Improve error messages in `zigcc.go` for clarity and update `ppc64le`…
jiridanek 1f0cac9
Enhance `zigcc` wrapper for improved cross-compilation: update `getTa…
jiridanek File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| .PHONY: build test clean | ||
|
|
||
| build: bin/zigcc | ||
|
|
||
| # always build for linux and the machine's native architecture | ||
| bin/zigcc: *.go go.mod | ||
| GOOS=linux go build -o $@ -ldflags="-s -w" -v ./... | ||
|
|
||
| test: | ||
| go test -v ./... | ||
|
|
||
| fmt: | ||
| go fmt ./... | ||
|
|
||
| vet: | ||
| go vet ./... | ||
|
|
||
| clean: | ||
| go clean | ||
| rm -f bin/* | ||
| rmdir bin |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| # zigcc | ||
|
|
||
| _Launcher for `zig cc`, `zig c++`, and related subcommands for more efficient cross-compilation_ | ||
|
|
||
| This script helps by using a native compiler binary to compile for the target architecture. | ||
| This means that the compiler then is running at the native speed. | ||
|
|
||
| ## Background | ||
|
|
||
| Cross-compilation means compiling for a different architecture than the one on which the compiler is running. | ||
| Specifically, it is when you're creating a workbench container image for say x86_64 on an arm64 machine such as an M-series MacBook. | ||
| Everything that's running in the container will run slower, because it has to run under qemu. | ||
|
|
||
| This slowdown is especially noticeable when compiling C/C++ code for IBM Power and Z, such as Python extension modules that don't have precompiled binaries for these architectures on PyPI. | ||
|
|
||
| ## Usage | ||
|
|
||
| ```commandline | ||
| gmake codeserver-ubi9-python-3.12 BUILD_ARCH=linux/s390x CONTAINER_BUILD_CACHE_ARGS= | ||
| ``` | ||
|
|
||
| This is about 50% faster than cross-compiling through `qemu-s390x-static` or `qemu-ppc64le-static`. | ||
|
|
||
| ## Cross-compilation overview | ||
|
|
||
| ### Qemu-user-static | ||
|
|
||
| Docker/Podman can perform cross-compilation using `qemu-user-static`. | ||
| The idea is to install the various `qemu-user` binaries as interpreters for foreign architecture binaries. | ||
| Launching such binary will then automatically run it under qemu interpreter. | ||
|
|
||
| Docker is uniquely suitable to run binaries like this, because container images bring all dependencies with them. | ||
|
|
||
| ### Traditional cross-compilation | ||
|
|
||
| For CMake, I can imagine an approach which involves installing a cross compiler and mounting arm64 docker image to provide arm64 environment with libraries. | ||
| <https://cmake.org/cmake/help/book/mastering-cmake/chapter/Cross%20Compiling%20With%20CMake.html> | ||
|
|
||
| ### Zig | ||
|
|
||
| https://zig.guide/working-with-c/zig-cc/ | ||
|
|
||
| The `zig cc` command bundles clang in a way that simplifies its usage for cross compilation, | ||
| <https://zig.news/kristoff/cross-compile-a-c-c-project-with-zig-3599> | ||
|
|
||
| #### Wrapper (zigcc.go) | ||
|
|
||
| We need a wrapper so that we can transform CLI arguments to work with `zig cc`. | ||
|
|
||
| The main problem is the `-Wl,D_FORTIFY_SOURCE=2` flag, because zig has limited handling for -Wl, and does not do -Wl,D correctly. | ||
|
|
||
| The wrapper should be written in a low-overhead language, like Go, or possibly Bash, certainly not Python. | ||
| The lower the overhead of the wrapper, the better, since the compiler is invoked many times during a typical build. | ||
|
|
||
| ### Debugging | ||
|
|
||
| To observe the effect of the wrapper, we can use `execsnoop` from `bcc-tools` to monitor the compiler invocations during a container build. | ||
|
|
||
| ```commandline | ||
| $ podman machine ssh | ||
| # bootc usr-overlay | ||
| # dnf install bcc-tools | ||
| # /usr/share/bcc/tools/execsnoop | ||
| ``` | ||
|
|
||
| ## Credits | ||
|
|
||
| This is inspired by <https://github.com/skupperproject/skupper-router/pull/1100> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| module zigcc | ||
|
|
||
| go 1.24 | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| FROM quay.io/centos/centos:stream9 | ||
|
|
||
| # Don't install the GCC compiler, we will inject our own CC | ||
| #RUN dnf install -y gcc | ||
|
|
||
| # Check CC is in fact injected | ||
| RUN /bin/bash <<'EOF' | ||
| set -Eeuxo pipefail | ||
| ls ${CC} | ||
| ${CC} --version | ||
| EOF | ||
|
|
||
| #RUN /mnt/zig clang -x c /dev/null --no-default-config -target s390x-unknown-linux5.10.0-gnu2.34.0 -mhard-float -fno-PIE -fPIC -gdwarf-4 -gdwarf32 -fno-lto -MD -MV -MF /root/.cache/zig/tmp/4ee4407ea328f5c8-null.o.d -fhosted -fno-omit-frame-pointer | ||
| #RUN /mnt/zig cc -target s390x-linux-gnu.2.34 --sysroot / -isystem /usr/include -L/usr/lib64 -isystem /usr/local/include -L/usr/local/lib64 -dM -E -x c /dev/null | ||
| RUN /mnt/zig -cc1 -triple x86_64-unknown-linux5.10.0-gnu2.34.0 -E -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name abi-note.S -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math | ||
|
|
||
| # Create a directory for the program | ||
| RUN mkdir /app | ||
|
|
||
| # Copy the C source code into the container | ||
| RUN sh -c 'cat > /app/hello.c' <<EOF | ||
| #include <stdio.h> | ||
| int main() { | ||
| printf("Hello, World!\\n"); | ||
| return 0; | ||
| } | ||
| EOF | ||
|
|
||
| # Compile the C program | ||
| RUN ${CC} /app/hello.c -o /app/hello | ||
| # Check it works | ||
| RUN /app/hello | ||
|
|
||
| # Set the entry point to run the compiled program | ||
| CMD ["/app/hello"] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| #! /usr/bin/env python3 | ||
|
|
||
| import argparse | ||
| import logging | ||
| import pathlib | ||
| import subprocess | ||
| import sys | ||
| from typing import cast | ||
|
|
||
| ROOT_DIR = pathlib.Path(__file__).parent.parent.parent.parent | ||
|
|
||
| logging.basicConfig(level=logging.INFO) | ||
| logging.root.name = pathlib.Path(__file__).name | ||
|
|
||
|
|
||
| class Args(argparse.Namespace): | ||
| platform: str | ||
|
|
||
|
|
||
| def main() -> int: | ||
| p = argparse.ArgumentParser() | ||
| p.add_argument("--platform", default="linux/amd64", help="Target platform for the build") | ||
| args = cast(Args, p.parse_args()) | ||
|
|
||
| dockerfile_path = ROOT_DIR / "scripts" / "zigcc" / "test" / "Dockerfile" | ||
| sandbox_script_path = ROOT_DIR / "scripts" / "sandbox.py" | ||
|
|
||
| return subprocess.call( | ||
| [sys.executable, str(sandbox_script_path), | ||
| "--dockerfile", str(dockerfile_path), | ||
| "--platform", args.platform, | ||
| "--", | ||
| "podman", "build", | ||
| "--no-cache", | ||
| "--platform", args.platform, | ||
| "-t", "hello-world-test", | ||
| # dockerfile path in podman command is required, Dockerfile is not copied to sandbox | ||
| "-f", str(dockerfile_path), | ||
| "{};"], | ||
| # sandbox.py assumes running from repo root | ||
| cwd=ROOT_DIR | ||
| ) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| sys.exit(main()) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Target a released Go toolchain
go 1.24is not available yet, so current builders (Go ≤1.22/1.23) will abort with “requires go >=1.24”. Drop to the latest released version you actually need (e.g. 1.22).📝 Committable suggestion
🤖 Prompt for AI Agents