Subject: [PATCH bazel-zig-cc 0/4] Move platforms and toolchains

From: ~laurynasl <[email-masked]>
Date: Thu, 07 Apr 2022 09:37:52 +0000

Move platform and toochains definitions into their own "namespaces".

laurynasl (4):
  move platforms under @zig_cc//platform:
  Move declare_platforms() to platform/
  Move toolchainss under @zig_sdk//platform:
  Move toolchain definitions to toolchains/

 .bazelrc                            |   8 +-
 README.md                           |  27 +--
 ci/test                             |   4 +-
 toolchain/BUILD.sdk.bazel           |   5 +-
 toolchain/defs.bzl                  | 244 +++-------------------------
 toolchain/platform/BUILD            |   3 +
 toolchain/platform/defs.bzl         |  17 ++
 toolchain/private/BUILD             |   0
 toolchain/private/defs.bzl          | 124 ++++++++++++++
 toolchain/toolchain/BUILD           |   0
 toolchain/toolchain/BUILD.sdk.bazel |  10 ++
 toolchain/toolchain/defs.bzl        |  87 ++++++++++
 12 files changed, 277 insertions(+), 252 deletions(-)
 create mode 100644 toolchain/platform/BUILD
 create mode 100644 toolchain/platform/defs.bzl
 create mode 100644 toolchain/private/BUILD
 create mode 100644 toolchain/private/defs.bzl
 create mode 100644 toolchain/toolchain/BUILD
 create mode 100644 toolchain/toolchain/BUILD.sdk.bazel
 create mode 100644 toolchain/toolchain/defs.bzl

-- 
2.34.1

---

From: ~laurynasl <[email-masked]>
Date: Wed, 06 Apr 2022 19:16:53 +0000

From: laurynasl <[email-masked]>

---
 README.md                |  9 +++------
 ci/test                  |  2 +-
 toolchain/defs.bzl       | 10 ++++++++--
 toolchain/platform/BUILD |  3 +++
 4 files changed, 15 insertions(+), 9 deletions(-)
 create mode 100644 toolchain/platform/BUILD

diff --git a/README.md b/README.md
index 1c8e011..d855c78 100644
--- a/README.md
+++ b/README.md
@@ -114,9 +114,6 @@ 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
@@ -164,7 +161,7 @@ may apply to aarch64, but the author didn't find a need to test it (yet).
 ## build & run linux cgo + glibc
 
 ```
-$ bazel build --platforms @zig_sdk//:linux_amd64_platform //test/go:go
+$ bazel build --platforms @zig_sdk//platform:linux_amd64 //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
@@ -176,7 +173,7 @@ hello, world
 ```
 $ bazel test \
     --config=qemu-aarch64 \
-    --platforms @zig_sdk//:linux_arm64_platform \
+    --platforms @zig_sdk//platform:linux_arm64 \
     --extra_toolchains @zig_sdk//:linux_arm64_musl_toolchain //test/...
 ...
 INFO: Build completed successfully, 10 total actions
