Skip to content

Commit e823004

Browse files
authored
Merge pull request #10812 from oharboe/hermetic-llvm-toolchain
bazel: switch C++ toolchain to hermetic-llvm; add etc/bazel-hermetic
2 parents 17f494d + 2d533a6 commit e823004

17 files changed

Lines changed: 1126 additions & 144 deletions

.bazelrc

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,13 @@ common --enable_platform_specific_config
9696
# macOS: boost.stacktrace needs this since backtrace() doesn't require GNU source
9797
build:macos --copt=-DBOOST_STACKTRACE_GNU_SOURCE_NOT_REQUIRED
9898
build:macos --host_copt=-DBOOST_STACKTRACE_GNU_SOURCE_NOT_REQUIRED
99-
# Aligned allocation/deallocation for abseil is only available since 10.13
100-
build:macos --macos_minimum_os=10.13
101-
build:macos --host_macos_minimum_os=10.13
99+
# Floating-point std::to_chars (behind std::format, used by OpenSTA)
100+
# needs macOS 13.3; std::filesystem (src/tcl_readline_setup.cc) needs
101+
# 10.15; abseil's aligned allocation needs 10.13. The historical 10.13
102+
# floor was never enforced: toolchains_llvm ignored it and compiled
103+
# against the host SDK's default. hermetic-llvm honors it.
104+
build:macos --macos_minimum_os=13.3
105+
build:macos --host_macos_minimum_os=13.3
102106

103107
# Settings for --config=asan address sanitizer build
104108
build:asan --strip=never
@@ -123,6 +127,9 @@ build:profile --copt -fno-omit-frame-pointer --host_copt -fno-omit-frame-pointer
123127
# Improve hermeticity by disallowing user envars and network access
124128
build --incompatible_strict_action_env
125129
build --nosandbox_default_allow_network
130+
# Refuse to autodetect a local C++ toolchain (/usr/bin/gcc); the hermetic
131+
# toolchain must win resolution, with or without the etc/bazel-hermetic wrapper.
132+
common --repo_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1
126133

127134
test --build_tests_only
128135

@@ -142,6 +149,11 @@ build:ci --disk_cache=
142149
# Tell the 'ci' config to include 'opt'
143150
build:ci --config=opt
144151

152+
# Launch py_binary via a shell stub instead of rules_python's legacy python
153+
# stub, whose '#!/usr/bin/env python3' shebang needs a host python3 before
154+
# the hermetic interpreter takes over (found by etc/bazel-hermetic).
155+
common --@rules_python//python/config_settings:bootstrap_impl=script
156+
145157
# Setup remote cache
146158
# Anon: HTTPS read-only cache
147159
build --remote_cache=https://bazel.precisioninno.com

MODULE.bazel

Lines changed: 109 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,35 @@ bazel_dep(name = "rules_python", version = "1.8.5")
3434
bazel_dep(name = "rules_shell", version = "0.6.1")
3535
bazel_dep(name = "swig", version = "4.3.0.bcr.2")
3636

37-
# bison is transitive (rules_bison -> bison). Its vendored gnulib headers
38-
# deliberately shadow libc headers; under toolchains that inject libc
39-
# headers as leading -isystem entries (hermetic-llvm, #10812) the shadowing
40-
# breaks and bison@3.8.2.bcr.5 fails to compile (O_BINARY, BCR #7642).
41-
# 3.8.2.bcr.7 fixes most of it (a small remainder is patched in #10812
42-
# pending a proposed 3.8.2.bcr.8).
37+
# bison is transitive (rules_bison -> bison). Same gnulib libc-header
38+
# shadowing class as sed/gawk/m4 under hermetic-llvm (BCR #7642).
39+
# 3.8.2.bcr.7 fixes lib/ but src/ still picks up raw libc headers; the
40+
# patch restores gnulib wrapper-header precedence via -I (to be proposed
41+
# upstream as 3.8.2.bcr.8, then drop).
4342
single_version_override(
4443
module_name = "bison",
44+
patch_strip = 1,
45+
patches = [
46+
"//bazel/bison-patches:0001-gnulib-wrapper-headers-use-I-not-isystem.patch",
47+
],
4548
version = "3.8.2.bcr.7",
4649
)
4750

4851
BOOST_VERSION = "1.89.0.bcr.2"
4952

