From 4d65b80903c3578f451eee27d13fd50a10953939 Mon Sep 17 00:00:00 2001 From: laurynasl Date: Wed, 13 Apr 2022 14:52:25 +0000 Subject: [PATCH] Add libc constraint and libc aware toolchains - Also get rid of @bazel_skylib dependency --- .bazelrc | 5 +- .build.yml | 5 +- README.md | 182 +++++++++++++++++++++------ WORKSPACE | 11 +- ci/list_toolchains_platforms | 15 +++ rules/platform.bzl | 4 +- test/c/BUILD | 46 +++++++ test/c/main.c | 11 ++ test/c/test.sh | 16 +++ test/go/BUILD | 8 +- toolchain/BUILD.sdk.bazel | 2 + toolchain/defs.bzl | 65 +++++----- toolchain/libc/BUILD | 17 +++ toolchain/libc/defs.bzl | 8 ++ toolchain/libc_aware/platform/BUILD | 7 ++ toolchain/libc_aware/toolchain/BUILD | 7 ++ toolchain/platform/BUILD | 4 + toolchain/platform/defs.bzl | 49 ++++++-- toolchain/private/defs.bzl | 4 + toolchain/toolchain/defs.bzl | 57 ++++++--- 20 files changed, 400 insertions(+), 123 deletions(-) create mode 100755 ci/list_toolchains_platforms create mode 100644 test/c/BUILD create mode 100644 test/c/main.c create mode 100755 test/c/test.sh create mode 100644 toolchain/libc/BUILD create mode 100644 toolchain/libc/defs.bzl create mode 100644 toolchain/libc_aware/platform/BUILD create mode 100644 toolchain/libc_aware/toolchain/BUILD diff --git a/.bazelrc b/.bazelrc index c564a31..3cf6b94 100644 --- a/.bazelrc +++ b/.bazelrc @@ -6,7 +6,4 @@ build --worker_sandboxing build --compilation_mode=opt build --incompatible_enable_cc_toolchain_resolution -build --extra_toolchains @zig_sdk//toolchain:linux_amd64_gnu.2.19 -build --extra_toolchains @zig_sdk//toolchain:linux_arm64_gnu.2.28 -build --extra_toolchains @zig_sdk//toolchain:darwin_amd64 -build --extra_toolchains @zig_sdk//toolchain:darwin_arm64 +build --action_env BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1 diff --git a/.build.yml b/.build.yml index 7eb773f..785b50f 100644 --- a/.build.yml +++ b/.build.yml @@ -20,10 +20,7 @@ tasks: sudo apt-get install libc6:arm64 -y - list_toolchains_platforms: | cd bazel-zig-cc; . .envrc - echo "Available toolchains:" - bazel query @zig_sdk//toolchain:* - echo "Available platforms:" - bazel query @zig_sdk//platform:* + ./ci/list_toolchains_platforms - test: | cd bazel-zig-cc; . .envrc ./ci/test --color=yes --curses=yes diff --git a/README.md b/README.md index f6a7538..f3464db 100644 --- a/README.md +++ b/README.md @@ -23,67 +23,168 @@ http_archive( 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") +load("@bazel-zig-cc//toolchain:defs.bzl", zig_toolchains = "toolchains") -zig_register_toolchains() - -# Or, if you are using this in production, you probably want more control: -zig_register_toolchains( - version = "<...>", - url_formats = [ - "https://example.internal/zig/zig-{host_platform}-{version}.tar.xz", - ], - host_platform_sha256 = { ... }, -) +zig_toolchains() ``` +> ### zig sdk download control +> +> If you are using this in production, you probably want more control over +> where the zig sdk is downloaded from: +> ``` +> zig_register_toolchains( +> version = "<...>", +> url_formats = [ +> "https://example.internal/zig/zig-{host_platform}-{version}.tar.xz", +> ], +> host_platform_sha256 = { ... }, +> ) +> ``` + And this to `.bazelrc`: ``` build --incompatible_enable_cc_toolchain_resolution -build --extra_toolchains @zig_sdk//toolchain:linux_amd64_gnu.2.19 -build --extra_toolchains @zig_sdk//toolchain:linux_arm64_gnu.2.28 -build --extra_toolchains @zig_sdk//toolchain:darwin_amd64 -build --extra_toolchains @zig_sdk//toolchain:darwin_arm64 +``` + +The snippets above will download the zig toolchain and make the bazel +toolchains available for registration and usage. + +The next steps depend on your use case. + +## I want to manually build a single target with a specific zig cc toolchain + +You may explicitly request Bazel to use a specific toolchain (compatible with +the specified platform). For example, if you wish to compile a specific binary +(or run tests) on linux/amd64/musl, you may specify: + +``` +bazel build \ + --platforms @zig_sdk//platform:linux_arm64 \ + --extra_toolchains @zig_sdk//toolchain:linux_arm64_musl \ + //test/go:go +``` + +This registers the toolchain `@zig_sdk//toolchain:linux_arm64_musl` for linux +arm64 targets. This toolchains links code statically with musl. We also specify +that we want to build //test/go:go for linux arm64. + +## I want to use zig cc as the default compiler + +Replace the call to `zig_register_toolchains` with +``` +register_toolchains( + "@zig_sdk//toolchain:linux_amd64_gnu.2.19", + "@zig_sdk//toolchain:linux_arm64_gnu.2.28", + "@zig_sdk//toolchain:darwin_amd64", + "@zig_sdk//toolchain:darwin_arm64", +) ``` The snippets above will download the zig toolchain and register it for the -following platforms: +following configurations: -- `x86_64-linux-gnu.2.19` for `["@platforms//os:linux", "@platforms//cpu:x86_64"]`. -- `x86_64-linux-gnu.2.28` for `["@platforms//os:linux", "@platforms//cpu:aarch64"]`. -- `x86_64-macos-gnu` for `["@platforms//os:macos", "@platforms//cpu:x86_64"]`. -- `aarch64-macos-gnu` for `["@platforms//os:macos", "@platforms//cpu:aarch64"]`. +- `toolchain:linux_amd64_gnu.2.19` for `["@platforms//os:linux", "@platforms//cpu:x86_64", "@zig_sdk//libc:unconstrained"]`. +- `toolchain:linux_arm64_gnu.2.28` for `["@platforms//os:linux", "@platforms//cpu:aarch64", "@zig_sdk//libc:unconstrained"]`. +- `toolchain:darwin_arm64` for `["@platforms//os:macos", "@platforms//cpu:x86_64"]`. +- `toolchain:darwin_arm64` for `["@platforms//os:macos", "@platforms//cpu:aarch64"]`. -Note that both Go and Bazel naming schemes are accepted. For convenience with -Go, the following Go-style toolchain aliases are created: +> ### Naming +> +> 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//toolchain/... +> ``` -|Bazel (zig) name | Go name | -|---------------- | -------- | -|`x86_64` | `amd64` | -|`aarch64` | `arm64` | -|`macos` | `darwin` | +> ### Disabling the default bazel cc toolchain +> +> It may be useful to disable the default toolchain that bazel configures for +> you, so that configuration issues can be caught early on: +> +> .bazelrc +> ``` +> build:zig_cc --action_env BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1 +> ``` +> +> This is not documented in bazel, so use at your own peril. -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: +## I want to start using the zig cc toolchain gradually +You can register your zig cc toolchains under a config in your .bazelrc ``` -$ bazel query @zig_sdk//toolchain/... +build:zig_cc --extra_toolchains @zig_sdk//toolchain:linux_amd64_gnu.2.19 +build:zig_cc --extra_toolchains @zig_sdk//toolchain:linux_arm64_gnu.2.28 +build:zig_cc --extra_toolchains @zig_sdk//toolchain:darwin_amd64 +build:zig_cc --extra_toolchains @zig_sdk//toolchain:darwin_arm64 ``` -## Specifying non-default toolchains - -You may explicitly request Bazel to use a specific toolchain, even though a -different one is registered using `--extra_toolchains ` in -`.bazelrc`. For example, if you wish to compile a specific binary (or run -tests) on linux/amd64/musl, you may specify: - +Then for your builds/tests you need to specify that the `zig_cc` config +should be used: ``` ---extra_toolchains @zig_sdk//toolchain:linux_amd64_musl +bazel build --config zig_cc //test/go:go ``` -## UBSAN and "SIGILL: Illegal Instruction" +You can build a target for a different platform like so: +``` +bazel build --config zig_cc \ + --platforms @zig_sdk//platform:linux_arm64 \ + //test/go:go +``` + +## I want to use zig to build targets for multiple libc variants + +If you have targets that need to be build with different glibc versions or with +musl, you can register a linux toolchain declared under `libc_aware/toolchains`. +It will only be selected when building for a specific libc version. For example + +- `libc_aware/toolchain:linux_amd64_gnu.2.19` for `["@platforms//os:linux", "@platforms//cpu:x86_64", "@zig_sdk//libc:gnu.2.19"]`. +- `libc_aware/toolchain:linux_amd64_gnu.2.28` for `["@platforms//os:linux", "@platforms//cpu:x86_64", "@zig_sdk//libc:gnu.2.28"]`. +- `libc_aware/toolchain:x86_64-linux-musl` for `["@platforms//os:linux", "@platforms//cpu:x86_64", "@zig_sdk//libc:musl"]`. + +With these toolchains registered, you can build a project for a specific libc +aware platform: +``` +$ bazel build --platforms @zig_sdk//libc_aware/platform:linux_amd64_gnu.2.19 //test/go:go +$ bazel build --platforms @zig_sdk//libc_aware/platform:linux_amd64_gnu.2.28 //test/go:go +$ bazel build --platforms @zig_sdk//libc_aware/platform:linux_amd64_musl //test/go:go +``` + +You can see the list of libc aware toolchains and platforms by running: +``` +$ bazel query @zig_sdk//libc_aware/toolchain/... +$ bazel query @zig_sdk//libc_aware/platform/... + ``` + +This is especially useful if you are relying on [transitions][transitions], as +transitioning `extra_platforms` will cause your host tools to be rebuilt with +the specific libc version, which takes time, and your host may not be able to +run them. + +The `@zig_sdk//libc:variant` constraint is used to select a matching toolchain. +If you are using your own platform definitions, add a `@zig_sdk//libc:variant` +constraint to them. See the list of available values: +``` +$ bazel query "attr(constraint_setting, @zig_sdk//libc:variant, @zig_sdk//...)" +``` + +`@zig_sdk//libc:unconstrained` is a special value that indicates that no value +for the constraint is specified. The non libc aware linux toolchains are only +compatible with this value to prevent accidental silent fallthrough to them. + +# UBSAN and "SIGILL: Illegal Instruction" `zig cc` differs from "mainstream" compilers by [enabling UBSAN by default][ubsan1]. Which means your program may compile successfully and crash @@ -200,3 +301,4 @@ the issues promptly. [sysroot]: https://github.com/ziglang/zig/issues/10299#issuecomment-989153750 [ubsan1]: https://github.com/ziglang/zig/issues/4830#issuecomment-605491606 [ubsan2]: https://github.com/ziglang/zig/issues/5163 +[transitions]: https://docs.bazel.build/versions/main/skylark/config.html#user-defined-transitions diff --git a/WORKSPACE b/WORKSPACE index 54d84a0..759d198 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -44,7 +44,14 @@ gazelle_dependencies(go_repository_default_config = "@//:WORKSPACE") load( "//toolchain:defs.bzl", - zig_register_toolchains = "register_toolchains", + zig_toolchains = "toolchains", ) -zig_register_toolchains() +zig_toolchains() + +register_toolchains( + "@zig_sdk//toolchain:linux_amd64_gnu.2.19", + "@zig_sdk//toolchain:linux_arm64_gnu.2.28", + "@zig_sdk//toolchain:darwin_amd64", + "@zig_sdk//toolchain:darwin_arm64", +) diff --git a/ci/list_toolchains_platforms b/ci/list_toolchains_platforms new file mode 100755 index 0000000..a67735f --- /dev/null +++ b/ci/list_toolchains_platforms @@ -0,0 +1,15 @@ +#!/bin/bash +set -euo pipefail + +indent() { sed 's/^/ /'; } + +echo "Available toolchains:" +bazel query '@zig_sdk//toolchain:*' | indent +echo "Available platforms:" +bazel query '@zig_sdk//platform:*' | indent +echo "Available libc aware toolchains:" +bazel query '@zig_sdk//libc_aware/toolchain:*' | indent +echo "Available libc aware platforms:" +bazel query '@zig_sdk//libc_aware/platform:*' | indent +echo "Available libc variants:" +bazel query "attr(constraint_setting, @zig_sdk//libc:variant, @zig_sdk//...)" | indent diff --git a/rules/platform.bzl b/rules/platform.bzl index 73ea7ca..268dfd6 100644 --- a/rules/platform.bzl +++ b/rules/platform.bzl @@ -1,8 +1,8 @@ def _platform_transition_impl(settings, attr): _ignore = settings return { - "//command_line_option:platforms": "@zig_sdk//platform:{}".format(attr.platform), - "//command_line_option:extra_toolchains": ["@zig_sdk//toolchain:{}".format(tc) for tc in attr.extra_toolchains], + "//command_line_option:platforms": "@zig_sdk{}".format(attr.platform), + "//command_line_option:extra_toolchains": ["@zig_sdk{}".format(tc) for tc in attr.extra_toolchains], } _platform_transition = transition( diff --git a/test/c/BUILD b/test/c/BUILD new file mode 100644 index 0000000..69d259e --- /dev/null +++ b/test/c/BUILD @@ -0,0 +1,46 @@ +load("@bazel-zig-cc//rules:platform.bzl", "platform_binary") + +cc_binary( + name = "which_libc", + srcs = ["main.c"], + target_compatible_with = [ + "@platforms//os:linux", + ], +) + +[ + ( + platform_binary( + name = "which_libc_{}".format(name), + src = "which_libc", + extra_toolchains = [ + # toolchains for specific libc versions + "//libc_aware/toolchain:linux_amd64_gnu.2.19", + "//libc_aware/toolchain:linux_amd64_gnu.2.28", + "//libc_aware/toolchain:linux_amd64_gnu.2.31", + "//libc_aware/toolchain:linux_amd64_musl", + # fallback toolchains + "//toolchain:linux_amd64_gnu.2.19", + "//toolchain:linux_arm64_gnu.2.28", + ], + platform = platform, + ), + sh_test( + name = "test_libc_{}".format(name), + srcs = ["test.sh"], + data = ["which_libc_{}".format(name)], + env = { + "WANT": want, + "BINARY": "$(location which_libc_{})".format(name), + }, + ), + ) + for name, platform, want in [ + ("linux_amd64_musl", "//libc_aware/platform:linux_amd64_musl", "non-glibc"), + ("linux_amd64_gnu.2.19", "//libc_aware/platform:linux_amd64_gnu.2.19", "glibc_2.19"), + ("linux_amd64_gnu.2.28", "//libc_aware/platform:linux_amd64_gnu.2.28", "glibc_2.28"), + ("linux_amd64_gnu.2.31", "//libc_aware/platform:linux_amd64_gnu.2.31", "glibc_2.31"), + ("linux_amd64", "//platform:linux_amd64", "glibc_2.19"), + ("linux_arm64", "//platform:linux_arm64", "glibc_2.28"), + ] +] diff --git a/test/c/main.c b/test/c/main.c new file mode 100644 index 0000000..9ab0dc1 --- /dev/null +++ b/test/c/main.c @@ -0,0 +1,11 @@ +#include +#include + +int main() { + #ifdef __GLIBC__ + printf("glibc_%d.%d", __GLIBC__, __GLIBC_MINOR__); + #else + puts("non-glibc"); + #endif + return 0; +} diff --git a/test/c/test.sh b/test/c/test.sh new file mode 100755 index 0000000..d5331ff --- /dev/null +++ b/test/c/test.sh @@ -0,0 +1,16 @@ +#/bin/bash + +set -euo pipefail + +want=$WANT +binary=$BINARY + +got=$($binary) + +if [[ "$got" != "$want" ]]; then + echo wanted: + echo \ \ "$want" + echo got: + echo \ \ "$got" + exit 1 +fi diff --git a/test/go/BUILD b/test/go/BUILD index 7dba4ab..e5206fd 100644 --- a/test/go/BUILD +++ b/test/go/BUILD @@ -26,8 +26,8 @@ go_test( platform_binary( name = "go_{}".format(toolchain), src = "go", - extra_toolchains = [toolchain], - platform = platform, + extra_toolchains = ["//toolchain:{}".format(toolchain)], + platform = "//platform:{}".format(platform), ) for platform, toolchain in [ ("linux_amd64", "linux_amd64_musl"), @@ -42,8 +42,8 @@ go_test( platform_test( name = "go_test_{}".format(toolchain), src = "go_test", - extra_toolchains = [toolchain], - platform = platform, + extra_toolchains = ["//toolchain:{}".format(toolchain)], + platform = "//platform:{}".format(platform), ) for platform, toolchain in [ ("linux_amd64", "linux_amd64_musl"), diff --git a/toolchain/BUILD.sdk.bazel b/toolchain/BUILD.sdk.bazel index cf5dc4a..ada3e5d 100644 --- a/toolchain/BUILD.sdk.bazel +++ b/toolchain/BUILD.sdk.bazel @@ -4,6 +4,8 @@ package( default_visibility = ["//visibility:public"], ) + + declare_files( zig_include_root = {zig_include_root}, ) diff --git a/toolchain/defs.bzl b/toolchain/defs.bzl index 9e34e6b..696931a 100644 --- a/toolchain/defs.bzl +++ b/toolchain/defs.bzl @@ -1,4 +1,3 @@ -load("@bazel_skylib//lib:shell.bzl", "shell") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") load("@bazel_tools//tools/build_defs/repo:utils.bzl", "read_user_netrc", "use_netrc") load("@bazel-zig-cc//toolchain/private:defs.bzl", "DEFAULT_INCLUDE_DIRECTORIES", "ZIG_TOOL_PATH", "target_structs") @@ -42,15 +41,15 @@ _HOST_PLATFORM_SHA256 = { "macos-x86_64": "78220a4460a7c0f563d7365313fcd3ea028ed38166ebac55ba22f17ab6404851", } -def register_toolchains( - register = [], +def toolchains( version = _VERSION, url_formats = [URL_FORMAT_JAKSTYS], host_platform_sha256 = _HOST_PLATFORM_SHA256): """ - Download zig toolchain and register some. - @param register registers the given toolchains to the system using - native.register_toolchains(). See README for possible choices. + Download zig toolchain and declare bazel toolchains. + The platforms are not registered automatically, that should be done by + the user with register_toolchains() in the WORKSPACE file. See README + for possible choices. """ zig_repository( name = "zig_sdk", @@ -65,9 +64,6 @@ def register_toolchains( }, ) - toolchains = ["@zig_sdk//toolchain:%s" % t for t in register] - native.register_toolchains(*toolchains) - ZIG_TOOL_WRAPPER = """#!/bin/bash set -e @@ -95,6 +91,9 @@ _ZIG_TOOLS = [ "wasm-ld", # WebAssembly ] +def _quote(s): + return "'" + s.replace("'", "'\\''") + "'" + def _zig_repository_impl(repository_ctx): arch = repository_ctx.os.arch if arch == "amd64": @@ -139,34 +138,28 @@ def _zig_repository_impl(repository_ctx): content = _fcntl_h, ) - repository_ctx.symlink( - Label("//toolchain/platform:BUILD"), - "platform/BUILD", - ) + for dest, src in { + "platform/BUILD": "//toolchain/platform:BUILD", + "toolchain/BUILD": "//toolchain/toolchain:BUILD", + "libc/BUILD": "//toolchain/libc:BUILD", + "libc_aware/platform/BUILD": "//toolchain/libc_aware/platform:BUILD", + "libc_aware/toolchain/BUILD": "//toolchain/libc_aware/toolchain:BUILD", + }.items(): + repository_ctx.symlink(Label(src), dest) - repository_ctx.template( - "BUILD", - Label("//toolchain:BUILD.sdk.bazel"), - executable = False, - substitutions = { - "{zig_include_root}": shell.quote(zig_include_root), - }, - ) - - repository_ctx.symlink( - Label("//toolchain/toolchain:BUILD"), - "toolchain/BUILD", - ) - - repository_ctx.template( - "private/BUILD", - Label("//toolchain/private:BUILD.sdk.bazel"), - executable = False, - substitutions = { - "{absolute_path}": shell.quote(str(repository_ctx.path(""))), - "{zig_include_root}": shell.quote(zig_include_root), - }, - ) + for dest, src in { + "BUILD": "//toolchain:BUILD.sdk.bazel", + "private/BUILD": "//toolchain/private:BUILD.sdk.bazel", + }.items(): + repository_ctx.template( + dest, + Label(src), + executable = False, + substitutions = { + "{absolute_path}": _quote(str(repository_ctx.path(""))), + "{zig_include_root}": _quote(zig_include_root), + }, + ) zig_repository = repository_rule( attrs = { diff --git a/toolchain/libc/BUILD b/toolchain/libc/BUILD new file mode 100644 index 0000000..e2713f8 --- /dev/null +++ b/toolchain/libc/BUILD @@ -0,0 +1,17 @@ +load("@bazel-zig-cc//toolchain/libc:defs.bzl", "declare_libcs") + +package( + default_visibility = ["//visibility:public"], +) + +constraint_setting( + name = "variant", + default_constraint_value = "unconstrained", +) + +constraint_value( + name = "unconstrained", + constraint_setting = "variant", +) + +declare_libcs() diff --git a/toolchain/libc/defs.bzl b/toolchain/libc/defs.bzl new file mode 100644 index 0000000..58532b0 --- /dev/null +++ b/toolchain/libc/defs.bzl @@ -0,0 +1,8 @@ +load("@bazel-zig-cc//toolchain/private:defs.bzl", "LIBCS") + +def declare_libcs(): + for libc in LIBCS: + native.constraint_value( + name = libc, + constraint_setting = "variant", + ) diff --git a/toolchain/libc_aware/platform/BUILD b/toolchain/libc_aware/platform/BUILD new file mode 100644 index 0000000..b34acc6 --- /dev/null +++ b/toolchain/libc_aware/platform/BUILD @@ -0,0 +1,7 @@ +load("@bazel-zig-cc//toolchain/platform:defs.bzl", "declare_libc_aware_platforms") + +package( + default_visibility = ["//visibility:public"], +) + +declare_libc_aware_platforms() diff --git a/toolchain/libc_aware/toolchain/BUILD b/toolchain/libc_aware/toolchain/BUILD new file mode 100644 index 0000000..98065fd --- /dev/null +++ b/toolchain/libc_aware/toolchain/BUILD @@ -0,0 +1,7 @@ +load("@bazel-zig-cc//toolchain/toolchain:defs.bzl", "declare_libc_aware_toolchains") + +package( + default_visibility = ["//visibility:public"], +) + +declare_libc_aware_toolchains() diff --git a/toolchain/platform/BUILD b/toolchain/platform/BUILD index ce0ffc7..f43b852 100644 --- a/toolchain/platform/BUILD +++ b/toolchain/platform/BUILD @@ -1,3 +1,7 @@ load("@bazel-zig-cc//toolchain/platform:defs.bzl", "declare_platforms") +package( + default_visibility = ["//visibility:public"], +) + declare_platforms() diff --git a/toolchain/platform/defs.bzl b/toolchain/platform/defs.bzl index e094029..cf42191 100644 --- a/toolchain/platform/defs.bzl +++ b/toolchain/platform/defs.bzl @@ -1,17 +1,40 @@ +load("@bazel-zig-cc//toolchain/private:defs.bzl", "LIBCS") + +_CPUS = (("x86_64", "amd64"), ("aarch64", "arm64")) + def declare_platforms(): # create @zig_sdk//{os}_{arch}_platform entries with zig and go conventions - for zigcpu, gocpu in (("x86_64", "amd64"), ("aarch64", "arm64")): + for zigcpu, gocpu in _CPUS: for bzlos, oss in {"linux": ["linux"], "macos": ["macos", "darwin"]}.items(): for os in oss: - constraint_values = [ - "@platforms//os:{}".format(bzlos), - "@platforms//cpu:{}".format(zigcpu), - ] - native.platform( - name = "{os}_{zigcpu}".format(os = os, zigcpu = zigcpu), - constraint_values = constraint_values, - ) - native.platform( - name = "{os}_{gocpu}".format(os = os, gocpu = gocpu), - constraint_values = constraint_values, - ) + declare_platform(gocpu, zigcpu, bzlos, os) + +def declare_libc_aware_platforms(): + # create @zig_sdk//{os}_{arch}_platform entries with zig and go conventions + # with libc specified + for zigcpu, gocpu in _CPUS: + for libc in LIBCS: + declare_platform( + gocpu, + zigcpu, + "linux", + "linux", + suffix = "_{}".format(libc), + extra_constraints = ["@zig_sdk//libc:{}".format(libc)], + ) + +def declare_platform(gocpu, zigcpu, bzlos, os, suffix = "", extra_constraints = []): + constraint_values = [ + "@platforms//os:{}".format(bzlos), + "@platforms//cpu:{}".format(zigcpu), + ] + extra_constraints + + native.platform( + name = "{os}_{zigcpu}{suffix}".format(os = os, zigcpu = zigcpu, suffix = suffix), + constraint_values = constraint_values, + ) + + native.platform( + name = "{os}_{gocpu}{suffix}".format(os = os, gocpu = gocpu, suffix = suffix), + constraint_values = constraint_values, + ) diff --git a/toolchain/private/defs.bzl b/toolchain/private/defs.bzl index 8380071..671a81a 100644 --- a/toolchain/private/defs.bzl +++ b/toolchain/private/defs.bzl @@ -28,6 +28,8 @@ _GLIBCS = [ "2.34", ] +LIBCS = ["musl", "gnu"] + ["gnu.{}".format(glibc) for glibc in _GLIBCS] + def target_structs(): ret = [] for zigcpu, gocpu in (("x86_64", "amd64"), ("aarch64", "arm64")): @@ -100,6 +102,7 @@ def _target_linux_gnu(gocpu, zigcpu, glibc_version = ""): "@platforms//os:linux", "@platforms//cpu:{}".format(zigcpu), ], + libc_constraint = "@zig_sdk//libc:{}".format(glibc_suffix), tool_paths = {"ld": "ld.lld"}, ) @@ -120,5 +123,6 @@ def _target_linux_musl(gocpu, zigcpu): "@platforms//os:linux", "@platforms//cpu:{}".format(zigcpu), ], + libc_constraint = "@zig_sdk//libc:musl", tool_paths = {"ld": "ld.lld"}, ) diff --git a/toolchain/toolchain/defs.bzl b/toolchain/toolchain/defs.bzl index 2c9bf96..1d99a61 100644 --- a/toolchain/toolchain/defs.bzl +++ b/toolchain/toolchain/defs.bzl @@ -1,25 +1,46 @@ -load("@bazel-zig-cc//toolchain/private:defs.bzl", "DEFAULT_INCLUDE_DIRECTORIES", "ZIG_TOOL_PATH", "target_structs") +load("@bazel-zig-cc//toolchain/private:defs.bzl", "target_structs") def declare_toolchains(): for target_config in target_structs(): gotarget = target_config.gotarget zigtarget = target_config.zigtarget - # register two kinds of toolchain targets: Go and Zig conventions. - # Go convention: amd64/arm64, linux/darwin - native.toolchain( - name = gotarget, - exec_compatible_with = None, - target_compatible_with = target_config.constraint_values, - toolchain = "@zig_sdk//private:%s_cc" % zigtarget, - toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", - ) + # if the toolchain is libc aware, create two variants for it: one that + # is only selected if libc is not expicitly set and another one that is + # only selected if the specific libc variant is selected. + extra_constraints = [] + if hasattr(target_config, "libc_constraint"): + extra_constraints = ["@zig_sdk//libc:unconstrained"] - # Zig convention: x86_64/aarch64, linux/macos - native.toolchain( - name = zigtarget, - exec_compatible_with = None, - target_compatible_with = target_config.constraint_values, - toolchain = "@zig_sdk//private:%s_cc" % zigtarget, - toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", - ) + _declare_toolchain(gotarget, zigtarget, target_config.constraint_values + extra_constraints) + +def declare_libc_aware_toolchains(): + for target_config in target_structs(): + gotarget = target_config.gotarget + zigtarget = target_config.zigtarget + + # if the toolchain is libc aware, create two variants for it: one that + # is only selected if libc is not expicitly set and another one that is + # only selected if the specific libc variant is selected. + if hasattr(target_config, "libc_constraint"): + _declare_toolchain(gotarget, zigtarget, target_config.constraint_values + [target_config.libc_constraint]) + +def _declare_toolchain(gotarget, zigtarget, target_compatible_with): + # register two kinds of toolchain targets: Go and Zig conventions. + # Go convention: amd64/arm64, linux/darwin + native.toolchain( + name = gotarget, + exec_compatible_with = None, + target_compatible_with = target_compatible_with, + toolchain = "@zig_sdk//private:%s_cc" % zigtarget, + toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", + ) + + # Zig convention: x86_64/aarch64, linux/macos + native.toolchain( + name = zigtarget, + exec_compatible_with = None, + target_compatible_with = target_compatible_with, + toolchain = "@zig_sdk//private:%s_cc" % zigtarget, + toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", + )