-
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 20 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,27 @@ | ||
| # zigcc | ||
|
|
||
| _Launcher for `zig cc`, `zig c++`, and related subcommands for more efficient cross-compilation_ | ||
|
|
||
| ## 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 | ||
|
|
||
| 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> | ||
|
|
||
| ## 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,97 @@ | ||
| package main | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "os" | ||
| "path/filepath" | ||
| "strings" | ||
| "syscall" | ||
| ) | ||
|
|
||
| const ( | ||
| zig = "/mnt/zig" | ||
| ) | ||
|
|
||
| func getTarget() string { | ||
| var arch string | ||
| switch os.Getenv("ZIGCC_ARCH") { | ||
| case "amd64": | ||
| arch = "x86_64" | ||
| case "arm64": | ||
| arch = "aarch64" | ||
| case "ppc64le": | ||
| arch = "ppc64le" | ||
| case "s390x": | ||
| arch = "s390x" | ||
| default: | ||
| fmt.Fprintf(os.Stderr, "Error: unknown architecture: %s\n", os.Getenv("ZIGCC_ARCH")) | ||
| os.Exit(1) | ||
| } | ||
|
|
||
| // target glibc 2.28 or newer (supports FORTIFY_SOURCE) | ||
| return arch + "-linux-gnu.2.34" | ||
| } | ||
|
|
||
| func processArg0(arg0 string) (string, error) { | ||
| switch arg0 { | ||
| case "cc": | ||
| return "cc", nil | ||
| case "c++": | ||
| return "c++", nil | ||
|
|
||
| // `llvm-` prefix so that CMake finds it | ||
| // https://gitlab.kitware.com/cmake/cmake/-/issues/23554 | ||
| // https://gitlab.kitware.com/cmake/cmake/-/issues/18712#note_1006035 | ||
| // ../../libtool: line 1887: /mnt/ar: No such file or directory | ||
| case "ar", "llvm-ar": | ||
| return "ar", nil | ||
| case "ranlib", "llvm-ranlib": | ||
| return "ranlib", nil | ||
| case "strip", "llvm-strip": | ||
| return "strip", nil | ||
|
|
||
| default: | ||
| return "", fmt.Errorf("unknown wrapper name: %s", arg0) | ||
| } | ||
| } | ||
|
|
||
| func processArgs(args []string) []string { | ||
| newArgs := make([]string, 0, len(args)) | ||
| for _, arg := range args { | ||
| // deal with -Wp,-D_FORTIFY_SOURCE=2: | ||
| // this comes in https://github.com/giampaolo/psutil/blob/master/setup.py#L254 | ||
| // build defaults to using python's flags and they are the RHEL fortified ones | ||
| if strings.HasPrefix(arg, "-Wp,") { | ||
| newArgs = append(newArgs, strings.Split(arg, ",")[1:]...) | ||
| } else { | ||
| newArgs = append(newArgs, arg) | ||
| } | ||
| } | ||
| return newArgs | ||
| } | ||
|
|
||
| func main() { | ||
| arg0 := filepath.Base(os.Args[0]) | ||
| subcommand, err := processArg0(arg0) | ||
| if err != nil { | ||
| fmt.Fprintf(os.Stderr, "Error: %v\n", err) | ||
| os.Exit(1) | ||
| } | ||
|
|
||
| target := getTarget() | ||
|
|
||
| newArgs := []string{ | ||
| zig, | ||
| subcommand, | ||
| } | ||
| if subcommand == "cc" || subcommand == "c++" { | ||
| newArgs = append(newArgs, "-target", target) | ||
| } | ||
| newArgs = append(newArgs, processArgs(os.Args[1:])...) | ||
|
|
||
| env := os.Environ() | ||
| if err := syscall.Exec(newArgs[0], newArgs, env); err != nil { | ||
| fmt.Fprintf(os.Stderr, "Error executing zig: %v\n", err) | ||
| os.Exit(1) | ||
| } | ||
| } |
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 @@ | ||
| package main | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "reflect" | ||
| "testing" | ||
| ) | ||
|
|
||
| func TestProcessWp(t *testing.T) { | ||
| args := []string{"-Wp,-D_FORTIFY_SOURCE=2"} | ||
| newArgs := processArgs(args) | ||
| if !reflect.DeepEqual(newArgs, []string{"-D_FORTIFY_SOURCE=2"}) { | ||
| t.Fatalf("expected -DFOO=bar, got %v", newArgs) | ||
| } | ||
| for _, tc := range []struct { | ||
| args []string | ||
| expected []string | ||
| }{ | ||
| { | ||
| args: []string{"-Wp,-D_FORTIFY_SOURCE=2"}, | ||
| expected: []string{"-D_FORTIFY_SOURCE=2"}, | ||
| }, | ||
| { | ||
| args: []string{"-Wp,-DNDEBUG,-D_FORTIFY_SOURCE=2"}, | ||
| expected: []string{"-DNDEBUG", "-D_FORTIFY_SOURCE=2"}, | ||
| }, | ||
| } { | ||
| t.Run(fmt.Sprint(tc.args), func(t *testing.T) { | ||
| newArgs := processArgs(tc.args) | ||
| if !reflect.DeepEqual(newArgs, tc.expected) { | ||
| t.Fatalf("expected %#v, got %#v", tc.expected, newArgs) | ||
| } | ||
| }) | ||
| } | ||
| } |
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