53+
# boost::icl's exclusive_less_than comparator violates strict weak ordering
54+
# (boostorg/icl#51); libc++'s std::map exposes it, leaving phantom intervals
55+
# after interval_set subtraction (boostorg/icl#55) — pad IO fillers were
56+
# placed on top of pads. Upstream fix boostorg/icl@7de3f55655 (#54), merged
57+
# after boost 1.90. Drop when a boost.icl release containing it lands in BCR.
58+
single_version_override(
59+
module_name = "boost.icl",
60+
patch_strip = 1,
61+
patches = [
62+
"//bazel/boost-icl-patches:0001-refactor-interval-lookup-operations-icl-54.patch",
63+
],
64+
)
65+
5066
bazel_dep(name = "boost.algorithm", version = BOOST_VERSION)
5167
bazel_dep(name = "boost.asio", version = BOOST_VERSION)
5268
bazel_dep(name = "boost.beast", version = BOOST_VERSION)
@@ -88,11 +104,10 @@ bazel_dep(name = "cudd", version = "3.0.0.bcr.2")
88104
bazel_dep(name = "eigen", version = "3.4.0.bcr.3")
89105
bazel_dep(name = "fmt", version = "11.2.0.bcr.1")
90106

91-
# gawk is transitive (abc -> ncurses -> gawk; yosys -> gawk). Its vendored
92-
# gnulib headers deliberately shadow libc headers; under toolchains that
93-
# inject libc headers as leading -isystem entries (hermetic-llvm, #10812)
94-
# the shadowing breaks and gawk fails to compile (BCR #7642).
95-
# 5.3.2.bcr.7 carries the upstream BCR fix (BCR #7989).
107+
# gawk is transitive (abc -> ncurses -> gawk; yosys -> gawk). Same gnulib
108+
# libc-header shadowing as sed: gawk@5.3.2.bcr.2 fails to compile against
109+
# hermetic-llvm's explicit libc -isystem entries (BCR #7642). 5.3.2.bcr.7
110+
# carries the upstream fix (BCR #7989).
96111
single_version_override(
97112
module_name = "gawk",
98113
version = "5.3.2.bcr.7",
@@ -101,21 +116,41 @@ single_version_override(
101116
bazel_dep(name = "git", version = "2.54.0")
102117
bazel_dep(name = "googletest", version = "1.17.0.bcr.2")
103118

104-
# m4 is transitive (rules_bison/rules_flex -> m4). Its vendored gnulib
105-
# headers deliberately shadow libc headers; under toolchains that inject
106-
# libc headers as leading -isystem entries (hermetic-llvm, #10812) the
107-
# shadowing breaks and m4@1.4.21 fails to compile (O_SEARCH, BCR #7642).
108-
# 1.4.21.bcr.4 carries the upstream fix.
119+
# m4 is transitive (rules_bison/rules_flex -> m4). Same gnulib libc-header
120+
# shadowing class as sed/gawk under hermetic-llvm (BCR #7642).
109121
single_version_override(
110122
module_name = "m4",
111123
version = "1.4.21.bcr.4",
112124
)
113125

114126
bazel_dep(name = "openmp", version = "21.1.5.bcr.2")
115127
bazel_dep(name = "or-tools", version = "9.15")
128+
129+
# sed is transitive (abc -> ncurses -> sed). Its vendored gnulib headers
130+
# deliberately shadow libc headers (stdio.h, error.h); hermetic-llvm's
131+
# explicit libc -isystem entries outrank them and sed@4.9.bcr.3 fails to
132+
# compile (BCR #7642). 4.9.bcr.5 carries the upstream fix (BCR #7915).
133+
single_version_override(
134+
module_name = "sed",
135+
version = "4.9.bcr.5",
136+
)
137+
116138
bazel_dep(name = "spdlog", version = "1.15.1")
117139
bazel_dep(name = "sv-lang", version = "10.0.1-20260316-f04e8156")
118140
bazel_dep(name = "tcl_lang", version = "9.0.2.bcr.1")
141+
142+
# tclZipfs.c's '#include "crypt.h"' picks up glibc's crypt.h instead of the
143+
# vendored minizip one when glibc headers are explicit -isystem directories
144+
# (hermetic-llvm zero-sysroot toolchain). Drop when fixed in a tcl_lang
145+
# BCR release.
146+
single_version_override(
147+
module_name = "tcl_lang",
148+
patch_strip = 1,
149+
patches = [
150+
"//bazel/tcl-patches:0001-tclZipfs-include-vendored-minizip-crypt.h-by-path.patch",
151+
],
152+
)
153+
119154
bazel_dep(name = "tcmalloc", version = "0.0.0-20250927-12f2552")
120155
bazel_dep(name = "yaml-cpp", version = "0.9.0")
121156
bazel_dep(name = "zlib", version = "1.3.1.bcr.8")
@@ -134,7 +169,12 @@ git_override(
134169

135170
## Lock the compiler version and avoid any local compiler.
136171
## Downstream consumers must configure their own C++ toolchain.
137-
bazel_dep(name = "toolchains_llvm", version = "1.5.0", dev_dependency = True)
172+
##
173+
## hermetic-llvm (BCR module "llvm") provides statically linked LLVM
174+
## binaries and a zero-sysroot cc_toolchain: no host compiler, linker,
175+
## libxml2 or /usr/include involved, and it runs unmodified on distros
176+
## without FHS paths (e.g. NixOS).
177+
bazel_dep(name = "llvm", version = "0.8.11", dev_dependency = True)
138178

139179
# --- Dev dependencies (not propagated to downstream consumers) ---
140180

@@ -201,23 +241,63 @@ archive_override(
201241

202242
# --- Extensions ---
203243

204-
llvm = use_extension(
205-
"@toolchains_llvm//toolchain/extensions:llvm.bzl",
206-
"llvm",
207-
dev_dependency = True,
208-
)
209-
llvm.toolchain(
210-
llvm_version = "20.1.8",
211-
)
212-
use_repo(llvm, "llvm_toolchain", "llvm_toolchain_llvm")
213-
214-
# FYI: Comment out @llvm_toolchain//:all on NixOS and use the local clang toolchain instead.
215244
register_toolchains(
216-
"@llvm_toolchain//:all",
245+
"@llvm//toolchain:all",
217246
"@rules_verilator//verilator:verilator_toolchain",
218247
dev_dependency = True,
219248
)
220249

250+
# hermetic-llvm ships a minimal macOS SDK subset (frameworks are opt-in).
251+
# Qt (qt-bazel) needs the desktop frameworks; the first six entries are
252+
# hermetic-llvm's defaults, which listing any framework replaces.
253+
osx = use_extension("@llvm//extensions:osx.bzl", "osx", dev_dependency = True)
254+
osx.frameworks(names = [
255+
"CoreFoundation",
256+
"Foundation",
257+
"Kernel",
258+
"OSLog",
259+
"Security",
260+
"SystemConfiguration",
261+
"AppKit",
262+
"ApplicationServices",
263+
"CFNetwork",
264+
"Carbon",
265+
"Cocoa",
266+
"ColorSync",
267+
"CoreData",
268+
"CoreGraphics",
269+
"CoreImage",
270+
"CoreServices",
271+
"CoreText",
272+
"CoreVideo",
273+
"DiskArbitration",
274+
# ATS (inside the ApplicationServices umbrella) has .tbd symlinks into
275+
# the FontServices private framework; without it they dangle and bazel
276+
# rejects the sysroot ("file type is not supported").
277+
"FontServices",
278+
"GSS",
279+
"IOKit",
280+
"IOSurface",
281+
"ImageIO",
282+
"Metal",
283+
# MetalKit's MTKModel.h includes ModelIO/ModelIO.h.
284+
"MetalKit",
285+
"ModelIO",
286+
"OpenGL",
287+
# PrintCore is inside the ApplicationServices umbrella, but must be
288+
# named for the SDK subset to keep usr/include/cups (its ObjC headers
289+
# import <cups/ppd.h>).
290+
"PrintCore",
291+
"QuartzCore",
292+
# AppKit reaches these on macOS: NSImageView.h includes Symbols
293+
# unconditionally; NSText*.h take the non-UIKit branch into the
294+
# UIFoundation private framework; NSSharingService pulls CloudKit.
295+
"CloudKit",
296+
"Symbols",
297+
"UIFoundation",
298+
"UniformTypeIdentifiers",
299+
])
300+
221301
python = use_extension("@rules_python//python/extensions:python.bzl", "python")
222302
python.toolchain(
223303
ignore_root_user_error = True,

0 commit comments

Comments
 (0)