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