Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

llvmPackages.stdenv: make Darwin a “system” libc++ platform #347388

Draft
wants to merge 5 commits into
base: staging
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion pkgs/development/compilers/llvm/common/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
fetchpatch,
fetchpatch2,
overrideCC,
overrideLibcxx,
wrapCCWith,
wrapBintoolsWith,
buildLlvmTools, # tools, but from the previous stage, for cross
Expand Down Expand Up @@ -1040,7 +1041,19 @@ let
else
libraries.compiler-rt-libc;

stdenv = overrideCC stdenv buildLlvmTools.clang;
stdenv =
let
stdenv' = overrideCC stdenv buildLlvmTools.clang;
in
# Treat libc++ as a “system” library on Darwin where all versions use the same underlying libc++.
# Use libcxxStdenv to use a specific version of LLVM and libc++ regardless.
if
stdenv.targetPlatform.isDarwin
&& lib.versionOlder metadata.release_version (lib.getVersion stdenv.cc.libcxx)
then
overrideLibcxx stdenv'
else
stdenv';

libcxxStdenv = overrideCC stdenv buildLlvmTools.libcxxClang;

Expand Down
71 changes: 57 additions & 14 deletions pkgs/stdenv/adapters.nix
Original file line number Diff line number Diff line change
Expand Up @@ -56,30 +56,73 @@ rec {
assert stdenv.cc.libcxx != null;
assert pkgs.stdenv.cc.libcxx != null;
# only unified libcxx / libcxxabi stdenv's are supported
assert lib.versionAtLeast pkgs.stdenv.cc.libcxx.version "12";
assert lib.versionAtLeast stdenv.cc.libcxx.version "12";
assert lib.versionAtLeast (lib.getVersion pkgs.stdenv.cc.libcxx) "12";
assert lib.versionAtLeast (lib.getVersion stdenv.cc.libcxx) "12";
let
llvmLibcxxVersion = lib.getVersion llvmLibcxx;
stdenvLibcxxVersion = lib.getVersion stdenvLibcxx;

stdenvLibcxx = pkgs.stdenv.cc.libcxx;
llvmLibcxx = stdenv.cc.libcxx;

libcxx = pkgs.runCommand "${stdenvLibcxx.name}-${llvmLibcxxVersion}" {
outputs = [ "out" "dev" ];
isLLVM = true;
} ''
mkdir -p "$dev/nix-support"
ln -s '${stdenvLibcxx}' "$out"
echo '${stdenvLibcxx}' > "$dev/nix-support/propagated-build-inputs"
ln -s '${lib.getDev llvmLibcxx}/include' "$dev/include"
'';
} (
''
mkdir -p "$dev/nix-support"
ln -s '${lib.getDev llvmLibcxx}/include' "$dev/include"
''
+ (
# Use `tapi` on Darwin to generate stubs with only the symbols from the older libc++ version
# while still linking to the newer one.
if stdenv.hostPlatform.isDarwin then
''
mkdir -p "$out/lib"
for stdenvFile in '${stdenvLibcxx}'"/lib/"*; do
filename=$(basename "$stdenvFile")
llvmFile='${llvmLibcxx}'"/lib/$filename"
if isMachO "$stdenvFile"; then
tbdFile=$out/lib/''${filename%.*}.tbd
# Don’t run `tapi` on symlinks. Create updated symlinks pointing to the tbd instead.
if [ -L "$stdenvFile" ]; then
srcName=$(readlink "$stdenvFile")
ln -s "''${srcName%.*}.tbd" "$tbdFile"
else
${lib.getExe pkgs.pkgsBuildHost.libtapi} stubify "$llvmFile" --filetype=tbd-v4 -o "$tbdFile"
substituteInPlace "$tbdFile" --replace-fail "$llvmFile" "$stdenvFile"
fi
else
ln -s "$file" "$out/lib/$filename"
fi
done
echo "$out" > "$dev/nix-support/propagated-build-inputs"
''
else
''
ln -s '${stdenvLibcxx}' "$out"
echo '${stdenvLibcxx}' > "$dev/nix-support/propagated-build-inputs"
''
)
);
in
overrideCC stdenv (stdenv.cc.override {
inherit libcxx;
extraPackages = [
pkgs.buildPackages.targetPackages."llvmPackages_${lib.versions.major llvmLibcxxVersion}".compiler-rt
];
});
# Return the stdenv libc++ in case it’s the same version as the LLVM version. This can happen on Darwin
# when `overrideLibcxx` is used with an LLVM stdenv version that matches the default LLVM version.
if stdenvLibcxxVersion == llvmLibcxxVersion then
overrideCC stdenv (stdenv.cc.override {
libcxx = stdenvLibcxx;
extraPackages = [ pkgs.buildPackages.targetPackages.llvmPackages.compiler-rt ];
})
# Check the version for the stdenv’s libc++ version to avoid trying to override it multiple times.
else if lib.hasPrefix stdenvLibcxxVersion llvmLibcxxVersion then
stdenv
else
overrideCC stdenv (stdenv.cc.override {
inherit libcxx;
extraPackages = [
pkgs.buildPackages.targetPackages."llvmPackages_${lib.versions.major llvmLibcxxVersion}".compiler-rt
];
});

# Override the setup script of stdenv. Useful for testing new
# versions of the setup script without causing a rebuild of
Expand Down