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