nixpkgs mirror (for testing) github.com/NixOS/nixpkgs
nix
at python-updates 471 lines 18 kB view raw
1{ 2 lib, 3 stdenv, 4 removeReferencesTo, 5 pkgsBuildBuild, 6 pkgsBuildHost, 7 pkgsBuildTarget, 8 targetPackages, 9 llvmShared, 10 llvmSharedForBuild, 11 llvmSharedForHost, 12 llvmSharedForTarget, 13 llvmPackages, 14 runCommandLocal, 15 fetchurl, 16 file, 17 python3, 18 cargo, 19 cmake, 20 rustc, 21 rustfmt, 22 pkg-config, 23 openssl, 24 xz, 25 zlib, 26 bintools, 27 which, 28 libffi, 29 withBundledLLVM ? false, 30 enableRustcDev ? true, 31 version, 32 sha256, 33 patches ? [ ], 34 fd, 35 ripgrep, 36 wezterm, 37 firefox, 38 thunderbird, 39 # This only builds std for target and reuses the rustc from build. 40 fastCross, 41 lndir, 42 makeWrapper, 43}: 44 45let 46 inherit (lib) 47 optionals 48 optional 49 optionalString 50 concatStringsSep 51 ; 52 useLLVM = stdenv.targetPlatform.useLLVM or false; 53in 54stdenv.mkDerivation (finalAttrs: { 55 pname = "${targetPackages.stdenv.cc.targetPrefix}rustc"; 56 inherit version; 57 58 src = fetchurl { 59 url = "https://static.rust-lang.org/dist/rustc-${version}-src.tar.gz"; 60 inherit sha256; 61 # See https://nixos.org/manual/nixpkgs/stable/#using-git-bisect-on-the-rust-compiler 62 passthru.isReleaseTarball = true; 63 }; 64 65 __darwinAllowLocalNetworking = true; 66 67 # rustc complains about modified source files otherwise 68 dontUpdateAutotoolsGnuConfigScripts = true; 69 70 # Running the default `strip -S` command on Darwin corrupts the 71 # .rlib files in "lib/". 72 # 73 # See https://github.com/NixOS/nixpkgs/pull/34227 74 # 75 # Running `strip -S` when cross compiling can harm the cross rlibs. 76 # See: https://github.com/NixOS/nixpkgs/pull/56540#issuecomment-471624656 77 stripDebugList = [ "bin" ]; 78 79 env = { 80 NIX_LDFLAGS = toString ( 81 # when linking stage1 libstd: cc: undefined reference to `__cxa_begin_catch' 82 # This doesn't apply to cross-building for FreeBSD because the host 83 # uses libstdc++, but the target (used for building std) uses libc++ 84 optional ( 85 stdenv.hostPlatform.isLinux && !withBundledLLVM && !stdenv.targetPlatform.isFreeBSD && !useLLVM 86 ) "--push-state --as-needed -lstdc++ --pop-state" 87 ++ 88 optional 89 (stdenv.hostPlatform.isLinux && !withBundledLLVM && !stdenv.targetPlatform.isFreeBSD && useLLVM) 90 "--push-state --as-needed -L${llvmPackages.libcxx}/lib -lc++ -lc++abi -lLLVM-${lib.versions.major llvmPackages.llvm.version} --pop-state" 91 ++ optional (stdenv.hostPlatform.isDarwin && !withBundledLLVM) "-lc++ -lc++abi" 92 ++ optional stdenv.hostPlatform.isDarwin "-rpath ${llvmSharedForHost.lib}/lib" 93 ); 94 95 RUSTFLAGS = lib.concatStringsSep " " ( 96 [ 97 # Increase codegen units to introduce parallelism within the compiler. 98 "-Ccodegen-units=10" 99 ] 100 ++ lib.optionals (stdenv.hostPlatform.rust.rustcTargetSpec == "x86_64-unknown-linux-gnu") [ 101 # Upstream defaults to lld on x86_64-unknown-linux-gnu, we want to use our linker 102 "-Clinker-features=-lld" 103 "-Clink-self-contained=-linker" 104 ] 105 ); 106 RUSTDOCFLAGS = "-A rustdoc::broken-intra-doc-links"; 107 }; 108 109 # We need rust to build rust. If we don't provide it, configure will try to download it. 110 # Reference: https://github.com/rust-lang/rust/blob/master/src/bootstrap/configure.py 111 configureFlags = 112 let 113 prefixForStdenv = stdenv: "${stdenv.cc}/bin/${stdenv.cc.targetPrefix}"; 114 ccPrefixForStdenv = 115 stdenv: "${prefixForStdenv stdenv}${if (stdenv.cc.isClang or false) then "clang" else "cc"}"; 116 cxxPrefixForStdenv = 117 stdenv: "${prefixForStdenv stdenv}${if (stdenv.cc.isClang or false) then "clang++" else "c++"}"; 118 setBuild = "--set=target.\"${stdenv.buildPlatform.rust.rustcTargetSpec}\""; 119 setHost = "--set=target.\"${stdenv.hostPlatform.rust.rustcTargetSpec}\""; 120 setTarget = "--set=target.\"${stdenv.targetPlatform.rust.rustcTargetSpec}\""; 121 ccForBuild = ccPrefixForStdenv pkgsBuildBuild.targetPackages.stdenv; 122 cxxForBuild = cxxPrefixForStdenv pkgsBuildBuild.targetPackages.stdenv; 123 ccForHost = ccPrefixForStdenv pkgsBuildHost.targetPackages.stdenv; 124 cxxForHost = cxxPrefixForStdenv pkgsBuildHost.targetPackages.stdenv; 125 ccForTarget = ccPrefixForStdenv pkgsBuildTarget.targetPackages.stdenv; 126 cxxForTarget = cxxPrefixForStdenv pkgsBuildTarget.targetPackages.stdenv; 127 in 128 [ 129 "--sysconfdir=${placeholder "out"}/etc" 130 "--release-channel=stable" 131 "--set=build.rustc=${rustc}/bin/rustc" 132 "--set=build.cargo=${cargo}/bin/cargo" 133 ] 134 ++ lib.optionals (!(finalAttrs.src.passthru.isReleaseTarball or false)) [ 135 # release tarballs vendor the rustfmt source; when 136 # git-bisect'ing from upstream's git repo we must prevent 137 # attempts to download the missing source tarball 138 "--set=build.rustfmt=${rustfmt}/bin/rustfmt" 139 ] 140 ++ [ 141 "--tools=rustc,rustdoc,rust-analyzer-proc-macro-srv" 142 "--enable-rpath" 143 "--enable-vendor" 144 # For Nixpkgs it makes more sense to use stdenv's linker than 145 # letting rustc build its own. 146 "--disable-lld" 147 "--build=${stdenv.buildPlatform.rust.rustcTargetSpec}" 148 "--host=${stdenv.hostPlatform.rust.rustcTargetSpec}" 149 # std is built for all platforms in --target. 150 "--target=${ 151 concatStringsSep "," ( 152 # Other targets that don't need any extra dependencies to build. 153 optionals (!fastCross) [ 154 "wasm32-unknown-unknown" 155 "wasm32v1-none" 156 "bpfel-unknown-none" 157 "bpfeb-unknown-none" 158 ] 159 # (build!=target): When cross-building a compiler we need to add 160 # the build platform as well so rustc can compile build.rs 161 # scripts. 162 ++ optionals (stdenv.buildPlatform != stdenv.targetPlatform && !fastCross) [ 163 stdenv.buildPlatform.rust.rustcTargetSpec 164 ] 165 # (host!=target): When building a cross-targeting compiler we 166 # need to add the host platform as well so rustc can compile 167 # build.rs scripts. 168 ++ optionals (stdenv.hostPlatform != stdenv.targetPlatform && !fastCross) [ 169 stdenv.hostPlatform.rust.rustcTargetSpec 170 ] 171 ++ [ 172 # `make install` only keeps the docs of the last target in the list. 173 # If the `targetPlatform` is not the last entry, we may end up without 174 # `alloc` or `std` docs (if the last target is `no_std`). 175 # More information: https://github.com/rust-lang/rust/issues/140922 176 stdenv.targetPlatform.rust.rustcTargetSpec 177 ] 178 ) 179 }" 180 181 "${setBuild}.cc=${ccForBuild}" 182 "${setHost}.cc=${ccForHost}" 183 "${setTarget}.cc=${ccForTarget}" 184 185 # The Rust compiler build identifies platforms by Rust target 186 # name, and later arguments override previous arguments. This 187 # means that when platforms differ in configuration but overlap 188 # in Rust target name (for instance, `pkgsStatic`), only one 189 # setting will be applied for any given option. 190 # 191 # This is usually mostly harmless, especially as `fastCross` 192 # means that we usually only compile `std` in such cases. 193 # However, the build does still need to link helper tools for the 194 # build platform in that case. This was breaking the Darwin 195 # `pkgsStatic` build, as it was attempting to link build tools 196 # with the target platform’s static linker, and failing to locate 197 # an appropriate static library for `-liconv`. 198 # 199 # Since the static build does not link anything for the target 200 # platform anyway, we put the target linker first so that the 201 # build platform linker overrides it when the Rust target names 202 # overlap, allowing the helper tools to build successfully. 203 # 204 # Note that Rust does not remember these settings in the built 205 # compiler, so this does not compromise any functionality of the 206 # resulting compiler. 207 # 208 # The longer‐term fix would be to get Rust to use a more nuanced 209 # understanding of platforms, such as by explicitly constructing 210 # and passing Rust JSON target definitions that let us 211 # distinguish the platforms in cases like these. That would also 212 # let us supplant various hacks around the wrappers and hooks 213 # that we currently need. 214 "${setTarget}.linker=${ccForTarget}" 215 "${setBuild}.linker=${ccForBuild}" 216 "${setHost}.linker=${ccForHost}" 217 218 "${setBuild}.cxx=${cxxForBuild}" 219 "${setHost}.cxx=${cxxForHost}" 220 "${setTarget}.cxx=${cxxForTarget}" 221 222 "${setBuild}.crt-static=${lib.boolToString stdenv.buildPlatform.isStatic}" 223 "${setHost}.crt-static=${lib.boolToString stdenv.hostPlatform.isStatic}" 224 "${setTarget}.crt-static=${lib.boolToString stdenv.targetPlatform.isStatic}" 225 ] 226 ++ optionals (!withBundledLLVM) [ 227 "--enable-llvm-link-shared" 228 "${setBuild}.llvm-config=${llvmSharedForBuild.dev}/bin/llvm-config" 229 "${setHost}.llvm-config=${llvmSharedForHost.dev}/bin/llvm-config" 230 "${setTarget}.llvm-config=${llvmSharedForTarget.dev}/bin/llvm-config" 231 ] 232 ++ optionals fastCross [ 233 # Since fastCross only builds std, it doesn't make sense (and 234 # doesn't work) to build a linker. 235 "--disable-llvm-bitcode-linker" 236 ] 237 ++ optionals (!fastCross && stdenv.targetPlatform.config != "wasm32-unknown-none") [ 238 # See https://github.com/rust-lang/rust/issues/132802 239 "--set=target.wasm32-unknown-unknown.optimized-compiler-builtins=false" 240 "--set=target.wasm32v1-none.optimized-compiler-builtins=false" 241 ] 242 ++ optionals (stdenv.targetPlatform.isLinux && !(stdenv.targetPlatform.useLLVM or false)) [ 243 "--enable-profiler" # build libprofiler_builtins 244 ] 245 ++ optionals stdenv.targetPlatform.isDarwin [ 246 # potentially other llvm targets work with the same fix? 247 "--enable-profiler" # build libprofiler_builtins 248 # Disable profiler for targets that don't support it 249 "--set=target.wasm32-unknown-unknown.profiler=false" 250 "--set=target.wasm32v1-none.profiler=false" 251 "--set=target.bpfel-unknown-none.profiler=false" 252 "--set=target.bpfeb-unknown-none.profiler=false" 253 ] 254 ++ optionals stdenv.buildPlatform.isMusl [ 255 "${setBuild}.musl-root=${pkgsBuildBuild.targetPackages.stdenv.cc.libc}" 256 ] 257 ++ optionals stdenv.hostPlatform.isMusl [ 258 "${setHost}.musl-root=${pkgsBuildHost.targetPackages.stdenv.cc.libc}" 259 ] 260 ++ optionals stdenv.targetPlatform.isMusl [ 261 "${setTarget}.musl-root=${pkgsBuildTarget.targetPackages.stdenv.cc.libc}" 262 ] 263 ++ optionals stdenv.targetPlatform.rust.isNoStdTarget [ 264 "--disable-docs" 265 ] 266 ++ optionals (stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isx86_64) [ 267 # https://github.com/rust-lang/rust/issues/92173 268 "--set=rust.jemalloc" 269 ] 270 ++ optionals (useLLVM && !stdenv.targetPlatform.isFreeBSD) [ 271 # https://github.com/NixOS/nixpkgs/issues/311930 272 "--llvm-libunwind=${if withBundledLLVM then "in-tree" else "system"}" 273 "--enable-use-libcxx" 274 ] 275 ++ optionals (!stdenv.hostPlatform.isx86_32) [ 276 # This enables frame pointers for the compiler itself. 277 # 278 # Note that when compiling std, frame pointers (or at least non-leaf 279 # frame pointers, depending on version) are unconditionally enabled and 280 # cannot be overridden, so we do not touch that. (Also note this only 281 # applies to functions that can be immediately compiled when building 282 # std. Generic functions that do codegen when called in user code obey 283 # -Cforce-frame-pointers specified then, if any) 284 "--set=rust.frame-pointers" 285 ]; 286 287 # if we already have a rust compiler for build just compile the target std 288 # library and reuse compiler 289 buildPhase = 290 if fastCross then 291 '' 292 runHook preBuild 293 294 mkdir -p build/${stdenv.hostPlatform.rust.rustcTargetSpec}/stage{0,1}-{std,rustc}/${stdenv.hostPlatform.rust.rustcTargetSpec}/release/ 295 ln -s ${rustc.unwrapped}/lib/rustlib/${stdenv.hostPlatform.rust.rustcTargetSpec}/libstd-*.so build/${stdenv.hostPlatform.rust.rustcTargetSpec}/stage0-std/${stdenv.hostPlatform.rust.rustcTargetSpec}/release/libstd.so 296 ln -s ${rustc.unwrapped}/lib/rustlib/${stdenv.hostPlatform.rust.rustcTargetSpec}/librustc_driver-*.so build/${stdenv.hostPlatform.rust.rustcTargetSpec}/stage0-rustc/${stdenv.hostPlatform.rust.rustcTargetSpec}/release/librustc.so 297 ln -s ${rustc.unwrapped}/bin/rustc build/${stdenv.hostPlatform.rust.rustcTargetSpec}/stage0-rustc/${stdenv.hostPlatform.rust.rustcTargetSpec}/release/rustc-main 298 ln -s ${rustc.unwrapped}/bin/rustc build/${stdenv.hostPlatform.rust.rustcTargetSpec}/stage1-rustc/${stdenv.hostPlatform.rust.rustcTargetSpec}/release/rustc-main 299 touch build/${stdenv.hostPlatform.rust.rustcTargetSpec}/stage0-std/${stdenv.hostPlatform.rust.rustcTargetSpec}/release/.libstd-stamp 300 touch build/${stdenv.hostPlatform.rust.rustcTargetSpec}/stage{0,1}-rustc/${stdenv.hostPlatform.rust.rustcTargetSpec}/release/.librustc-stamp 301 python ./x.py --keep-stage=0 --stage=1 build library 302 303 runHook postBuild 304 '' 305 else 306 null; 307 308 installPhase = 309 if fastCross then 310 '' 311 runHook preInstall 312 313 python ./x.py --keep-stage=0 --stage=1 install library/std 314 mkdir -v $doc $man 315 ln -s ${rustc.unwrapped}/{bin,libexec} $out 316 rm -rf -v $out/lib/rustlib/{manifest-rust-std-,}${stdenv.hostPlatform.rust.rustcTargetSpec} 317 ln -s ${rustc.unwrapped}/lib/rustlib/{manifest-rust-std-,}${stdenv.hostPlatform.rust.rustcTargetSpec} $out/lib/rustlib/ 318 ln -s ${rustc.unwrapped}/lib/rustlib/etc $out/lib/rustlib/ 319 echo rust-std-${stdenv.hostPlatform.rust.rustcTargetSpec} >> $out/lib/rustlib/components 320 lndir ${rustc.doc} $doc 321 lndir ${rustc.man} $man 322 323 runHook postInstall 324 '' 325 else 326 null; 327 328 # the rust build system complains that nix alters the checksums 329 dontFixLibtool = true; 330 331 inherit patches; 332 333 postPatch = '' 334 patchShebangs src/etc 335 336 # rust-lld is the name rustup uses for its bundled lld, so that it 337 # doesn't conflict with any system lld. This is not an 338 # appropriate default for Nixpkgs, where there is no rust-lld. 339 substituteInPlace compiler/rustc_target/src/spec/*/*.rs \ 340 --replace-quiet '"rust-lld"' '"lld"' 341 342 ${optionalString (!withBundledLLVM) "rm -rf src/llvm"} 343 344 # Useful debugging parameter 345 # export VERBOSE=1 346 '' 347 + lib.optionalString (stdenv.hostPlatform.isDarwin || stdenv.targetPlatform.isDarwin) '' 348 # Replace hardcoded path to strip with llvm-strip 349 # https://github.com/NixOS/nixpkgs/issues/299606 350 substituteInPlace compiler/rustc_codegen_ssa/src/back/link.rs \ 351 --replace-fail "/usr/bin/strip" "${lib.getExe' llvmShared "llvm-strip"}" 352 '' 353 + lib.optionalString (stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isx86_64) '' 354 # See https://github.com/jemalloc/jemalloc/issues/1997 355 # Using a value of 48 should work on both emulated and native x86_64-darwin. 356 export JEMALLOC_SYS_WITH_LG_VADDR=48 357 '' 358 + lib.optionalString (!(finalAttrs.src.passthru.isReleaseTarball or false)) '' 359 mkdir .cargo 360 cat > .cargo/config.toml <<\EOF 361 [source.crates-io] 362 replace-with = "vendored-sources" 363 [source.vendored-sources] 364 directory = "vendor" 365 EOF 366 '' 367 + lib.optionalString (stdenv.hostPlatform.isFreeBSD) '' 368 # lzma-sys bundles an old version of xz that doesn't build 369 # on modern FreeBSD, use the system one instead 370 substituteInPlace src/bootstrap/src/core/build_steps/tool.rs \ 371 --replace 'cargo.env("LZMA_API_STATIC", "1");' ' ' 372 ''; 373 374 # rustc unfortunately needs cmake to compile llvm-rt but doesn't 375 # use it for the normal build. This disables cmake in Nix. 376 dontUseCmakeConfigure = true; 377 378 depsBuildBuild = [ 379 pkgsBuildHost.stdenv.cc 380 pkg-config 381 ]; 382 depsBuildTarget = lib.optionals stdenv.targetPlatform.isMinGW [ bintools ]; 383 384 nativeBuildInputs = [ 385 file 386 python3 387 rustc 388 cmake 389 which 390 libffi 391 removeReferencesTo 392 pkg-config 393 xz 394 ] 395 ++ optionals fastCross [ 396 lndir 397 makeWrapper 398 ]; 399 400 buildInputs = [ 401 openssl 402 ] 403 ++ optionals stdenv.hostPlatform.isDarwin [ 404 zlib 405 ] 406 ++ optional (!withBundledLLVM) llvmShared.lib 407 ++ optional (useLLVM && !withBundledLLVM) llvmPackages.libunwind; 408 409 outputs = [ 410 "out" 411 "man" 412 "doc" 413 ]; 414 setOutputFlags = false; 415 416 postInstall = 417 lib.optionalString (enableRustcDev && !fastCross) '' 418 # install rustc-dev components. Necessary to build rls, clippy... 419 python x.py dist rustc-dev 420 tar xf build/dist/rustc-dev*tar.gz 421 cp -r rustc-dev*/rustc-dev*/lib/* $out/lib/ 422 rm $out/lib/rustlib/install.log 423 for m in $out/lib/rustlib/manifest-rust* 424 do 425 sort --output=$m < $m 426 done 427 428 '' 429 + '' 430 # remove references to llvm-config in lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so 431 # and thus a transitive dependency on ncurses 432 find $out/lib -name "*.so" -type f -exec remove-references-to -t ${llvmShared} '{}' '+' 433 434 # remove uninstall script that doesn't really make sense for Nix. 435 rm $out/lib/rustlib/uninstall.sh 436 ''; 437 438 configurePlatforms = [ ]; 439 440 enableParallelBuilding = true; 441 442 setupHooks = ./setup-hook.sh; 443 444 requiredSystemFeatures = [ "big-parallel" ]; 445 446 passthru = { 447 llvm = llvmShared; 448 inherit llvmPackages; 449 inherit (rustc) targetPlatforms targetPlatformsWithHostTools badTargetPlatforms; 450 tests = { 451 inherit fd ripgrep wezterm; 452 } 453 // lib.optionalAttrs stdenv.hostPlatform.isLinux { inherit firefox thunderbird; }; 454 }; 455 456 __structuredAttrs = true; 457 458 meta = { 459 homepage = "https://www.rust-lang.org/"; 460 description = "Safe, concurrent, practical language"; 461 teams = [ lib.teams.rust ]; 462 license = [ 463 lib.licenses.mit 464 lib.licenses.asl20 465 ]; 466 platforms = rustc.targetPlatformsWithHostTools; 467 # If rustc can't target a platform, we also can't build rustc for 468 # that platform. 469 badPlatforms = rustc.badTargetPlatforms; 470 }; 471})