at master 126 lines 3.9 kB view raw
1{ 2 lib, 3 stdenvNoCC, 4 cctools, 5 clang-unwrapped, 6 ld64, 7 llvm, 8 llvm-manpages, 9 makeWrapper, 10 enableManpages ? stdenvNoCC.targetPlatform == stdenvNoCC.hostPlatform, 11}: 12 13let 14 inherit (stdenvNoCC) targetPlatform hostPlatform; 15 targetPrefix = lib.optionalString (targetPlatform != hostPlatform) "${targetPlatform.config}-"; 16 17 llvm_cmds = [ 18 "addr2line" 19 "ar" 20 "c++filt" 21 "dwarfdump" 22 "dsymutil" 23 "nm" 24 "objcopy" 25 "objdump" 26 "otool" 27 "size" 28 "strings" 29 "strip" 30 ]; 31 32 cctools_cmds = [ 33 "codesign_allocate" 34 "gprof" 35 "ranlib" 36 # Use the cctools versions because the LLVM ones can crash or fail when the cctools ones don’t. 37 # Revisit when LLVM is updated to LLVM 18 on Darwin. 38 "lipo" 39 "install_name_tool" 40 ]; 41 42 linkManPages = 43 pkg: source: target: 44 lib.optionalString enableManpages '' 45 sourcePath=${pkg}/share/man/man1/${source}.1.gz 46 targetPath=''${!outputMan}/share/man/man1/${target}.1.gz 47 48 if [ -f "$sourcePath" ]; then 49 mkdir -p "$(dirname "$targetPath")" 50 ln -s "$sourcePath" "$targetPath" 51 fi 52 ''; 53in 54stdenvNoCC.mkDerivation { 55 pname = "${targetPrefix}cctools-binutils-darwin"; 56 inherit (cctools) version; 57 58 outputs = [ "out" ] ++ lib.optional enableManpages "man"; 59 60 strictDeps = true; 61 62 nativeBuildInputs = [ makeWrapper ]; 63 64 buildCommand = '' 65 mkdir -p $out/bin $out/include 66 67 for tool in ${toString llvm_cmds}; do 68 # Translate between LLVM and traditional tool names (e.g., `c++filt` versus `cxxfilt`). 69 cctoolsTool=''${tool//-/_} 70 llvmTool=''${tool//++/xx} 71 72 # Some tools arent prefixed (like `dsymutil`). 73 llvmPath="${lib.getBin llvm}/bin" 74 if [ -e "$llvmPath/llvm-$llvmTool" ]; then 75 llvmTool=llvm-$llvmTool 76 elif [ -e "$llvmPath/${targetPrefix}$llvmTool" ]; then 77 llvmTool=${targetPrefix}$llvmTool 78 fi 79 80 # Not all tools are included in the bootstrap tools. Dont link them if they dont exist. 81 if [ -e "$llvmPath/$llvmTool" ]; then 82 ln -s "$llvmPath/$llvmTool" "$out/bin/${targetPrefix}$cctoolsTool" 83 fi 84 ${linkManPages llvm-manpages "$llvmTool" "$cctoolsTool"} 85 done 86 87 for tool in ${toString cctools_cmds}; do 88 toolsrc="${lib.getBin cctools}/bin/${targetPrefix}$tool" 89 if [ -e "$toolsrc" ]; then 90 ln -s "${lib.getBin cctools}/bin/${targetPrefix}$tool" "$out/bin/${targetPrefix}$tool" 91 fi 92 ${linkManPages (lib.getMan cctools) "$tool" "$tool"} 93 done 94 ${ 95 # These are unprefixed because some tools expect to invoke them without it when cross-compiling to Darwin: 96 # - clang needs `dsymutil` when building with debug information; 97 # - meson needs `lipo` when cross-compiling to Darwin; and 98 # - meson also needs `install_name_tool` and `otool` when performing rpath cleanup on installation. 99 lib.optionalString (targetPrefix != "") '' 100 for bintool in dsymutil install_name_tool lipo otool; do 101 ln -s "$out/bin/${targetPrefix}$bintool" "$out/bin/$bintool" 102 done 103 '' 104 } 105 # Use the clang-integrated assembler. `as` in cctools is deprecated upstream and no longer built in nixpkgs. 106 makeWrapper "${lib.getBin clang-unwrapped}/bin/clang" "$out/bin/${targetPrefix}as" \ 107 --add-flags "-x assembler -integrated-as -c" 108 109 ln -s '${lib.getBin ld64}/bin/ld' "$out/bin/${targetPrefix}ld" 110 ${linkManPages (lib.getMan ld64) "ld" "ld"} 111 ${linkManPages (lib.getMan ld64) "ld-classic" "ld-classic"} 112 ${linkManPages (lib.getMan ld64) "ld64" "ld64"} 113 ''; 114 115 __structuredAttrs = true; 116 117 passthru = { 118 inherit cctools_cmds llvm_cmds targetPrefix; 119 isCCTools = true; # The fact ld64 is used instead of lld is why this isn’t `isLLVM`. 120 }; 121 122 meta = { 123 maintainers = with lib.maintainers; [ reckenrode ]; 124 priority = 10; 125 }; 126}