@@ -186,7 +183,7 @@ INFO: Build completed successfully, 10 total actions
 ## macos cgo
 
 ```
-$ bazel build --platforms @zig_sdk//:darwin_amd64_platform //test/go:go
+$ bazel build --platforms @zig_sdk//platform:darwin_amd64 //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>
diff --git a/ci/test b/ci/test
index e9a8e9a..5b9a4d7 100755
--- a/ci/test
+++ b/ci/test
@@ -18,7 +18,7 @@ while read -r action platform toolchain config; do
     fi
 
     args+=(\
-        --platforms "@zig_sdk//:${platform}_platform" \
+        --platforms "@zig_sdk//platform:${platform}" \
         --extra_toolchains "@zig_sdk//:${toolchain}_toolchain" \
         //test/... \
     )
diff --git a/toolchain/defs.bzl b/toolchain/defs.bzl
index 112a64a..eb005fe 100644
--- a/toolchain/defs.bzl
+++ b/toolchain/defs.bzl
@@ -264,6 +264,11 @@ def _zig_repository_impl(repository_ctx):
         content = _fcntl_h,
     )
 
+    repository_ctx.symlink(
+        Label("//toolchain/platform:BUILD"),
+        "platform/BUILD",
+    )
+
     repository_ctx.template(
         "BUILD.bazel",
         Label("//toolchain:BUILD.sdk.bazel"),
@@ -380,6 +385,7 @@ def zig_build_macro(absolute_path, zig_include_root):
             toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
         )
 
+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 bzlos, oss in {"linux": ["linux"], "macos": ["macos", "darwin"]}.items():
@@ -389,10 +395,10 @@ def zig_build_macro(absolute_path, zig_include_root):
                     "@platforms//cpu:{}".format(zigcpu),
                 ]
                 native.platform(
-                    name = "{os}_{zigcpu}_platform".format(os = os, zigcpu = zigcpu),
+                    name = "{os}_{zigcpu}".format(os = os, zigcpu = zigcpu),
                     constraint_values = constraint_values,
                 )
                 native.platform(
-                    name = "{os}_{gocpu}_platform".format(os = os, gocpu = gocpu),
+                    name = "{os}_{gocpu}".format(os = os, gocpu = gocpu),
                     constraint_values = constraint_values,
                 )
diff --git a/toolchain/platform/BUILD b/toolchain/platform/BUILD
new file mode 100644
index 0000000..b02436b
--- /dev/null
+++ b/toolchain/platform/BUILD
@@ -0,0 +1,3 @@
+load("@bazel-zig-cc//toolchain:defs.bzl", "declare_platforms")
+
+declare_platforms()
-- 
2.34.1

---

From: ~laurynasl <[email-masked]>
Date: Wed, 06 Apr 2022 19:19:44 +0000

---
 toolchain/defs.bzl          | 17 -----------------
 toolchain/platform/BUILD    |  2 +-
 toolchain/platform/defs.bzl | 17 +++++++++++++++++
 3 files changed, 18 insertions(+), 18 deletions(-)
 create mode 100644 toolchain/platform/defs.bzl

diff --git a/toolchain/defs.bzl b/toolchain/defs.bzl
index eb005fe..3f6b4bd 100644
--- a/toolchain/defs.bzl
+++ b/toolchain/defs.bzl
@@ -385,20 +385,3 @@ def zig_build_macro(absolute_path, zig_include_root):
             toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
         )
 
-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 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,
-                )
diff --git a/toolchain/platform/BUILD b/toolchain/platform/BUILD
index b02436b..ce0ffc7 100644
--- a/toolchain/platform/BUILD
+++ b/toolchain/platform/BUILD
@@ -1,3 +1,3 @@
-load("@bazel-zig-cc//toolchain:defs.bzl", "declare_platforms")
+load("@bazel-zig-cc//toolchain/platform:defs.bzl", "declare_platforms")
 
 declare_platforms()
diff --git a/toolchain/platform/defs.bzl b/toolchain/platform/defs.bzl
new file mode 100644
index 0000000..e094029
--- /dev/null
+++ b/toolchain/platform/defs.bzl
@@ -0,0 +1,17 @@
+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 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,
+                )
-- 
2.34.1

---

From: ~laurynasl <[email-masked]>
Date: Wed, 06 Apr 2022 19:46:15 +0000

---
 .bazelrc                            |  8 ++---
 README.md                           | 18 ++++------
 ci/test                             |  2 +-
 toolchain/BUILD.sdk.bazel           |  5 ++-
 toolchain/defs.bzl                  | 55 ++++++++++++++++++-----------
 toolchain/toolchain/BUILD           |  0
 toolchain/toolchain/BUILD.sdk.bazel | 10 ++++++
 7 files changed, 57 insertions(+), 41 deletions(-)
 create mode 100644 toolchain/toolchain/BUILD
 create mode 100644 toolchain/toolchain/BUILD.sdk.bazel

diff --git a/.bazelrc b/.bazelrc
index cba4a5e..fed6f0b 100644
--- a/.bazelrc
+++ b/.bazelrc
@@ -6,10 +6,10 @@ build --worker_sandboxing
 build --compilation_mode=opt
 
 build --incompatible_enable_cc_toolchain_resolution
-build --extra_toolchains @zig_sdk//:linux_amd64_gnu.2.19_toolchain
-build --extra_toolchains @zig_sdk//:linux_arm64_gnu.2.28_toolchain
-build --extra_toolchains @zig_sdk//:darwin_amd64_toolchain
-build --extra_toolchains @zig_sdk//:darwin_arm64_toolchain
+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
 
 test:qemu-aarch64 --test_env=QEMU_LD_PREFIX=/usr/aarch64-linux-gnu/
 test:qemu-aarch64 --run_under=qemu-aarch64-static
diff --git a/README.md b/README.md
index d855c78..1a20d5f 100644
--- a/README.md
+++ b/README.md
@@ -41,10 +41,10 @@ And this to `.bazelrc`:
 
 ```
 build --incompatible_enable_cc_toolchain_resolution
-build --extra_toolchains @zig_sdk//:linux_amd64_gnu.2.19_toolchain
-build --extra_toolchains @zig_sdk//:linux_arm64_gnu.2.28_toolchain
-build --extra_toolchains @zig_sdk//:darwin_amd64_toolchain
-build --extra_toolchains @zig_sdk//:darwin_arm64_toolchain
+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 register it for the
@@ -80,7 +80,7 @@ different one is registered using `--extra_toolchains <toolchain>` in
 tests) on linux/amd64/musl, you may specify:
 
 ```
---extra_toolchains @zig_sdk//:linux_amd64_musl_toolchain
+--extra_toolchains @zig_sdk//toolchain:linux_amd64_musl
 ```
 
 ## UBSAN and "SIGILL: Illegal Instruction"
