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

Fix Darwin build on staging-next #322388

Merged
merged 12 commits into from
Jun 27, 2024
Merged
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
3 changes: 3 additions & 0 deletions pkgs/development/interpreters/python/cpython/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,9 @@ in with passthru; stdenv.mkDerivation (finalAttrs: {
(enableFeature enableGIL "gil")
] ++ optionals enableOptimizations [
"--enable-optimizations"
] ++ optionals (stdenv.isDarwin && configd == null) [
# Make conditional on Darwin for now to avoid causing Linux rebuilds.
"py_cv_module__scproxy=n/a"
] ++ optionals (sqlite != null) [
"--enable-loadable-sqlite-extensions"
] ++ optionals (libxcrypt != null) [
Expand Down
7 changes: 5 additions & 2 deletions pkgs/development/python-modules/cffi/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
pythonAtLeast,
}:

let
ccVersion = lib.getVersion stdenv.cc;
in
if isPyPy then
null
else
Expand Down Expand Up @@ -53,9 +56,9 @@ else
hash = "sha256-H5rFgRRTr27l5S6REo8+7dmPDQW7WXhP4f4DGZjdi+s=";
})
]
++ lib.optionals (stdenv.cc.isClang && lib.versionAtLeast (lib.getVersion stdenv.cc) "13") [
++ lib.optionals (stdenv.cc.isClang && (ccVersion == "boot" || lib.versionAtLeast ccVersion "13")) [
# -Wnull-pointer-subtraction is enabled with -Wextra. Suppress it to allow the following tests
# to run and pass when cffi is built with newer versions of clang:
# to run and pass when cffi is built with newer versions of clang (including the bootstrap tools clang on Darwin):
# - testing/cffi1/test_verify1.py::test_enum_usage
# - testing/cffi1/test_verify1.py::test_named_pointer_as_argument
./clang-pointer-substraction-warning.diff
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ appleDerivation' stdenv {
(cd $dep/include && find . -name '*.h' | copyHierarchy $out/include)
done

(cd ${buildPackages.darwin.cctools.dev}/include/mach-o && find . -name '*.h' | copyHierarchy $out/include/mach-o)
(cd ${lib.getDev buildPackages.darwin.cctools}/include/mach-o && find . -name '*.h' | copyHierarchy $out/include/mach-o)

for header in pthread.h pthread_impl.h pthread_spis.h sched.h; do
ln -s "$out/include/pthread/$header" "$out/include/$header"
Expand Down Expand Up @@ -142,7 +142,7 @@ appleDerivation' stdenv {
$out/lib

substituteInPlace $out/lib/libSystem.B.tbd \
--replace "/usr/lib/system/" "$out/lib/system/"
--replace-fail "/usr/lib/system/" "$out/lib/system/"
ln -s libSystem.B.tbd $out/lib/libSystem.tbd

# Set up links to pretend we work like a conventional unix (Apple's design, not mine!)
Expand Down
190 changes: 103 additions & 87 deletions pkgs/os-specific/darwin/binutils/default.nix
Original file line number Diff line number Diff line change
@@ -1,108 +1,124 @@
{ lib, stdenv, makeWrapper, binutils-unwrapped, cctools, llvm, clang-unwrapped, dualAs ? false }:

# Make sure both underlying packages claim to have prepended their binaries
# with the same targetPrefix.
assert binutils-unwrapped.targetPrefix == cctools.targetPrefix;
{
lib,
stdenvNoCC,
cctools,
clang-unwrapped,
llvm,
llvm-manpages,
makeWrapper,
enableManpages ? stdenvNoCC.targetPlatform == stdenvNoCC.hostPlatform,
}:

let
inherit (binutils-unwrapped) targetPrefix;
cmds = [
"ar" "ranlib" "as" "install_name_tool"
"ld" "strip" "otool" "lipo" "nm" "strings" "size"
inherit (stdenvNoCC) targetPlatform hostPlatform;
targetPrefix = lib.optionalString (targetPlatform != hostPlatform) "${targetPlatform.config}-";

llvm_cmds = [
"addr2line"
"ar"
"c++filt"
"dsymutil"
"nm"
"objcopy"
"objdump"
"otool"
"size"
"strings"
"strip"
];

cctools_cmds = [
"codesign_allocate"
"gprof"
"ranlib"
# Use the cctools versions because the LLVM ones can crash or fail when the cctools ones don’t.
# Revisit when LLVM is updated to LLVM 18 on Darwin.
"lipo"
"install_name_tool"
];
isCCToolsLLVM = lib.getName cctools == "cctools-llvm";
in

# TODO: loop over targetPrefixed binaries too
stdenv.mkDerivation {
pname = "${targetPrefix}cctools-binutils-darwin" + lib.optionalString dualAs "-dualas";
linkManPages =
pkg: source: target:
lib.optionalString enableManpages ''
sourcePath=${pkg}/share/man/man1/${source}.1.gz
targetPath=''${!outputMan}/share/man/man1/${target}.1.gz

if [ -f "$sourcePath" ]; then
mkdir -p "$(dirname "$targetPath")"
ln -s "$sourcePath" "$targetPath"
fi
'';
in
stdenvNoCC.mkDerivation {
pname = "${targetPrefix}cctools-binutils-darwin";
inherit (cctools) version;
outputs = [ "out" "man" ];

outputs = [ "out" ] ++ lib.optional enableManpages "man";

strictDeps = true;

nativeBuildInputs = [ makeWrapper ];

buildCommand = ''
mkdir -p $out/bin $out/include

ln -s ${binutils-unwrapped.out}/bin/${targetPrefix}c++filt $out/bin/${targetPrefix}c++filt

# We specifically need:
# - ld: binutils doesn't provide it on darwin
# - as: as above
# - ar: the binutils one produces .a files that the cctools ld doesn't like
# - ranlib: for compatibility with ar
# - otool: we use it for some of our name mangling
# - install_name_tool: we use it to rewrite stuff in our bootstrap tools
# - strip: the binutils one seems to break mach-o files
# - lipo: gcc build assumes it exists
# - nm: the gnu one doesn't understand many new load commands
for i in ${lib.concatStringsSep " " (map (e: targetPrefix + e) cmds)}; do
ln -sf "${cctools}/bin/$i" "$out/bin/$i"
done
for tool in ${toString llvm_cmds}; do
# Translate between LLVM and traditional tool names (e.g., `c++filt` versus `cxxfilt`).
cctoolsTool=''${tool//-/_}
llvmTool=''${tool//++/xx}

ln -s ${llvm}/bin/dsymutil $out/bin/dsymutil
# Some tools aren’t prefixed (like `dsymutil`).
llvmPath="${lib.getBin llvm}/bin"
if [ -e "$llvmPath/llvm-$llvmTool" ]; then
llvmTool=llvm-$llvmTool
elif [ -e "$llvmPath/${targetPrefix}$llvmTool" ]; then
llvmTool=${targetPrefix}$llvmTool
fi

ln -s ${binutils-unwrapped.out}/share $out/share
# Not all tools are included in the bootstrap tools. Don’t link them if they don’t exist.
if [ -e "$llvmPath/$llvmTool" ]; then
ln -s "$llvmPath/$llvmTool" "$out/bin/${targetPrefix}$cctoolsTool"
fi
${linkManPages llvm-manpages "$llvmTool" "$cctoolsTool"}
done

mkdir -p "$man"/share/man/man{1,5}
for i in ${lib.concatStringsSep " " cmds}; do
for path in "${cctools.man}"/share/man/man?/$i.*; do
dest_path="$man''${path#${cctools.man}}"
ln -sv "$path" "$dest_path"
done
for tool in ${toString cctools_cmds}; do
toolsrc="${lib.getBin cctools}/bin/${targetPrefix}$tool"
if [ -e "$toolsrc" ]; then
ln -s "${lib.getBin cctools}/bin/${targetPrefix}$tool" "$out/bin/${targetPrefix}$tool"
fi
${linkManPages (lib.getMan cctools) "$tool" "$tool"}
done
''
+ lib.optionalString (!isCCToolsLLVM) (
# cctools-port has a `libexec` folder for `as`, but cctools-llvm uses the clang
# assembler on both platforms. Only link it when cctools is cctools-port.
''
ln -s ${cctools}/libexec $out/libexec
''
# cctools-llvm uses the LLVM assembler on both architectures, so use the assembler
# from that instead of relinking it.
#
# On aarch64-darwin we must use clang, because "as" from cctools just doesn't
# handle the arch. Proxying calls to clang produces quite a bit of warnings,
# and using clang directly here is a better option than relying on cctools.
# On x86_64-darwin the Clang version is too old to support this mode.
+ lib.optionalString stdenv.isAarch64 ''
rm $out/bin/${targetPrefix}as
makeWrapper "${clang-unwrapped}/bin/clang" "$out/bin/${targetPrefix}as" \
--add-flags "-x assembler -integrated-as -c"
''
# x86-64 Darwin gnat-bootstrap emits assembly
# with MOVQ as the mnemonic for quadword interunit moves
# such as `movq %rbp, %xmm0`.
# The clang integrated assembler recognises this as valid,
# but unfortunately the cctools-port GNU assembler does not;
# it instead uses MOVD as the mnemonic.
# The assembly that a GCC build emits is determined at build time
# and cannot be changed afterwards.
#
# To build GNAT on x86-64 Darwin, therefore,
# we need both the clang _and_ the cctools-port assemblers to be available:
# the former to build at least the stage1 compiler,
# and the latter at least to be detectable
# as the target for the final compiler.
#
# We choose to match the Aarch64 case above,
# wrapping the clang integrated assembler as `as`.
# It then seems sensible to wrap the cctools GNU assembler as `gas`.
#
+ lib.optionalString (stdenv.isx86_64 && dualAs) ''
mv $out/bin/${targetPrefix}as $out/bin/${targetPrefix}gas
makeWrapper "${clang-unwrapped}/bin/clang" "$out/bin/${targetPrefix}as" \
--add-flags "-x assembler -integrated-as -c"
''
);

nativeBuildInputs = lib.optionals (!isCCToolsLLVM && (stdenv.isAarch64 || dualAs)) [ makeWrapper ];
${
# These unprefixed because some tools expect to invoke them without it when cross-compiling to Darwin:
# - clang needs `dsymutil` when building with debug information;
# - meson needs `lipo` when cross-compiling to Darwin; and
# - meson also needs `install_name_tool` and `otool` when performing rpath cleanup on installation.
lib.optionalString (targetPrefix != "") ''
for bintool in dsymutil install_name_tool lipo otool; do
ln -s "$out/bin/${targetPrefix}$bintool" "$out/bin/$bintool"
done
''
}
# Use the clang-integrated assembler. `as` in cctools is deprecated upstream and no longer built in nixpkgs.
makeWrapper "${lib.getBin clang-unwrapped}/bin/clang" "$out/bin/${targetPrefix}as" \
--add-flags "-x assembler -integrated-as -c"

ln -s '${lib.getBin cctools}/bin/${targetPrefix}ld' "$out/bin/${targetPrefix}ld"
${linkManPages (lib.getMan cctools) "ld" "ld"}
# ${linkManPages (lib.getMan cctools) "ld-classic" "ld-classic"}
${linkManPages (lib.getMan cctools) "ld64" "ld64"}
'';

__structuredAttrs = true;

passthru = {
inherit targetPrefix;
isCCTools = true;
inherit cctools_cmds llvm_cmds targetPrefix;
isCCTools = true; # The fact ld64 is used instead of lld is why this isn’t `isLLVM`.
};

meta = {
maintainers = with lib.maintainers; [ matthewbauer ];
maintainers = with lib.maintainers; [ reckenrode ];
priority = 10;
};
}
8 changes: 7 additions & 1 deletion pkgs/os-specific/darwin/cctools/port.nix
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ stdenv.mkDerivation {
sha256 = "0ns12q7vg9yand4dmdsps1917cavfbw67yl5q7bm6kb4ia5kkx13";
};

outputs = [ "out" "dev" "man" ];
outputs = [ "out" "dev" "gas" "man" ];

nativeBuildInputs = [ autoconf automake libtool autoreconfHook installShellFiles ]
++ lib.optionals (stdenv.isDarwin && stdenv.isx86_64) [ memstreamHook ];
Expand Down Expand Up @@ -178,6 +178,12 @@ stdenv.mkDerivation {
popd
'';

postInstall = ''
# Move GNU as to its own output to prevent it from being used accidentally.
moveToOutput bin/gas "$gas"
moveToOutput libexec "$gas"
'';

passthru = {
inherit targetPrefix;
};
Expand Down
Loading