Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
1{ 2 lib, 3 stdenv, 4 fetchurl, 5 openssl, 6 python, 7 zlib, 8 libuv, 9 sqlite, 10 http-parser, 11 icu, 12 bash, 13 ninja, 14 pkgconf, 15 unixtools, 16 runCommand, 17 buildPackages, 18 testers, 19 # for `.pkgs` attribute 20 callPackage, 21 # Updater dependencies 22 writeScript, 23 coreutils, 24 gnugrep, 25 jq, 26 curl, 27 common-updater-scripts, 28 runtimeShell, 29 gnupg, 30 installShellFiles, 31}: 32 33{ 34 enableNpm ? true, 35 version, 36 sha256, 37 patches ? [ ], 38}@args: 39 40let 41 42 majorVersion = lib.versions.major version; 43 minorVersion = lib.versions.minor version; 44 45 pname = if enableNpm then "nodejs" else "nodejs-slim"; 46 47 canExecute = stdenv.buildPlatform.canExecute stdenv.hostPlatform; 48 emulator = stdenv.hostPlatform.emulator buildPackages; 49 canEmulate = stdenv.hostPlatform.emulatorAvailable buildPackages; 50 buildNode = buildPackages."${pname}_${majorVersion}"; 51 52 # See valid_os and valid_arch in configure.py. 53 destOS = 54 let 55 platform = stdenv.hostPlatform; 56 in 57 if platform.isiOS then 58 "ios" 59 else if platform.isAndroid then 60 "android" 61 else if platform.isWindows then 62 "win" 63 else if platform.isDarwin then 64 "mac" 65 else if platform.isLinux then 66 "linux" 67 else if platform.isOpenBSD then 68 "openbsd" 69 else if platform.isFreeBSD then 70 "freebsd" 71 else 72 throw "unsupported os ${platform.uname.system}"; 73 destCPU = 74 let 75 platform = stdenv.hostPlatform; 76 in 77 if platform.isAarch then 78 "arm" + lib.optionalString platform.is64bit "64" 79 else if platform.isMips32 then 80 "mips" + lib.optionalString platform.isLittleEndian "le" 81 else if platform.isMips64 && platform.isLittleEndian then 82 "mips64el" 83 else if platform.isPower then 84 "ppc" + lib.optionalString platform.is64bit "64" 85 else if platform.isx86_64 then 86 "x64" 87 else if platform.isx86_32 then 88 "ia32" 89 else if platform.isS390x then 90 "s390x" 91 else if platform.isRiscV64 then 92 "riscv64" 93 else if platform.isLoongArch64 then 94 "loong64" 95 else 96 throw "unsupported cpu ${platform.uname.processor}"; 97 destARMFPU = 98 let 99 platform = stdenv.hostPlatform; 100 in 101 if platform.isAarch32 && platform ? gcc.fpu then 102 lib.throwIfNot (builtins.elem platform.gcc.fpu [ 103 "vfp" 104 "vfpv2" 105 "vfpv3" 106 "vfpv3-d16" 107 "neon" 108 ]) "unsupported ARM FPU ${platform.gcc.fpu}" platform.gcc.fpu 109 else 110 null; 111 destARMFloatABI = 112 let 113 platform = stdenv.hostPlatform; 114 in 115 if platform.isAarch32 && platform ? gcc.float-abi then 116 lib.throwIfNot (builtins.elem platform.gcc.float-abi [ 117 "soft" 118 "softfp" 119 "hard" 120 ]) "unsupported ARM float ABI ${platform.gcc.float-abi}" platform.gcc.float-abi 121 else 122 null; 123 # TODO: also handle MIPS flags (mips_arch, mips_fpu, mips_float_abi). 124 125 useSharedHttpParser = 126 !stdenv.hostPlatform.isDarwin && lib.versionOlder "${majorVersion}.${minorVersion}" "11.4"; 127 useSharedSQLite = lib.versionAtLeast version "22.5"; 128 129 sharedLibDeps = { 130 inherit openssl zlib libuv; 131 } 132 // (lib.optionalAttrs useSharedHttpParser { 133 inherit http-parser; 134 }) 135 // (lib.optionalAttrs useSharedSQLite { 136 inherit sqlite; 137 }); 138 139 copyLibHeaders = map (name: "${lib.getDev sharedLibDeps.${name}}/include/*") ( 140 builtins.attrNames sharedLibDeps 141 ); 142 143 # Currently stdenv sets CC/LD/AR/etc environment variables to program names 144 # instead of absolute paths. If we add cctools to nativeBuildInputs, that 145 # would shadow stdenv’s bintools and potentially break other parts of the 146 # build. The correct behavior is to use absolute paths, and there is a PR for 147 # that, see https://github.com/NixOS/nixpkgs/pull/314920. As a temporary 148 # workaround, we use only a single program we need (and that is not part of 149 # the stdenv). 150 darwin-cctools-only-libtool = 151 # Would be nice to have onlyExe builder similar to onlyBin… 152 runCommand "darwin-cctools-only-libtool" { cctools = lib.getBin buildPackages.cctools; } '' 153 mkdir -p "$out/bin" 154 ln -s "$cctools/bin/libtool" "$out/bin/libtool" 155 ''; 156 157 # a script which claims to be a different script but switches to simply touching its output 158 # when an environment variable is set. See CC_host, --cross-compiling, and postConfigure. 159 touchScript = 160 real: 161 writeScript "touch-script" '' 162 #!${stdenv.shell} 163 if [ -z "$FAKE_TOUCH" ]; then 164 exec "${real}" "$@" 165 fi 166 while [ "$#" != "0" ]; do 167 if [ "$1" == "-o" ]; then 168 shift 169 touch "$1" 170 fi 171 shift 172 done 173 ''; 174 175 downloadDir = if lib.strings.hasInfix "-rc." version then "download/rc" else "dist"; 176 177 package = stdenv.mkDerivation ( 178 finalAttrs: 179 let 180 /** 181 the final package fixed point, after potential overrides 182 */ 183 self = finalAttrs.finalPackage; 184 in 185 { 186 inherit pname version; 187 188 src = fetchurl { 189 url = "https://nodejs.org/${downloadDir}/v${version}/node-v${version}.tar.xz"; 190 inherit sha256; 191 }; 192 193 strictDeps = true; 194 195 env = { 196 # Tell ninja to avoid ANSI sequences, otherwise we don’t see build 197 # progress in Nix logs. 198 # 199 # Note: do not set TERM=dumb environment variable globally, it is used in 200 # test-ci-js test suite to skip tests that otherwise run fine. 201 NINJA = "TERM=dumb ninja"; 202 } 203 // lib.optionalAttrs (!canExecute && !canEmulate) { 204 # these are used in the --cross-compiling case. see comment at postConfigure. 205 CC_host = touchScript "${buildPackages.stdenv.cc}/bin/cc"; 206 CXX_host = touchScript "${buildPackages.stdenv.cc}/bin/c++"; 207 AR_host = touchScript "${buildPackages.stdenv.cc}/bin/ar"; 208 }; 209 210 # NB: technically, we do not need bash in build inputs since all scripts are 211 # wrappers over the corresponding JS scripts. There are some packages though 212 # that use bash wrappers, e.g. polaris-web. 213 buildInputs = [ 214 zlib 215 libuv 216 openssl 217 http-parser 218 icu 219 bash 220 ] 221 ++ lib.optionals useSharedSQLite [ sqlite ]; 222 223 nativeBuildInputs = [ 224 installShellFiles 225 ninja 226 pkgconf 227 python 228 ] 229 ++ lib.optionals stdenv.buildPlatform.isDarwin [ 230 # gyp checks `sysctl -n hw.memsize` if `sys.platform == "darwin"`. 231 unixtools.sysctl 232 ] 233 ++ lib.optionals stdenv.hostPlatform.isDarwin [ 234 # For gyp-mac-tool if `flavor == "mac"`. 235 darwin-cctools-only-libtool 236 ]; 237 238 # We currently rely on Makefile and stdenv for build phases, so do not let 239 # ninja’s setup hook to override default stdenv phases. 240 dontUseNinjaBuild = true; 241 dontUseNinjaCheck = true; 242 dontUseNinjaInstall = true; 243 244 outputs = [ 245 "out" 246 "libv8" 247 ] 248 ++ lib.optionals (stdenv.hostPlatform == stdenv.buildPlatform) [ "dev" ]; 249 setOutputFlags = false; 250 moveToDev = false; 251 252 configureFlags = [ 253 "--ninja" 254 "--with-intl=system-icu" 255 "--openssl-use-def-ca-store" 256 # --cross-compiling flag enables use of CC_host et. al 257 (if canExecute || canEmulate then "--no-cross-compiling" else "--cross-compiling") 258 "--dest-os=${destOS}" 259 "--dest-cpu=${destCPU}" 260 ] 261 ++ lib.optionals (destARMFPU != null) [ "--with-arm-fpu=${destARMFPU}" ] 262 ++ lib.optionals (destARMFloatABI != null) [ "--with-arm-float-abi=${destARMFloatABI}" ] 263 ++ lib.optionals (!canExecute && canEmulate) [ 264 # Node.js requires matching bitness between build and host platforms, e.g. 265 # for V8 startup snapshot builder (see tools/snapshot) and some other 266 # tools. We apply a patch that runs these tools using a host platform 267 # emulator and avoid cross-compiling altogether (from the build system’s 268 # perspective). 269 "--emulator=${emulator}" 270 ] 271 ++ lib.optionals (lib.versionOlder version "19") [ "--without-dtrace" ] 272 ++ lib.optionals (!enableNpm) [ "--without-npm" ] 273 ++ lib.concatMap (name: [ 274 "--shared-${name}" 275 "--shared-${name}-libpath=${lib.getLib sharedLibDeps.${name}}/lib" 276 /** 277 Closure notes: we explicitly avoid specifying --shared-*-includes, 278 as that would put the paths into bin/nodejs. 279 Including pkg-config in build inputs would also have the same effect! 280 281 FIXME: the statement above is outdated, we have to include pkg-config 282 in build inputs for system-icu. 283 */ 284 ]) (builtins.attrNames sharedLibDeps); 285 286 configurePlatforms = [ ]; 287 288 dontDisableStatic = true; 289 290 configureScript = writeScript "nodejs-configure" '' 291 exec ${python.executable} configure.py "$@" 292 ''; 293 294 # In order to support unsupported cross configurations, we copy some intermediate executables 295 # from a native build and replace all the build-system tools with a script which simply touches 296 # its outfile. We have to indiana-jones-swap the build-system-targeted tools since they are 297 # tested for efficacy at configure time. 298 postConfigure = lib.optionalString (!canEmulate && !canExecute) '' 299 cp ${buildNode.dev}/bin/* out/Release 300 export FAKE_TOUCH=1 301 ''; 302 303 enableParallelBuilding = true; 304 305 # Don't allow enabling content addressed conversion as `nodejs` 306 # checksums it's image before conversion happens and image loading 307 # breaks: 308 # $ nix build -f. nodejs --arg config '{ contentAddressedByDefault = true; }' 309 # $ ./result/bin/node 310 # Check failed: VerifyChecksum(blob). 311 __contentAddressed = false; 312 313 passthru.interpreterName = "nodejs"; 314 315 passthru.pkgs = callPackage ../../node-packages/default.nix { 316 nodejs = self; 317 }; 318 319 setupHook = ./setup-hook.sh; 320 321 pos = builtins.unsafeGetAttrPos "version" args; 322 323 inherit patches; 324 325 __darwinAllowLocalNetworking = true; # for tests 326 327 doCheck = canExecute; 328 329 # See https://github.com/nodejs/node/issues/22006 330 enableParallelChecking = false; 331 332 # Some dependencies required for tools/doc/node_modules (and therefore 333 # test-addons, jstest and others) target are not included in the tarball. 334 # Run test targets that do not require network access. 335 checkTarget = lib.concatStringsSep " " ( 336 [ 337 "build-js-native-api-tests" 338 "build-node-api-tests" 339 "tooltest" 340 "cctest" 341 ] 342 ++ lib.optionals (!stdenv.buildPlatform.isDarwin || lib.versionAtLeast version "20") [ 343 # There are some test failures on macOS before v20 that are not worth the 344 # time to debug for a version that would be eventually removed in less 345 # than a year (Node.js 18 will be EOL at 2025-04-30). Note that these 346 # failures are specific to Nix sandbox on macOS and should not affect 347 # actual functionality. 348 "test-ci-js" 349 ] 350 ); 351 352 checkFlags = [ 353 # Do not create __pycache__ when running tests. 354 "PYTHONDONTWRITEBYTECODE=1" 355 ] 356 ++ lib.optionals (stdenv.buildPlatform.isDarwin && stdenv.buildPlatform.isx86_64) [ 357 # Python 3.12 introduced a warning for calling `os.fork()` in a 358 # multi‐threaded program. For some reason, the Node.js 359 # `tools/pseudo-tty.py` program used for PTY‐related tests 360 # triggers this warning on Hydra, on `x86_64-darwin` only, 361 # despite not creating any threads itself. This causes the 362 # Node.js test runner to misinterpret the warnings as part of the 363 # test output and fail. It does not reproduce reliably off Hydra 364 # on Intel Macs, or occur on the `aarch64-darwin` builds. 365 # 366 # This seems likely to be related to Rosetta 2, but it could also 367 # be some strange x86‐64‐only threading behaviour of the Darwin 368 # system libraries, or a bug in CPython, or something else 369 # haunted about the Nixpkgs/Hydra build environment. We silence 370 # the warnings in the hope that closing our eyes will make the 371 # ghosts go away. 372 "PYTHONWARNINGS=ignore::DeprecationWarning" 373 ] 374 ++ lib.optionals (!stdenv.buildPlatform.isDarwin || lib.versionAtLeast version "20") [ 375 "FLAKY_TESTS=skip" 376 # Skip some tests that are not passing in this context 377 "CI_SKIP_TESTS=${ 378 lib.concatStringsSep "," ( 379 [ 380 # Tests don't work in sandbox. 381 "test-child-process-exec-env" 382 "test-child-process-uid-gid" 383 "test-fs-write-stream-eagain" 384 "test-process-euid-egid" 385 "test-process-initgroups" 386 "test-process-setgroups" 387 "test-process-uid-gid" 388 "test-setproctitle" 389 # This is a bit weird, but for some reason fs watch tests fail with 390 # sandbox. 391 "test-fs-promises-watch" 392 "test-fs-watch" 393 "test-fs-watch-encoding" 394 "test-fs-watch-non-recursive" 395 "test-fs-watch-recursive-add-file" 396 "test-fs-watch-recursive-add-file-to-existing-subfolder" 397 "test-fs-watch-recursive-add-file-to-new-folder" 398 "test-fs-watch-recursive-add-file-with-url" 399 "test-fs-watch-recursive-add-folder" 400 "test-fs-watch-recursive-assert-leaks" 401 "test-fs-watch-recursive-promise" 402 "test-fs-watch-recursive-symlink" 403 "test-fs-watch-recursive-sync-write" 404 "test-fs-watch-recursive-update-file" 405 "test-fs-watchfile" 406 "test-runner-run" 407 "test-runner-watch-mode" 408 "test-watch-mode-files_watcher" 409 ] 410 ++ lib.optionals (!lib.versionAtLeast version "22") [ 411 "test-tls-multi-key" 412 ] 413 ++ lib.optionals stdenv.hostPlatform.is32bit [ 414 # utime (actually utimensat) fails with EINVAL on 2038 timestamp 415 "test-fs-utimes-y2K38" 416 ] 417 ++ lib.optionals stdenv.buildPlatform.isDarwin [ 418 # Disable tests that don’t work under macOS sandbox. 419 "test-macos-app-sandbox" 420 "test-os" 421 "test-os-process-priority" 422 423 # Debugger tests failing on macOS 15.4 424 "test-debugger-extract-function-name" 425 "test-debugger-random-port-with-inspect-port" 426 "test-debugger-launch" 427 "test-debugger-pid" 428 429 # Those are annoyingly flaky, but not enough to be marked as such upstream. 430 "test-wasi" 431 ] 432 ++ lib.optionals (stdenv.buildPlatform.isDarwin && stdenv.buildPlatform.isx86_64) [ 433 # These tests fail on x86_64-darwin (even without sandbox). 434 # TODO: revisit at a later date. 435 "test-fs-readv" 436 "test-fs-readv-sync" 437 "test-vm-memleak" 438 439 # Those are annoyingly flaky, but not enough to be marked as such upstream. 440 "test-tick-processor-arguments" 441 "test-set-raw-mode-reset-signal" 442 ] 443 # Those are annoyingly flaky, but not enough to be marked as such upstream. 444 ++ lib.optional (majorVersion == "22") "test-child-process-stdout-flush-exit" 445 ) 446 }" 447 ]; 448 449 postInstall = 450 let 451 # nodejs_18 does not have node_js2c, and we don't want to rebuild the other ones 452 # FIXME: fix this cleanly in staging 453 tools = 454 if majorVersion == "18" then 455 "{bytecode_builtins_list_generator,mksnapshot,torque,gen-regexp-special-case}" 456 else 457 "{bytecode_builtins_list_generator,mksnapshot,torque,node_js2c,gen-regexp-special-case}"; 458 in 459 lib.optionalString (stdenv.hostPlatform == stdenv.buildPlatform) '' 460 mkdir -p $dev/bin 461 cp out/Release/${tools} $dev/bin 462 '' 463 + '' 464 465 HOST_PATH=$out/bin patchShebangs --host $out 466 467 ${lib.optionalString canExecute '' 468 $out/bin/node --completion-bash > node.bash 469 installShellCompletion node.bash 470 ''} 471 472 ${lib.optionalString enableNpm '' 473 mkdir -p $out/share/bash-completion/completions 474 ln -s $out/lib/node_modules/npm/lib/utils/completion.sh \ 475 $out/share/bash-completion/completions/npm 476 for dir in "$out/lib/node_modules/npm/man/"*; do 477 mkdir -p $out/share/man/$(basename "$dir") 478 for page in "$dir"/*; do 479 ln -rs $page $out/share/man/$(basename "$dir") 480 done 481 done 482 ''} 483 484 # install the missing headers for node-gyp 485 # TODO: use propagatedBuildInputs instead of copying headers. 486 cp -r ${lib.concatStringsSep " " copyLibHeaders} $out/include/node 487 488 # assemble a static v8 library and put it in the 'libv8' output 489 mkdir -p $libv8/lib 490 pushd out/Release/obj 491 find . -path "**/torque_*/**/*.o" -or -path "**/v8*/**/*.o" \ 492 -and -not -name "torque.*" \ 493 -and -not -name "mksnapshot.*" \ 494 -and -not -name "gen-regexp-special-case.*" \ 495 -and -not -name "bytecode_builtins_list_generator.*" \ 496 | sort -u >files 497 test -s files # ensure that the list is not empty 498 $AR -cqs $libv8/lib/libv8.a @files 499 popd 500 501 # copy v8 headers 502 cp -r deps/v8/include $libv8/ 503 504 # create a pkgconfig file for v8 505 major=$(grep V8_MAJOR_VERSION deps/v8/include/v8-version.h | cut -d ' ' -f 3) 506 minor=$(grep V8_MINOR_VERSION deps/v8/include/v8-version.h | cut -d ' ' -f 3) 507 patch=$(grep V8_PATCH_LEVEL deps/v8/include/v8-version.h | cut -d ' ' -f 3) 508 mkdir -p $libv8/lib/pkgconfig 509 cat > $libv8/lib/pkgconfig/v8.pc << EOF 510 Name: v8 511 Description: V8 JavaScript Engine 512 Version: $major.$minor.$patch 513 Libs: -L$libv8/lib -lv8 -pthread -licui18n -licuuc 514 Cflags: -I$libv8/include 515 EOF 516 '' 517 + lib.optionalString (stdenv.hostPlatform == stdenv.buildPlatform) '' 518 cp -r $out/include $dev/include 519 ''; 520 521 passthru.tests = { 522 version = testers.testVersion { 523 package = self; 524 version = "v${lib.head (lib.strings.splitString "-rc." version)}"; 525 }; 526 }; 527 528 passthru.updateScript = import ./update.nix { 529 inherit 530 writeScript 531 common-updater-scripts 532 coreutils 533 curl 534 fetchurl 535 gnugrep 536 gnupg 537 jq 538 runtimeShell 539 ; 540 inherit lib; 541 inherit majorVersion; 542 }; 543 544 meta = with lib; { 545 description = "Event-driven I/O framework for the V8 JavaScript engine"; 546 homepage = "https://nodejs.org"; 547 changelog = "https://github.com/nodejs/node/releases/tag/v${version}"; 548 license = licenses.mit; 549 maintainers = with maintainers; [ aduh95 ]; 550 platforms = platforms.linux ++ platforms.darwin ++ platforms.freebsd; 551 # This broken condition is likely too conservative. Feel free to loosen it if it works. 552 broken = 553 !canExecute && !canEmulate && (stdenv.buildPlatform.parsed.cpu != stdenv.hostPlatform.parsed.cpu); 554 mainProgram = "node"; 555 knownVulnerabilities = optional (versionOlder version "18") "This NodeJS release has reached its end of life. See https://nodejs.org/en/about/releases/."; 556 }; 557 558 passthru.python = python; # to ensure nodeEnv uses the same version 559 } 560 ); 561in 562package