@@ -108,12 +108,6 @@ how to contribute.
 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.
 
-## 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.
-
 ## OSX: sysroot
 
 For non-trivial programs (and for all darwin/arm64 cgo programs) MacOS SDK may
@@ -174,7 +168,7 @@ hello, world
 $ bazel test \
     --config=qemu-aarch64 \
     --platforms @zig_sdk//platform:linux_arm64 \
-    --extra_toolchains @zig_sdk//:linux_arm64_musl_toolchain //test/...
+    --extra_toolchains @zig_sdk//toolchain:linux_arm64_musl //test/...
 ...
 INFO: Build completed successfully, 10 total actions
 //test/go:go_test                                                        PASSED in 0.2s
diff --git a/ci/test b/ci/test
index 5b9a4d7..35d0c07 100755
--- a/ci/test
+++ b/ci/test
@@ -19,7 +19,7 @@ while read -r action platform toolchain config; do
 
     args+=(\
         --platforms "@zig_sdk//platform:${platform}" \
-        --extra_toolchains "@zig_sdk//:${toolchain}_toolchain" \
+        --extra_toolchains "@zig_sdk//toolchain:${toolchain}" \
         //test/... \
     )
 
diff --git a/toolchain/BUILD.sdk.bazel b/toolchain/BUILD.sdk.bazel
index 8b5db49..cf5dc4a 100644
--- a/toolchain/BUILD.sdk.bazel
+++ b/toolchain/BUILD.sdk.bazel
@@ -1,11 +1,10 @@
-load("@bazel-zig-cc//toolchain:defs.bzl", "zig_build_macro")
+load("@bazel-zig-cc//toolchain:defs.bzl", "declare_files")
 
 package(
     default_visibility = ["//visibility:public"],
 )
 
-zig_build_macro(
-    absolute_path = {absolute_path},
+declare_files(
     zig_include_root = {zig_include_root},
 )
 
diff --git a/toolchain/defs.bzl b/toolchain/defs.bzl
index 3f6b4bd..61e099f 100644
--- a/toolchain/defs.bzl
+++ b/toolchain/defs.bzl
@@ -189,7 +189,7 @@ def register_toolchains(
         },
     )
 
-    toolchains = ["@zig_sdk//:%s_toolchain" % t for t in register]
+    toolchains = ["@zig_sdk//:toolchain:%s" % t for t in register]
     native.register_toolchains(*toolchains)
 
 ZIG_TOOL_PATH = "tools/{zig_tool}"
@@ -268,11 +268,19 @@ def _zig_repository_impl(repository_ctx):
         Label("//toolchain/platform:BUILD"),
         "platform/BUILD",
     )
