1
Go to file
2022-02-05 11:16:16 +02:00
bin wip: go repositories 2021-07-21 14:59:33 +03:00
ci restructure tests for merging 2022-02-05 06:12:41 +02:00
rules move go_binary_override to rules_go 2021-11-07 12:39:34 +02:00
test/go move golang tests to its own directory 2022-02-03 15:24:26 +02:00
toolchain add @zig_sdk//:<os>_<arch>_platform values 2022-02-03 14:24:26 +02:00
.bazelrc [bazelrc] build --compilation_mode=opt 2021-12-15 15:05:12 +02:00
.bazelversion bump bazel version 2021-12-09 10:23:46 +02:00
.build.yml install binfmt-support 2022-02-05 05:58:24 +02:00
.envrc .envrc: remove bashism 2022-02-04 11:16:52 +02:00
.gitignore download a verified version of bazelisk 2021-09-06 17:02:17 +03:00
BUILD rename/fix the package 2022-01-28 15:57:22 +02:00
go.mod rename/fix the package 2022-01-28 15:57:22 +02:00
go.sum remove sqlite from dependencies 2022-01-28 15:50:33 +02:00
LICENSE add license 2021-06-11 06:16:23 +03:00
README.md [readme] more examples 2022-02-05 11:16:16 +02:00
release [release] update version regexp to allow -rc 2021-12-13 03:29:10 +02:00
relnotes.awk add release note updater 2021-10-18 15:46:05 +03:00
repositories.bzl rename/fix the package 2022-01-28 15:57:22 +02:00
WORKSPACE upgrade rules_go 2022-02-05 11:07:58 +02:00

builds.sr.ht status

Bazel zig cc toolchain

This is a C/C++ toolchain that can (cross-)compile C/C++ programs. It contains clang-13, musl, glibc (versions 2-2.34, selectable), all in a ~40MB package. Read here about zig-cc; the rest of the README will present how to use this toolchain from Bazel.

Usage

Add this to your WORKSPACE:

BAZEL_ZIG_CC_VERSION = "v0.4.4"

http_archive(
    name = "bazel-zig-cc",
    sha256 = "ad6384b4d16ebb3e5047df6548a195e598346da84e5f320250beb9198705ac81",
    strip_prefix = "bazel-zig-cc-{}".format(BAZEL_ZIG_CC_VERSION),
    urls = ["https://git.sr.ht/~motiejus/bazel-zig-cc/archive/{}.tar.gz".format(BAZEL_ZIG_CC_VERSION)],
)

load("@bazel-zig-cc//toolchain:defs.bzl", zig_register_toolchains = "register_toolchains")

zig_register_toolchains(register = [
    "x86_64-linux-gnu.2.28",
    "x86_64-macos-gnu",
])

And this to .bazelrc:

build --incompatible_enable_cc_toolchain_resolution

The snippet above will download the zig toolchain and register it for the following platforms:

  • x86_64-linux-gnu.2.28 for ["@platforms//os:linux", "@platforms//cpu:x86_64"].
  • x86_64-macos-gnu for ["@platforms//os:macos", "@platforms//cpu:x86_64"].

Note that both Go and Bazel naming schemes are accepted. For convenience with Go, the following Go-style toolchain aliases are created:

Bazel (zig) name Go name
x86_64 amd64
aarch64 arm64
macos darwin

For example, the toolchain linux_amd64_gnu.2.28 is aliased to x86_64-linux-gnu.2.28. To find out which toolchains can be registered or used, run:

$ bazel query @zig_sdk//... | sed -En '/.*_toolchain$/ s/.*:(.*)_toolchain$/\1/p'

Specifying non-default toolchains (and not registering at all)

You may explicitly request Bazel to use a specific toolchain, even though one is registered using --extra_toolchains <toolchain> flag. For example, if you wish to compile a specific binary (or run tests) using musl on linux/amd64, you may specify:

--extra_toolchains @zig_sdk//:linux_amd64_musl_toolchain

As an extension to this, you may not register the toolchains at all:

zig_register_toolchains()

In that case, you will need to specify the --extra_toolchains <toolchain> command-line argument. Otherwise Bazel will use the default one -- the host toolchain.

UBSAN and "SIGILL: Illegal Instruction"

zig cc differs from "mainstream" compilers by enabling UBSAN by default. Which means your program may compile successfully and crash with:

