at master 7.2 kB view raw
1{ 2 lib, 3 stdenv, 4 llvm_meta, 5 release_version, 6 monorepoSrc ? null, 7 src ? null, 8 runCommand, 9 cmake, 10 lndir, 11 ninja, 12 python3, 13 fixDarwinDylibNames, 14 version, 15 freebsd, 16 cxxabi ? if stdenv.hostPlatform.isFreeBSD then freebsd.libcxxrt else null, 17 libunwind, 18 enableShared ? stdenv.hostPlatform.hasSharedLibraries, 19 devExtraCmakeFlags ? [ ], 20 substitute, 21 fetchpatch, 22}: 23 24# external cxxabi is not supported on Darwin as the build will not link libcxx 25# properly and not re-export the cxxabi symbols into libcxx 26# https://github.com/NixOS/nixpkgs/issues/166205 27# https://github.com/NixOS/nixpkgs/issues/269548 28assert cxxabi == null || !stdenv.hostPlatform.isDarwin; 29let 30 cxxabiName = "lib${if cxxabi == null then "cxxabi" else cxxabi.libName}"; 31 runtimes = [ "libcxx" ] ++ lib.optional (cxxabi == null) "libcxxabi"; 32 33 # Note: useLLVM is likely false for Darwin but true under pkgsLLVM 34 useLLVM = stdenv.hostPlatform.useLLVM or false; 35 36 cxxabiCMakeFlags = [ 37 (lib.cmakeBool "LIBCXXABI_USE_LLVM_UNWINDER" false) 38 ] 39 ++ lib.optionals (useLLVM && !stdenv.hostPlatform.isWasm) [ 40 (lib.cmakeFeature "LIBCXXABI_ADDITIONAL_LIBRARIES" "unwind") 41 (lib.cmakeBool "LIBCXXABI_USE_COMPILER_RT" true) 42 ] 43 ++ lib.optionals stdenv.hostPlatform.isWasm [ 44 (lib.cmakeBool "LIBCXXABI_ENABLE_THREADS" false) 45 (lib.cmakeBool "LIBCXXABI_ENABLE_EXCEPTIONS" false) 46 ] 47 ++ lib.optionals (!enableShared || stdenv.hostPlatform.isWindows) [ 48 # Required on Windows due to https://github.com/llvm/llvm-project/issues/55245 49 (lib.cmakeBool "LIBCXXABI_ENABLE_SHARED" false) 50 ]; 51 52 cxxCMakeFlags = [ 53 (lib.cmakeFeature "LIBCXX_CXX_ABI" cxxabiName) 54 (lib.cmakeBool "LIBCXX_ENABLE_SHARED" enableShared) 55 # https://github.com/llvm/llvm-project/issues/55245 56 (lib.cmakeBool "LIBCXX_ENABLE_STATIC_ABI_LIBRARY" stdenv.hostPlatform.isWindows) 57 ] 58 ++ lib.optionals (cxxabi == null) [ 59 # Include libc++abi symbols within libc++.a for static linking libc++; 60 # dynamic linking includes them through libc++.so being a linker script 61 # which includes both shared objects. 62 (lib.cmakeBool "LIBCXX_STATICALLY_LINK_ABI_IN_STATIC_LIBRARY" true) 63 ] 64 ++ lib.optionals (cxxabi != null) [ 65 (lib.cmakeFeature "LIBCXX_CXX_ABI_INCLUDE_PATHS" "${lib.getDev cxxabi}/include") 66 ] 67 ++ lib.optionals (stdenv.hostPlatform.isMusl || stdenv.hostPlatform.isWasi) [ 68 (lib.cmakeFeature "LIBCXX_HAS_MUSL_LIBC" "1") 69 ] 70 ++ 71 lib.optionals (!useLLVM && stdenv.hostPlatform.libc == "glibc" && !stdenv.hostPlatform.isStatic) 72 [ 73 (lib.cmakeFeature "LIBCXX_ADDITIONAL_LIBRARIES" "gcc_s") 74 ] 75 ++ lib.optionals stdenv.hostPlatform.isFreeBSD [ 76 # Name and documentation claim this is for libc++abi, but its man effect is adding `-lunwind` 77 # to the libc++.so linker script. We want FreeBSD's so-called libgcc instead of libunwind. 78 (lib.cmakeBool "LIBCXXABI_USE_LLVM_UNWINDER" false) 79 ] 80 ++ lib.optionals useLLVM [ 81 (lib.cmakeBool "LIBCXX_USE_COMPILER_RT" true) 82 ] 83 ++ lib.optionals (useLLVM && !stdenv.hostPlatform.isFreeBSD) [ 84 (lib.cmakeFeature "LIBCXX_ADDITIONAL_LIBRARIES" "unwind") 85 ] 86 ++ lib.optionals stdenv.hostPlatform.isWasm [ 87 (lib.cmakeBool "LIBCXX_ENABLE_THREADS" false) 88 (lib.cmakeBool "LIBCXX_ENABLE_FILESYSTEM" false) 89 (lib.cmakeBool "LIBCXX_ENABLE_EXCEPTIONS" false) 90 ] 91 ++ lib.optionals (cxxabi != null && cxxabi.libName == "cxxrt") [ 92 (lib.cmakeBool "LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS" true) 93 ]; 94 95 cmakeFlags = [ 96 (lib.cmakeFeature "LLVM_ENABLE_RUNTIMES" (lib.concatStringsSep ";" runtimes)) 97 ] 98 ++ lib.optionals stdenv.hostPlatform.isWasm [ 99 (lib.cmakeBool "CMAKE_CXX_COMPILER_WORKS" true) 100 (lib.cmakeBool "CMAKE_C_COMPILER_WORKS" true) 101 (lib.cmakeBool "UNIX" true) # Required otherwise libc++ fails to detect the correct linker 102 ] 103 ++ cxxCMakeFlags 104 ++ lib.optionals (cxxabi == null) cxxabiCMakeFlags 105 ++ devExtraCmakeFlags; 106 107in 108 109stdenv.mkDerivation (finalAttrs: { 110 pname = "libcxx"; 111 inherit version cmakeFlags; 112 113 src = 114 if monorepoSrc != null then 115 runCommand "libcxx-src-${version}" { inherit (monorepoSrc) passthru; } ( 116 '' 117 mkdir -p "$out/llvm" 118 cp -r ${monorepoSrc}/cmake "$out" 119 cp -r ${monorepoSrc}/libcxx "$out" 120 cp -r ${monorepoSrc}/llvm/cmake "$out/llvm" 121 cp -r ${monorepoSrc}/llvm/utils "$out/llvm" 122 cp -r ${monorepoSrc}/third-party "$out" 123 '' 124 + (lib.optionalString (lib.versionAtLeast release_version "20") '' 125 cp -r ${monorepoSrc}/libc "$out" 126 '') 127 + '' 128 cp -r ${monorepoSrc}/runtimes "$out" 129 '' 130 + (lib.optionalString (cxxabi == null) '' 131 cp -r ${monorepoSrc}/libcxxabi "$out" 132 '') 133 ) 134 else 135 src; 136 137 outputs = [ 138 "out" 139 "dev" 140 ]; 141 142 preConfigure = lib.optionalString stdenv.hostPlatform.isMusl '' 143 patchShebangs utils/cat_files.py 144 ''; 145 146 # TODO: Remove on `staging`. 147 patches = [ ]; 148 149 nativeBuildInputs = [ 150 cmake 151 ninja 152 python3 153 ] 154 ++ lib.optional stdenv.hostPlatform.isDarwin fixDarwinDylibNames 155 ++ lib.optional (cxxabi != null) lndir; 156 157 buildInputs = [ 158 cxxabi 159 ] 160 ++ lib.optionals (useLLVM && !stdenv.hostPlatform.isWasm && !stdenv.hostPlatform.isFreeBSD) [ 161 libunwind 162 ]; 163 164 # TODO: Possibly move back to `sourceRoot` on `staging`? 165 postPatch = '' 166 cd runtimes 167 ''; 168 169 # libc++.so is a linker script which expands to multiple libraries, 170 # libc++.so.1 and libc++abi.so or the external cxxabi. ld-wrapper doesn't 171 # support linker scripts so the external cxxabi needs to be symlinked in 172 postInstall = 173 lib.optionalString (cxxabi != null) '' 174 lndir ${lib.getDev cxxabi}/include $dev/include/c++/v1 175 lndir ${lib.getLib cxxabi}/lib $out/lib 176 libcxxabi=$out/lib/lib${cxxabi.libName}.a 177 '' 178 # LIBCXX_STATICALLY_LINK_ABI_IN_STATIC_LIBRARY=ON doesn't work for 179 # external cxxabi libraries so merge libc++abi.a into libc++.a ourselves. 180 181 # GNU binutils emits objects in LIFO order in MRI scripts so after the merge 182 # the objects are in reversed order so a second MRI script is required so the 183 # objects in the archive are listed in proper order (libc++.a, libc++abi.a) 184 + lib.optionalString (cxxabi != null) '' 185 libcxxabi=''${libcxxabi-$out/lib/libc++abi.a} 186 if [[ -f $out/lib/libc++.a && -e $libcxxabi ]]; then 187 $AR -M <<MRI 188 create $out/lib/libc++.a 189 addlib $out/lib/libc++.a 190 addlib $libcxxabi 191 save 192 end 193 MRI 194 $AR -M <<MRI 195 create $out/lib/libc++.a 196 addlib $out/lib/libc++.a 197 save 198 end 199 MRI 200 fi 201 ''; 202 203 passthru = { 204 isLLVM = true; 205 }; 206 207 meta = llvm_meta // { 208 homepage = "https://libcxx.llvm.org/"; 209 description = "C++ standard library"; 210 longDescription = '' 211 libc++ is an implementation of the C++ standard library, targeting C++11, 212 C++14 and above. 213 ''; 214 # "All of the code in libc++ is dual licensed under the MIT license and the 215 # UIUC License (a BSD-like license)": 216 license = with lib.licenses; [ 217 mit 218 ncsa 219 ]; 220 }; 221})