guix: Build for macOS using LLVM toolchain only
What changed, and why it matters
This commit changes how Bitcoin Core's official macOS builds are produced, switching the build tools from the GNU compiler collection (GCC) to the LLVM/Clang toolchain. It does not change the Bitcoin software itself, only the compiler and linker scripts used to create macOS release binaries. There is no direct security bug visible in the diff, but any toolchain change can affect build reproducibility and the final binary layout.
Treat as a build-hardening/maintenance change. Verify that the new LLVM-based macOS build reproduces deterministically against prior release binaries before shipping. Run the existing Guix reproducibility checks and compare hashes. No immediate code-level remediation is required.
Security signals we found
Toolchain swap in release build pipeline
New linker flags introduced: -fuse-ld=lld -rtlib=compiler-rt -unwindlib=libunwind
Build reproducibility may be affected by compiler/runtime change
No direct vulnerability or bug fix present in diff
Evidence from the diff
The patch updates Guix reproducible-build scripts for macOS targets to use clang-toolchain-19, libcxx, lld-19, and the corresponding LLVM binutils (llvm-ar, llvm-ranlib, llvm-objdump, llvm-nm, llvm-strip) instead of gcc-toolchain-14. It threads new build_* variables into depends/Makefile invocations and adds CMAKE_AR overrides for Qt builds. The manifest now conditionally includes gcc-toolchain-14 only for Windows and Linux targets. No runtime code, consensus code, or cryptographic code is modified.
Changed components
contrib/guix/libexec/build_macos.shcontrib/guix/libexec/build_macos_gui.shcontrib/guix/manifest_build.scmdepends/packages/native_qt.mkdepends/packages/qt.mkInspect captured patch +51 / −20
diff --git a/contrib/guix/libexec/build_macos.sh b/contrib/guix/libexec/build_macos.sh
index 213ae9a6..f8e42e1b 100755
--- a/contrib/guix/libexec/build_macos.sh
+++ b/contrib/guix/libexec/build_macos.sh
@@ -8,13 +8,21 @@ set -o errexit -o pipefail
# shellcheck source=setup.sh
source "$(dirname "${BASH_SOURCE[0]}")/setup.sh"
-# Set environment variables to point the NATIVE toolchain to the right
-# includes/libs
-NATIVE_GCC="$(store_path gcc-toolchain)"
-
-# Set native toolchain
-build_CC="${NATIVE_GCC}/bin/gcc -isystem ${NATIVE_GCC}/include"
-build_CXX="${NATIVE_GCC}/bin/g++ -isystem ${NATIVE_GCC}/include/c++ -isystem ${NATIVE_GCC}/include"
+# Set toolchain
+CLANG_TOOLCHAIN="$(store_path clang-toolchain)"
+LIBCXX="$(store_path libcxx)"
+build_CC="${CLANG_TOOLCHAIN}/bin/clang \
+ -isystem ${CLANG_TOOLCHAIN}/include"
+build_CXX="${CLANG_TOOLCHAIN}/bin/clang++ \
+ -stdlib=libc++ \
+ -isystem ${LIBCXX}/include/c++/v1 \
+ -isystem ${CLANG_TOOLCHAIN}/include"
+build_LDFLAGS="-fuse-ld=lld -rtlib=compiler-rt -unwindlib=libunwind -L${LIBCXX}/lib -Wl,-rpath,${LIBCXX}/lib"
+build_AR="${CLANG_TOOLCHAIN}/bin/llvm-ar"
+build_RANLIB="${CLANG_TOOLCHAIN}/bin/llvm-ranlib"
+build_OBJDUMP="${CLANG_TOOLCHAIN}/bin/llvm-objdump"
+build_NM="${CLANG_TOOLCHAIN}/bin/llvm-nm"
+build_STRIP="${CLANG_TOOLCHAIN}/bin/llvm-strip"
# Build the depends tree
make -C depends --jobs="$JOBS" HOST="$HOST" \
@@ -24,6 +32,12 @@ make -C depends --jobs="$JOBS" HOST="$HOST" \
${SDK_PATH+SDK_PATH="$SDK_PATH"} \
${build_CC+build_CC="$build_CC"} \
${build_CXX+build_CXX="$build_CXX"} \
+ ${build_LDFLAGS+build_LDFLAGS="$build_LDFLAGS"} \
+ ${build_AR+build_AR="$build_AR"} \
+ ${build_RANLIB+build_RANLIB="$build_RANLIB"} \
+ ${build_OBJDUMP+build_OBJDUMP="$build_OBJDUMP"} \
+ ${build_NM+build_NM="$build_NM"} \
+ ${build_STRIP+build_STRIP="$build_STRIP"} \
NO_QT=1
mkdir -p "$DISTSRC"
diff --git a/contrib/guix/libexec/build_macos_gui.sh b/contrib/guix/libexec/build_macos_gui.sh
index 97f1932d..47ffe6c8 100755
--- a/contrib/guix/libexec/build_macos_gui.sh
+++ b/contrib/guix/libexec/build_macos_gui.sh
@@ -8,13 +8,21 @@ set -o errexit -o pipefail
# shellcheck source=setup.sh
source "$(dirname "${BASH_SOURCE[0]}")/setup.sh"
-# Set environment variables to point the NATIVE toolchain to the right
-# includes/libs
-NATIVE_GCC="$(store_path gcc-toolchain)"
-
-# Set native toolchain
-build_CC="${NATIVE_GCC}/bin/gcc -isystem ${NATIVE_GCC}/include"
-build_CXX="${NATIVE_GCC}/bin/g++ -isystem ${NATIVE_GCC}/include/c++ -isystem ${NATIVE_GCC}/include"
+# Set toolchain
+CLANG_TOOLCHAIN="$(store_path clang-toolchain)"
+LIBCXX="$(store_path libcxx)"
+build_CC="${CLANG_TOOLCHAIN}/bin/clang \
+ -isystem ${CLANG_TOOLCHAIN}/include"
+build_CXX="${CLANG_TOOLCHAIN}/bin/clang++ \
+ -stdlib=libc++ \
+ -isystem ${LIBCXX}/include/c++/v1 \
+ -isystem ${CLANG_TOOLCHAIN}/include"
+build_LDFLAGS="-fuse-ld=lld -rtlib=compiler-rt -unwindlib=libunwind -L${LIBCXX}/lib -Wl,-rpath,${LIBCXX}/lib"
+build_AR="${CLANG_TOOLCHAIN}/bin/llvm-ar"
+build_RANLIB="${CLANG_TOOLCHAIN}/bin/llvm-ranlib"
+build_OBJDUMP="${CLANG_TOOLCHAIN}/bin/llvm-objdump"
+build_NM="${CLANG_TOOLCHAIN}/bin/llvm-nm"
+build_STRIP="${CLANG_TOOLCHAIN}/bin/llvm-strip"
# Build the depends tree
make -C depends --jobs="$JOBS" HOST="$HOST" \
@@ -23,7 +31,13 @@ make -C depends --jobs="$JOBS" HOST="$HOST" \
${BASE_CACHE+BASE_CACHE="$BASE_CACHE"} \
${SDK_PATH+SDK_PATH="$SDK_PATH"} \
${build_CC+build_CC="$build_CC"} \
- ${build_CXX+build_CXX="$build_CXX"}
+ ${build_CXX+build_CXX="$build_CXX"} \
+ ${build_LDFLAGS+build_LDFLAGS="$build_LDFLAGS"} \
+ ${build_AR+build_AR="$build_AR"} \
+ ${build_RANLIB+build_RANLIB="$build_RANLIB"} \
+ ${build_OBJDUMP+build_OBJDUMP="$build_OBJDUMP"} \
+ ${build_NM+build_NM="$build_NM"} \
+ ${build_STRIP+build_STRIP="$build_STRIP"}
mkdir -p "$DISTSRC"
(
diff --git a/contrib/guix/manifest_build.scm b/contrib/guix/manifest_build.scm
index 919d2a34..3d908243 100644
--- a/contrib/guix/manifest_build.scm
+++ b/contrib/guix/manifest_build.scm
@@ -264,7 +264,6 @@ chain for " target " development."))
tar
gzip
;; Build tools
- gcc-toolchain-14
cmake-minimal
gnu-make
;; Scripting
@@ -273,12 +272,14 @@ chain for " target " development."))
git-minimal)
(let ((target (getenv "HOST")))
(cond ((string-suffix? "-mingw32" target)
- (list (make-mingw-pthreads-cross-toolchain target)))
+ (list gcc-toolchain-14
+ (make-mingw-pthreads-cross-toolchain target)))
((string-contains target "-linux-")
- (list (list gcc-toolchain-14 "static")
+ (list gcc-toolchain-14
+ (list gcc-toolchain-14 "static")
(make-bitcoin-cross-toolchain target)))
((string-contains target "darwin")
(list clang-toolchain-19
- lld-19
- (make-lld-wrapper lld-19 #:lld-as-ld? #t)))
+ libcxx ;; 19.1.7
+ lld-19))
(else '())))))
diff --git a/depends/packages/native_qt.mk b/depends/packages/native_qt.mk
index 2bf088c1..c975c1e9 100644
--- a/depends/packages/native_qt.mk
+++ b/depends/packages/native_qt.mk
@@ -94,6 +94,7 @@ $(package)_config_env += OBJCXX="$$(build_CXX)"
endif
$(package)_cmake_opts := -DCMAKE_EXE_LINKER_FLAGS="$$(build_LDFLAGS)"
+$(package)_cmake_opts += -DCMAKE_AR="$$(build_AR)"
ifneq ($(V),)
$(package)_cmake_opts += --log-level=STATUS
endif
diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk
index 500a2729..3e4c5fcb 100644
--- a/depends/packages/qt.mk
+++ b/depends/packages/qt.mk
@@ -198,6 +198,7 @@ endif
$(package)_cmake_opts += -DCMAKE_EXE_LINKER_FLAGS="$$($$($(package)_type)_LDFLAGS)"
$(package)_cmake_opts += -DCMAKE_EXE_LINKER_FLAGS_RELEASE="$$($$($(package)_type)_release_LDFLAGS)"
$(package)_cmake_opts += -DCMAKE_EXE_LINKER_FLAGS_DEBUG="$$($$($(package)_type)_debug_LDFLAGS)"
+$(package)_cmake_opts += -DCMAKE_AR="$$($(package)_ar)"
ifneq ($(host),$(build))
$(package)_cmake_opts += -DCMAKE_SYSTEM_NAME=$($(host_os)_cmake_system_name)
Why this scored 18/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.