SIGILL: illegal instruction

This is by design: it encourages program authors to fix the undefined behavior. There are many ways to find the undefined behavior.

Known Issues In bazel-zig-cc

These are the things you may stumble into when using bazel-zig-cc. I am unlikely to implement them any time soon, but patches implementing those will be accepted. See Questions & Contributions on how to contribute.

Zig cache

Currently zig cache is in $HOME, so bazel clean --expunge does not clear the zig cache. Zig's cache should be stored somewhere in the project's path.

Alternative download URLs

Currently zig is downloaded from dl.jakstys.lt/zig, which is nuts. One should provide a way to specify alternative URLs for the zig toolchain.

Toolchain and platform target locations

The path to Bazel toolchains is @zig_sdk//:<toolchain>_toolchain. It should be moved to @zig_sdk//toolchain:<toolchain> or similar; so the user-facing targets are in their own namespace.

Likewise, platforms are @zig_sdk//:<platform>_platform, and should be moved to @zig_sdk//:platform:<platform>.

OSX: sysroot

For non-trivial programs (and for all darwin/arm64 cgo programs) MacOS SDK may be necessary. Read Jakub's comment about it. Support for OSX sysroot is currently not implemented.

OSX: different OS targets (Catalina -- Monterey)

Zig 0.9.0 may target macos.10 (Catalina), macos.11 (Big Sur) or macos.12 (Monterey). It currently targets the lowest version, without ability to change it.

Known Issues In Upstream

This section lists issues that I've stumbled into when using zig cc, and is outside of bazel-zig-cc's control.

using glibc 2.27 or older

Severity: Low

Task: ziglang/zig #9485 glibc 2.27 or older: fcntl64 not found, but zig's glibc headers refer it

Background: when glibc 2.27 or older is selected, it may miss fcntl64. A workaround is applied for x86_64, but not for aarch64. The same workaround may apply to aarch64, but the author didn't find a need to test it (yet).

Closed Upstream Issues

Testing

build & run linux cgo + glibc

$ bazel build --platforms @zig_sdk//:linux_amd64_platform //test/go:go
$ file bazel-out/k8-opt-ST-d17813c235ce/bin/test/go/go_/go
bazel-out/k8-opt-ST-d17813c235ce/bin/test/go/go_/go: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.0.0, Go BuildID=redacted, with debug_info, not stripped
$ bazel-out/k8-opt-ST-d17813c235ce/bin/test/go/go_/go
hello, world

test linux cgo + musl on arm64 (under qemu-aarch64)

$ bazel test \
    --run_under=qemu-aarch64 \
    --platforms @zig_sdk//:linux_arm64_platform \
    --extra_toolchains @zig_sdk//:linux_arm64_musl_toolchain //test/...
...
INFO: Build completed successfully, 10 total actions
//test/go:go_test                                                        PASSED in 0.2s

macos cgo

$ bazel build --platforms @zig_sdk//:darwin_amd64_platform //test/go:go
...
$ file bazel-out/k8-opt-ST-d17813c235ce/bin/test/go/go_/go
bazel-out/k8-opt-ST-d17813c235ce/bin/test/go/go_/go: Mach-O 64-bit x86_64 executable, flags:<NOUNDEFS|DYLDLINK|TWOLEVEL|PIE|HAS_TLV_DESCRIPTORS>

Transient docker environment

$ docker run -e CC=/usr/bin/false -ti --rm -v $(pwd):/x -w /x debian:bullseye-slim
# apt update && apt install direnv git -y
# . .envrc

And run the bazel build commands above. Take a look at .build.yml and see how CI does it.

Questions & Contributions

Project's mailing list is ~motiejus/bazel-zig-cc. The mailing list is used for:

  • announcements (I am aiming to send an email with every release).
  • user discussions.
  • raising issues.
  • contributions.

I will generally respond to emails about issues. I may even be able to fix them. However, no promises: you are much more likely (and welcome!) to get it fixed by submitting a patch.

To contribute, send your patches to the mailing list, as described in git-send-email.io or via Sourcehut web UI.

Copyright is retained by the contributors.

Thanks

Many thanks to Adam Bouhenguel and his bazel-zig-cc, the parent of this repository. Also, the Zig team for making this all possible and handling the issues promptly.