-
     repository_ctx.template(
-        "BUILD.bazel",
+        "BUILD",
         Label("//toolchain:BUILD.sdk.bazel"),
         executable = False,
+        substitutions = {
+            "{zig_include_root}": shell.quote(zig_include_root),
+        },
+    )
+
+    repository_ctx.template(
+        "toolchain/BUILD",
+        Label("//toolchain/toolchain:BUILD.sdk.bazel"),
+        executable = False,
         substitutions = {
             "{absolute_path}": shell.quote(str(repository_ctx.path(""))),
             "{zig_include_root}": shell.quote(zig_include_root),
@@ -302,13 +310,21 @@ def filegroup(name, **kwargs):
     native.filegroup(name = name, **kwargs)
     return ":" + name
 
-def zig_build_macro(absolute_path, zig_include_root):
+def declare_files(zig_include_root):
     filegroup(name = "empty")
     native.exports_files(["zig"], visibility = ["//visibility:public"])
     filegroup(name = "lib/std", srcs = native.glob(["lib/std/**"]))
 
     lazy_filegroups = {}
 
+    for target_config in _target_structs():
+        for d in DEFAULT_INCLUDE_DIRECTORIES + target_config.includes:
+            d = zig_include_root + d
+            if d not in lazy_filegroups:
+                lazy_filegroups[d] = filegroup(name = d, srcs = native.glob([d + "/**"]))
+
+
+def declare_toolchains(absolute_path, zig_include_root):
     for target_config in _target_structs():
         gotarget = target_config.gotarget
         zigtarget = target_config.zigtarget
@@ -316,8 +332,6 @@ def zig_build_macro(absolute_path, zig_include_root):
         cxx_builtin_include_directories = []
         for d in DEFAULT_INCLUDE_DIRECTORIES + target_config.includes:
             d = zig_include_root + d
-            if d not in lazy_filegroups:
-                lazy_filegroups[d] = filegroup(name = d, srcs = native.glob([d + "/**"]))
             cxx_builtin_include_directories.append(absolute_path + "/" + d)
         for d in getattr(target_config, "toplevel_include", []):
             cxx_builtin_include_directories.append(absolute_path + "/" + d)
@@ -338,7 +352,7 @@ def zig_build_macro(absolute_path, zig_include_root):
             copts = copts + ["-include", absolute_path + "/" + incl]
 
         zig_cc_toolchain_config(
-            name = zigtarget + "_toolchain_cc_config",
+            name = zigtarget + "_cc_config",
             target = zigtarget,
             tool_paths = absolute_tool_paths,
             cxx_builtin_include_directories = cxx_builtin_include_directories,
@@ -353,35 +367,34 @@ def zig_build_macro(absolute_path, zig_include_root):
         )
 
         native.cc_toolchain(
-            name = zigtarget + "_toolchain_cc",
+            name = zigtarget + "_cc",
             toolchain_identifier = zigtarget + "-toolchain",
-            toolchain_config = ":%s_toolchain_cc_config" % zigtarget,
-            all_files = ":zig",
-            ar_files = ":zig",
-            compiler_files = ":zig",
-            linker_files = ":zig",
-            dwp_files = ":empty",
-            objcopy_files = ":empty",
-            strip_files = ":empty",
+            toolchain_config = ":%s_cc_config" % zigtarget,
+            all_files = "@zig_sdk//:zig",
+            ar_files = "@zig_sdk//:zig",
+            compiler_files = "@zig_sdk//:zig",
+            linker_files = "@zig_sdk//:zig",
+            dwp_files = "@zig_sdk//:empty",
+            objcopy_files = "@zig_sdk//:empty",
+            strip_files = "@zig_sdk//:empty",
             supports_param_files = 0,
         )
 
         # register two kinds of toolchain targets: Go and Zig conventions.
         # Go convention: amd64/arm64, linux/darwin
         native.toolchain(
-            name = gotarget + "_toolchain",
+            name = gotarget,
             exec_compatible_with = None,
             target_compatible_with = target_config.constraint_values,
-            toolchain = ":%s_toolchain_cc" % zigtarget,
+            toolchain = ":%s_cc" % zigtarget,
             toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
         )
 
         # Zig convention: x86_64/aarch64, linux/macos
         native.toolchain(
-            name = zigtarget + "_toolchain",
+            name = zigtarget,
             exec_compatible_with = None,
             target_compatible_with = target_config.constraint_values,
-            toolchain = ":%s_toolchain_cc" % zigtarget,
+            toolchain = ":%s_cc" % zigtarget,
             toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
         )
-
diff --git a/toolchain/toolchain/BUILD b/toolchain/toolchain/BUILD
new file mode 100644
index 0000000..e69de29
diff --git a/toolchain/toolchain/BUILD.sdk.bazel b/toolchain/toolchain/BUILD.sdk.bazel
new file mode 100644
index 0000000..4b505dc
--- /dev/null
+++ b/toolchain/toolchain/BUILD.sdk.bazel
@@ -0,0 +1,10 @@
+load("@bazel-zig-cc//toolchain:defs.bzl", "declare_toolchains")
+
+package(
+    default_visibility = ["//visibility:public"],
+)
+
+declare_toolchains(
+    absolute_path = {absolute_path},
+    zig_include_root = {zig_include_root},
+)
-- 
2.34.1

---

From: ~laurynasl <[email-masked]>
Date: Wed, 06 Apr 2022 20:10:45 +0000

---
 toolchain/defs.bzl                  | 214 +---------------------------
 toolchain/private/BUILD             |   0
 toolchain/private/defs.bzl          | 124 ++++++++++++++++
 toolchain/toolchain/BUILD.sdk.bazel |   2 +-
 toolchain/toolchain/defs.bzl        |  87 +++++++++++
 5 files changed, 215 insertions(+), 212 deletions(-)
 create mode 100644 toolchain/private/BUILD
 create mode 100644 toolchain/private/defs.bzl
 create mode 100644 toolchain/toolchain/defs.bzl

diff --git a/toolchain/defs.bzl b/toolchain/defs.bzl
index 61e099f..084af86 100644
--- a/toolchain/defs.bzl
+++ b/toolchain/defs.bzl
@@ -1,23 +1,7 @@
 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(":zig_toolchain.bzl", "zig_cc_toolchain_config")
-
-DEFAULT_TOOL_PATHS = {
-    "ar": "ar",
-    "gcc": "c++",  # https://github.com/bazelbuild/bazel/issues/4644
-    "cpp": "/usr/bin/false",
-    "gcov": "/usr/bin/false",
-    "nm": "/usr/bin/false",
-    "objdump": "/usr/bin/false",
-    "strip": "/usr/bin/false",
-}.items()
-
-DEFAULT_INCLUDE_DIRECTORIES = [
-    "include",
-    "libcxx/include",
-    "libcxxabi/include",
-]
+load("@bazel-zig-cc//toolchain/private:defs.bzl", "DEFAULT_INCLUDE_DIRECTORIES", "ZIG_TOOL_PATH", "target_structs")
 
 _fcntl_map = """
 GLIBC_2.2.5 {
@@ -32,114 +16,6 @@ __asm__(".symver fcntl64, [email-masked]");
 #endif
 """
 
-# Zig supports even older glibcs than defined below, but we have tested only
-# down to 2.17.
-# $ zig targets | jq -r '.glibc[]' | sort -V
-_GLIBCS = [
-    "2.17",
-    "2.18",
-    "2.19",
-    "2.22",
-    "2.23",
-    "2.24",
-    "2.25",
-    "2.26",
-    "2.27",
-    "2.28",
-    "2.29",
-    "2.30",
-    "2.31",
-    "2.32",
-    "2.33",
-    "2.34",
-]
-
-def _target_darwin(gocpu, zigcpu):
-    min_os = "10"
-    if zigcpu == "aarch64":
-        min_os = "11"
-    return struct(
-        gotarget = "darwin_{}".format(gocpu),
-        zigtarget = "{}-macos-gnu".format(zigcpu),
-        includes = [
-            "libunwind/include",
-            # TODO: Define a toolchain for each minimum OS version
-            "libc/include/{}-macos.{}-gnu".format(zigcpu, min_os),
-            "libc/include/any-macos.{}-any".format(min_os),
-            "libc/include/any-macos-any",
-        ],
-        linkopts = [],
-        copts = [],
-        bazel_target_cpu = "darwin",
-        constraint_values = [
-            "@platforms//os:macos",
-            "@platforms//cpu:{}".format(zigcpu),
-        ],
-        tool_paths = {"ld": "ld64.lld"},
-    )
-
-def _target_linux_gnu(gocpu, zigcpu, glibc_version = ""):
-    glibc_suffix = "gnu"
-    if glibc_version != "":
-        glibc_suffix = "gnu.{}".format(glibc_version)
-
-    # https://github.com/ziglang/zig/issues/5882#issuecomment-888250676
-    # fcntl_hack is only required for glibc 2.27 or less. We assume that
-    # glibc_version == "" (autodetect) is running a recent glibc version, thus
-    # adding this hack only when glibc is explicitly 2.27 or lower.
-    fcntl_hack = False
-    if glibc_version == "":
-        # zig doesn't reliably detect the glibc version, so
-        # often falls back to 2.17; the hack should be included.
-        # https://github.com/ziglang/zig/issues/6469
-        fcntl_hack = True
-    else:
-        # hack is required for 2.27 or less.
-        fcntl_hack = glibc_version < "2.28"
-
-    return struct(
-        gotarget = "linux_{}_{}".format(gocpu, glibc_suffix),
-        zigtarget = "{}-linux-{}".format(zigcpu, glibc_suffix),
-        includes = [
-            "libunwind/include",
-            "libc/include/generic-glibc",
-            "libc/include/any-linux-any",
-            "libc/include/{}-linux-gnu".format(zigcpu),
-            "libc/include/{}-linux-any".format(zigcpu),
-        ] + (["libc/include/x86-linux-any"] if zigcpu == "x86_64" else []),
-        toplevel_include = ["glibc-hacks"] if fcntl_hack else [],
-        compiler_extra_includes = ["glibc-hacks/glibchack-fcntl.h"] if fcntl_hack else [],
-        linker_version_scripts = ["glibc-hacks/fcntl.map"] if fcntl_hack else [],
-        linkopts = ["-lc++", "-lc++abi"],
-        copts = [],
-        bazel_target_cpu = "k8",
-        constraint_values = [
-            "@platforms//os:linux",
-            "@platforms//cpu:{}".format(zigcpu),
-        ],
-        tool_paths = {"ld": "ld.lld"},
-    )
-
-def _target_linux_musl(gocpu, zigcpu):
-    return struct(
-        gotarget = "linux_{}_musl".format(gocpu),
-        zigtarget = "{}-linux-musl".format(zigcpu),
-        includes = [
-            "libc/include/generic-musl",
-            "libc/include/any-linux-any",
-            "libc/include/{}-linux-musl".format(zigcpu),
-            "libc/include/{}-linux-any".format(zigcpu),
-        ] + (["libc/include/x86-linux-any"] if zigcpu == "x86_64" else []),
-        linkopts = ["-s", "-w"],
-        copts = ["-D_LIBCPP_HAS_MUSL_LIBC", "-D_LIBCPP_HAS_THREAD_API_PTHREAD"],
-        bazel_target_cpu = "k8",
-        constraint_values = [
-            "@platforms//os:linux",
-            "@platforms//cpu:{}".format(zigcpu),
-        ],
-        tool_paths = {"ld": "ld.lld"},
-    )
-
 # Official recommended version. Should use this when we have a usable release.
 URL_FORMAT_RELEASE = "https://ziglang.org/download/{version}/zig-{host_platform}-{version}.tar.xz"
 
@@ -192,7 +68,6 @@ def register_toolchains(
     toolchains = ["@zig_sdk//:toolchain:%s" % t for t in register]
     native.register_toolchains(*toolchains)
 
-ZIG_TOOL_PATH = "tools/{zig_tool}"
 ZIG_TOOL_WRAPPER = """#!/bin/bash
 set -e
 
@@ -297,14 +172,7 @@ zig_repository = repository_rule(
     implementation = _zig_repository_impl,
 )
 
-def _target_structs():
-    ret = []
-    for zigcpu, gocpu in (("x86_64", "amd64"), ("aarch64", "arm64")):
-        ret.append(_target_darwin(gocpu, zigcpu))
-        ret.append(_target_linux_musl(gocpu, zigcpu))
-        for glibc in [""] + _GLIBCS:
-            ret.append(_target_linux_gnu(gocpu, zigcpu, glibc))
-    return ret
+
 
 def filegroup(name, **kwargs):
     native.filegroup(name = name, **kwargs)
@@ -317,84 +185,8 @@ def declare_files(zig_include_root):
 
     lazy_filegroups = {}
 
-    for target_config in _target_structs():
+    for target_config in target_structs():
         for d in DEFAULT_INCLUDE_DIRECTORIES + target_config.includes:
             d = zig_include_root + d
             if d not in lazy_filegroups:
                 lazy_filegroups[d] = filegroup(name = d, srcs = native.glob([d + "/**"]))
-
-
-def declare_toolchains(absolute_path, zig_include_root):
-    for target_config in _target_structs():
-        gotarget = target_config.gotarget
-        zigtarget = target_config.zigtarget
-
-        cxx_builtin_include_directories = []
-        for d in DEFAULT_INCLUDE_DIRECTORIES + target_config.includes:
-            d = zig_include_root + d
-            cxx_builtin_include_directories.append(absolute_path + "/" + d)
-        for d in getattr(target_config, "toplevel_include", []):
-            cxx_builtin_include_directories.append(absolute_path + "/" + d)
-
-        absolute_tool_paths = {}
-        for name, path in target_config.tool_paths.items() + DEFAULT_TOOL_PATHS:
-            if path[0] == "/":
-                absolute_tool_paths[name] = path
-                continue
-            tool_path = ZIG_TOOL_PATH.format(zig_tool = path)
-            absolute_tool_paths[name] = "%s/%s" % (absolute_path, tool_path)
-
-        linkopts = target_config.linkopts
-        copts = target_config.copts
-        for s in getattr(target_config, "linker_version_scripts", []):
-            linkopts = linkopts + ["-Wl,--version-script,%s/%s" % (absolute_path, s)]
-        for incl in getattr(target_config, "compiler_extra_includes", []):
-            copts = copts + ["-include", absolute_path + "/" + incl]
-
-        zig_cc_toolchain_config(
-            name = zigtarget + "_cc_config",
-            target = zigtarget,
-            tool_paths = absolute_tool_paths,
-            cxx_builtin_include_directories = cxx_builtin_include_directories,
-            copts = copts,
-            linkopts = linkopts,
-            target_cpu = target_config.bazel_target_cpu,
-            target_system_name = "unknown",
-            target_libc = "unknown",
-            compiler = "clang",
-            abi_version = "unknown",
-            abi_libc_version = "unknown",
-        )
-
-        native.cc_toolchain(
-            name = zigtarget + "_cc",
-            toolchain_identifier = zigtarget + "-toolchain",
-            toolchain_config = ":%s_cc_config" % zigtarget,
-            all_files = "@zig_sdk//:zig",
-            ar_files = "@zig_sdk//:zig",
-            compiler_files = "@zig_sdk//:zig",
-            linker_files = "@zig_sdk//:zig",
-            dwp_files = "@zig_sdk//:empty",
-            objcopy_files = "@zig_sdk//:empty",
-            strip_files = "@zig_sdk//:empty",
-            supports_param_files = 0,
-        )
-
-        # 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 = ":%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_config.constraint_values,
-            toolchain = ":%s_cc" % zigtarget,
-            toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
-        )
diff --git a/toolchain/private/BUILD b/toolchain/private/BUILD
new file mode 100644
index 0000000..e69de29
diff --git a/toolchain/private/defs.bzl b/toolchain/private/defs.bzl
new file mode 100644
index 0000000..8380071
--- /dev/null
+++ b/toolchain/private/defs.bzl
@@ -0,0 +1,124 @@
+DEFAULT_INCLUDE_DIRECTORIES = [
+    "include",
+    "libcxx/include",
+    "libcxxabi/include",
+]
+
+ZIG_TOOL_PATH = "tools/{zig_tool}"
+
+# Zig supports even older glibcs than defined below, but we have tested only
+# down to 2.17.
+# $ zig targets | jq -r '.glibc[]' | sort -V
+_GLIBCS = [
+    "2.17",
+    "2.18",
+    "2.19",
+    "2.22",
+    "2.23",
+    "2.24",
+    "2.25",
+    "2.26",
+    "2.27",
+    "2.28",
+    "2.29",
+    "2.30",
+    "2.31",
+    "2.32",
+    "2.33",
+    "2.34",
+]
+
+def target_structs():
+    ret = []
+    for zigcpu, gocpu in (("x86_64", "amd64"), ("aarch64", "arm64")):
+        ret.append(_target_darwin(gocpu, zigcpu))
+        ret.append(_target_linux_musl(gocpu, zigcpu))
+        for glibc in [""] + _GLIBCS:
+            ret.append(_target_linux_gnu(gocpu, zigcpu, glibc))
+    return ret
+
+def _target_darwin(gocpu, zigcpu):
+    min_os = "10"
+    if zigcpu == "aarch64":
+        min_os = "11"
+    return struct(
+        gotarget = "darwin_{}".format(gocpu),
+        zigtarget = "{}-macos-gnu".format(zigcpu),
+        includes = [
+            "libunwind/include",
+            # TODO: Define a toolchain for each minimum OS version
+            "libc/include/{}-macos.{}-gnu".format(zigcpu, min_os),
+            "libc/include/any-macos.{}-any".format(min_os),
+            "libc/include/any-macos-any",
+        ],
+        linkopts = [],
+        copts = [],
+        bazel_target_cpu = "darwin",
+        constraint_values = [
+            "@platforms//os:macos",
+            "@platforms//cpu:{}".format(zigcpu),
+        ],
+        tool_paths = {"ld": "ld64.lld"},
+    )
+
+def _target_linux_gnu(gocpu, zigcpu, glibc_version = ""):
+    glibc_suffix = "gnu"
+    if glibc_version != "":
+        glibc_suffix = "gnu.{}".format(glibc_version)
+
+    # https://github.com/ziglang/zig/issues/5882#issuecomment-888250676
+    # fcntl_hack is only required for glibc 2.27 or less. We assume that
+    # glibc_version == "" (autodetect) is running a recent glibc version, thus
+    # adding this hack only when glibc is explicitly 2.27 or lower.
+    fcntl_hack = False
+    if glibc_version == "":
+        # zig doesn't reliably detect the glibc version, so
+        # often falls back to 2.17; the hack should be included.
+        # https://github.com/ziglang/zig/issues/6469
+        fcntl_hack = True
+    else:
+        # hack is required for 2.27 or less.
+        fcntl_hack = glibc_version < "2.28"
+
+    return struct(
+        gotarget = "linux_{}_{}".format(gocpu, glibc_suffix),
+        zigtarget = "{}-linux-{}".format(zigcpu, glibc_suffix),
+        includes = [
+            "libunwind/include",
+            "libc/include/generic-glibc",
+            "libc/include/any-linux-any",
+            "libc/include/{}-linux-gnu".format(zigcpu),
+            "libc/include/{}-linux-any".format(zigcpu),
+        ] + (["libc/include/x86-linux-any"] if zigcpu == "x86_64" else []),
+        toplevel_include = ["glibc-hacks"] if fcntl_hack else [],
+        compiler_extra_includes = ["glibc-hacks/glibchack-fcntl.h"] if fcntl_hack else [],
+        linker_version_scripts = ["glibc-hacks/fcntl.map"] if fcntl_hack else [],
+        linkopts = ["-lc++", "-lc++abi"],
+        copts = [],
+        bazel_target_cpu = "k8",
+        constraint_values = [
+            "@platforms//os:linux",
+            "@platforms//cpu:{}".format(zigcpu),
+        ],
+        tool_paths = {"ld": "ld.lld"},
+    )
+
+def _target_linux_musl(gocpu, zigcpu):
+    return struct(
+        gotarget = "linux_{}_musl".format(gocpu),
+        zigtarget = "{}-linux-musl".format(zigcpu),
+        includes = [
+            "libc/include/generic-musl",
+            "libc/include/any-linux-any",
+            "libc/include/{}-linux-musl".format(zigcpu),
+            "libc/include/{}-linux-any".format(zigcpu),
+        ] + (["libc/include/x86-linux-any"] if zigcpu == "x86_64" else []),
+        linkopts = ["-s", "-w"],
+        copts = ["-D_LIBCPP_HAS_MUSL_LIBC", "-D_LIBCPP_HAS_THREAD_API_PTHREAD"],
+        bazel_target_cpu = "k8",
+        constraint_values = [
+            "@platforms//os:linux",
+            "@platforms//cpu:{}".format(zigcpu),
+        ],
+        tool_paths = {"ld": "ld.lld"},
+    )
diff --git a/toolchain/toolchain/BUILD.sdk.bazel b/toolchain/toolchain/BUILD.sdk.bazel
index 4b505dc..7cbca73 100644
--- a/toolchain/toolchain/BUILD.sdk.bazel
+++ b/toolchain/toolchain/BUILD.sdk.bazel
@@ -1,4 +1,4 @@
-load("@bazel-zig-cc//toolchain:defs.bzl", "declare_toolchains")
+load("@bazel-zig-cc//toolchain/toolchain:defs.bzl", "declare_toolchains")
 
 package(
     default_visibility = ["//visibility:public"],
diff --git a/toolchain/toolchain/defs.bzl b/toolchain/toolchain/defs.bzl
new file mode 100644
index 0000000..1b0c087
--- /dev/null
+++ b/toolchain/toolchain/defs.bzl
@@ -0,0 +1,87 @@
+load("@bazel-zig-cc//toolchain:zig_toolchain.bzl", "zig_cc_toolchain_config")
+load("@bazel-zig-cc//toolchain/private:defs.bzl", "DEFAULT_INCLUDE_DIRECTORIES", "ZIG_TOOL_PATH", "target_structs")
+
+DEFAULT_TOOL_PATHS = {
+    "ar": "ar",
+    "gcc": "c++",  # https://github.com/bazelbuild/bazel/issues/4644
+    "cpp": "/usr/bin/false",
+    "gcov": "/usr/bin/false",
+    "nm": "/usr/bin/false",
+    "objdump": "/usr/bin/false",
+    "strip": "/usr/bin/false",
+}.items()
+
+def declare_toolchains(absolute_path, zig_include_root):
+    for target_config in target_structs():
+        gotarget = target_config.gotarget
+        zigtarget = target_config.zigtarget
+
+        cxx_builtin_include_directories = []
+        for d in DEFAULT_INCLUDE_DIRECTORIES + target_config.includes:
+            d = zig_include_root + d
+            cxx_builtin_include_directories.append(absolute_path + "/" + d)
+        for d in getattr(target_config, "toplevel_include", []):
+            cxx_builtin_include_directories.append(absolute_path + "/" + d)
+
+        absolute_tool_paths = {}
+        for name, path in target_config.tool_paths.items() + DEFAULT_TOOL_PATHS:
+            if path[0] == "/":
+                absolute_tool_paths[name] = path
+                continue
+            tool_path = ZIG_TOOL_PATH.format(zig_tool = path)
+            absolute_tool_paths[name] = "%s/%s" % (absolute_path, tool_path)
+
+        linkopts = target_config.linkopts
+        copts = target_config.copts
+        for s in getattr(target_config, "linker_version_scripts", []):
+            linkopts = linkopts + ["-Wl,--version-script,%s/%s" % (absolute_path, s)]
+        for incl in getattr(target_config, "compiler_extra_includes", []):
+            copts = copts + ["-include", absolute_path + "/" + incl]
+
+        zig_cc_toolchain_config(
+            name = zigtarget + "_cc_config",
+            target = zigtarget,
+            tool_paths = absolute_tool_paths,
+            cxx_builtin_include_directories = cxx_builtin_include_directories,
+            copts = copts,
+            linkopts = linkopts,
+            target_cpu = target_config.bazel_target_cpu,
+            target_system_name = "unknown",
+            target_libc = "unknown",
+            compiler = "clang",
+            abi_version = "unknown",
+            abi_libc_version = "unknown",
+        )
+
+        native.cc_toolchain(
+            name = zigtarget + "_cc",
+            toolchain_identifier = zigtarget + "-toolchain",
+            toolchain_config = ":%s_cc_config" % zigtarget,
+            all_files = "@zig_sdk//:zig",
+            ar_files = "@zig_sdk//:zig",
+            compiler_files = "@zig_sdk//:zig",
+            linker_files = "@zig_sdk//:zig",
+            dwp_files = "@zig_sdk//:empty",
+            objcopy_files = "@zig_sdk//:empty",
+            strip_files = "@zig_sdk//:empty",
+            supports_param_files = 0,
+        )
+
+        # 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 = ":%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_config.constraint_values,
+            toolchain = ":%s_cc" % zigtarget,
+            toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
+        )
-- 
2.34.1