Skip to content

Commit de5644c

Browse files
authored
tools: make v8.nix more stable
If we only pass to the V8 builders the dependencies it actually needs, we can avoid rebuilding the same version of V8 just because an unrelated Node.js dependency has been updated. PR-URL: #62508 Reviewed-By: Filip Skokan <panva.ip@gmail.com>
1 parent 8c3cf47 commit de5644c

File tree

5 files changed

+326
-107
lines changed

5 files changed

+326
-107
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1212,6 +1212,7 @@ $(TARBALL): release-only doc-only
12121212
mkdir -p $(TARNAME)/doc/api
12131213
cp doc/node.1 $(TARNAME)/doc/node.1
12141214
cp -r out/doc/api/* $(TARNAME)/doc/api/
1215+
sed 's/fileset = fileset.intersection (fileset.gitTracked root)/fileset =/' tools/nix/v8.nix > $(TARNAME)/tools/nix/v8.nix
12151216
$(RM) -r $(TARNAME)/.editorconfig
12161217
$(RM) -r $(TARNAME)/.git*
12171218
$(RM) -r $(TARNAME)/.mailmap

shell.nix

Lines changed: 66 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,18 @@
1818
withSQLite ? true,
1919
withSSL ? true,
2020
withTemporal ? false,
21-
sharedLibDeps ?
22-
let
23-
d = import ./tools/nix/sharedLibDeps.nix {
24-
inherit
25-
pkgs
26-
withLief
27-
withQuic
28-
withSQLite
29-
withSSL
30-
withTemporal
31-
;
32-
};
33-
in
34-
# To avoid conflicts with V8's bundled simdutf lib, it's easier to remove it when using a precompiled V8.
35-
if (useSeparateDerivationForV8 != false) then builtins.removeAttrs d [ "simdutf" ] else d,
21+
sharedLibDeps ? (
22+
import ./tools/nix/sharedLibDeps.nix {
23+
inherit
24+
pkgs
25+
withLief
26+
withQuic
27+
withSQLite
28+
withSSL
29+
withTemporal
30+
;
31+
}
32+
),
3633

3734
# dev tools (not needed to build Node.js, useful to maintain it)
3835
ncu-path ? null, # Provide this if you want to use a local version of NCU
@@ -45,9 +42,20 @@ let
4542
useSharedAda = builtins.hasAttr "ada" sharedLibDeps;
4643
useSharedOpenSSL = builtins.hasAttr "openssl" sharedLibDeps;
4744

48-
needsRustCompiler = withTemporal && !builtins.hasAttr "temporal_capi" sharedLibDeps;
45+
useSharedTemporal = builtins.hasAttr "temporal_capi" sharedLibDeps;
46+
needsRustCompiler = withTemporal && !useSharedTemporal;
4947

50-
buildInputs = builtins.attrValues sharedLibDeps ++ pkgs.lib.optional useSharedICU icu;
48+
nativeBuildInputs =
49+
pkgs.nodejs-slim_latest.nativeBuildInputs
50+
++ pkgs.lib.optionals needsRustCompiler [
51+
pkgs.cargo
52+
pkgs.rustc
53+
];
54+
buildInputs =
55+
pkgs.lib.optional useSharedICU icu
56+
++ pkgs.lib.optional (withTemporal && useSharedTemporal) sharedLibDeps.temporal_capi;
57+
58+
# Put here only the configure flags that affect the V8 build
5159
configureFlags = [
5260
(
5361
if icu == null then
@@ -56,48 +64,31 @@ let
5664
"--with-intl=${if useSharedICU then "system" else icu}-icu"
5765
)
5866
]
59-
++ extraConfigFlags
60-
++ pkgs.lib.optional (!withAmaro) "--without-amaro"
61-
++ pkgs.lib.optional (!withLief) "--without-lief"
62-
++ pkgs.lib.optional withQuic "--experimental-quic"
63-
++ pkgs.lib.optional (!withSQLite) "--without-sqlite"
64-
++ pkgs.lib.optional (!withSSL) "--without-ssl"
6567
++ pkgs.lib.optional withTemporal "--v8-enable-temporal-support"
66-
++ pkgs.lib.optional (ninja != null) "--ninja"
67-
++ pkgs.lib.optional loadJSBuiltinsDynamically "--node-builtin-modules-path=${builtins.toString ./.}"
68-
++ pkgs.lib.concatMap (name: [
69-
"--shared-${name}"
70-
"--shared-${name}-libpath=${pkgs.lib.getLib sharedLibDeps.${name}}/lib"
71-
"--shared-${name}-include=${pkgs.lib.getInclude sharedLibDeps.${name}}/include"
72-
]) (builtins.attrNames sharedLibDeps);
68+
++ pkgs.lib.optional (withTemporal && useSharedTemporal) "--shared-temporal_capi";
7369
in
7470
pkgs.mkShell {
75-
inherit (pkgs.nodejs-slim_latest) nativeBuildInputs;
71+
inherit nativeBuildInputs;
7672

7773
buildInputs =
78-
buildInputs
74+
builtins.attrValues sharedLibDeps
75+
++ buildInputs
7976
++ pkgs.lib.optional (useSeparateDerivationForV8 != false) (
8077
if useSeparateDerivationForV8 == true then
81-
import ./tools/nix/v8.nix {
82-
inherit
83-
pkgs
84-
configureFlags
85-
buildInputs
86-
needsRustCompiler
87-
;
78+
let
79+
sharedLibsToMock = pkgs.callPackage ./tools/nix/non-v8-deps-mock.nix { };
80+
in
81+
pkgs.callPackage ./tools/nix/v8.nix {
82+
inherit nativeBuildInputs icu;
83+
84+
configureFlags = configureFlags ++ sharedLibsToMock.configureFlags ++ [ "--ninja" ];
85+
buildInputs = buildInputs ++ [ sharedLibsToMock ];
8886
}
8987
else
9088
useSeparateDerivationForV8
9189
);
9290

93-
packages =
94-
pkgs.lib.optional (ccache != null) ccache
95-
++ devTools
96-
++ benchmarkTools
97-
++ pkgs.lib.optionals needsRustCompiler [
98-
pkgs.cargo
99-
pkgs.rustc
100-
];
91+
packages = devTools ++ benchmarkTools ++ pkgs.lib.optional (ccache != null) ccache;
10192

10293
shellHook = pkgs.lib.optionalString (ccache != null) ''
10394
export CC="${pkgs.lib.getExe ccache} $CC"
@@ -107,7 +98,34 @@ pkgs.mkShell {
10798
BUILD_WITH = if (ninja != null) then "ninja" else "make";
10899
NINJA = pkgs.lib.optionalString (ninja != null) "${pkgs.lib.getExe ninja}";
109100
CONFIG_FLAGS = builtins.toString (
110-
configureFlags ++ pkgs.lib.optional (useSeparateDerivationForV8 != false) "--without-bundled-v8"
101+
configureFlags
102+
++ extraConfigFlags
103+
++ pkgs.lib.optional (ninja != null) "--ninja"
104+
++ pkgs.lib.optional (!withAmaro) "--without-amaro"
105+
++ pkgs.lib.optional (!withLief) "--without-lief"
106+
++ pkgs.lib.optional withQuic "--experimental-quic"
107+
++ pkgs.lib.optional (!withSQLite) "--without-sqlite"
108+
++ pkgs.lib.optional (!withSSL) "--without-ssl"
109+
++ pkgs.lib.optional loadJSBuiltinsDynamically "--node-builtin-modules-path=${builtins.toString ./.}"
110+
++ pkgs.lib.optional (useSeparateDerivationForV8 != false) "--without-bundled-v8"
111+
++
112+
pkgs.lib.concatMap
113+
(name: [
114+
"--shared-${name}"
115+
"--shared-${name}-libpath=${pkgs.lib.getLib sharedLibDeps.${name}}/lib"
116+
"--shared-${name}-include=${pkgs.lib.getInclude sharedLibDeps.${name}}/include"
117+
])
118+
(
119+
builtins.attrNames (
120+
if (useSeparateDerivationForV8 != false) then
121+
builtins.removeAttrs sharedLibDeps [
122+
"simdutf"
123+
"temporal_capi"
124+
]
125+
else
126+
sharedLibDeps
127+
)
128+
)
111129
);
112130
NOSQLITE = pkgs.lib.optionalString (!withSQLite) "1";
113131
}

tools/nix/non-v8-deps-mock.nix

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
{
2+
symlinkJoin,
3+
writeTextFile,
4+
validatePkgConfig,
5+
testers,
6+
lib,
7+
}:
8+
9+
let
10+
sharedLibsToMock = {
11+
zlib = [ "zlib" ];
12+
http-parser = [ "libllhttp" ];
13+
libuv = [ "libuv" ];
14+
ada = [ "ada" ];
15+
simdjson = [ "simdjson" ];
16+
brotli = [
17+
"libbrotlidec"
18+
"libbrotlienc"
19+
];
20+
cares = [ "libcares" ];
21+
gtest = [ "gtest" ];
22+
hdr-histogram = [ "hdr_histogram" ];
23+
merve = [ "merve" ];
24+
nbytes = [ "nbytes" ];
25+
nghttp2 = [ "libnghttp2" ];
26+
nghttp3 = [ "libnghttp3" ];
27+
ngtcp2 = [ "libngtcp2" ];
28+
uvwasi = [ "uvwasi" ];
29+
zstd = [ "libzstd" ];
30+
};
31+
in
32+
symlinkJoin (finalAttrs: {
33+
pname = "non-v8-deps-mock";
34+
version = "0.0.0-mock";
35+
36+
nativeBuildInputs = [ validatePkgConfig ];
37+
38+
paths = lib.concatMap (
39+
sharedLibName:
40+
(builtins.map (
41+
pkgName:
42+
writeTextFile {
43+
name = "mock-${pkgName}.pc";
44+
destination = "/lib/pkgconfig/${pkgName}.pc";
45+
text = ''
46+
Name: ${pkgName}
47+
Description: Mock package for ${sharedLibName}
48+
Version: ${finalAttrs.version}
49+
Libs:
50+
Cflags:
51+
'';
52+
}
53+
) sharedLibsToMock.${sharedLibName})
54+
) (builtins.attrNames sharedLibsToMock);
55+
passthru = {
56+
configureFlags = [
57+
"--without-lief"
58+
"--without-sqlite"
59+
"--without-ssl"
60+
]
61+
++ (lib.concatMap (sharedLibName: [
62+
"--shared-${sharedLibName}"
63+
"--shared-${sharedLibName}-libname="
64+
]) (builtins.attrNames sharedLibsToMock));
65+
66+
tests.pkg-config = testers.hasPkgConfigModules {
67+
package = finalAttrs.finalPackage;
68+
};
69+
};
70+
71+
meta = {
72+
description = "Mock of Node.js dependencies that are not needed for building V8";
73+
license = lib.licenses.mit;
74+
pkgConfigModules = lib.concatMap (x: x) (builtins.attrValues sharedLibsToMock);
75+
};
76+
})
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
diff --git a/deps/v8/src/objects/js-temporal-zoneinfo64.cc b/deps/v8/src/objects/js-temporal-zoneinfo64.cc
2+
index 99dd3a84c1e..b6b399c10dc 100644
3+
--- a/deps/v8/src/objects/js-temporal-zoneinfo64.cc
4+
+++ b/deps/v8/src/objects/js-temporal-zoneinfo64.cc
5+
@@ -11,12 +11,44 @@
6+
#include "temporal_rs/TimeZone.hpp"
7+
8+
#ifdef V8_INTL_SUPPORT
9+
-#include "udatamem.h"
10+
+#include "unicode/udata.h"
11+
+typedef struct {
12+
+ uint16_t headerSize;
13+
+ uint8_t magic1;
14+
+ uint8_t magic2;
15+
+} MappedData;
16+
+typedef struct {
17+
+ MappedData dataHeader;
18+
+ UDataInfo info;
19+
+} DataHeader;
20+
+typedef struct {
21+
+ void* Lookup;
22+
+ void* NumEntries;
23+
+} commonDataFuncs;
24+
+struct UDataMemory {
25+
+ const commonDataFuncs *vFuncs; /* Function Pointers for accessing TOC */
26+
+
27+
+ const DataHeader *pHeader; /* Header of the memory being described by this */
28+
+ /* UDataMemory object. */
29+
+ const void *toc; /* For common memory, table of contents for */
30+
+ /* the pieces within. */
31+
+ UBool heapAllocated; /* True if this UDataMemory Object is on the */
32+
+ /* heap and thus needs to be deleted when closed. */
33+
+
34+
+ void *mapAddr; /* For mapped or allocated memory, the start addr. */
35+
+ /* Only non-null if a close operation should unmap */
36+
+ /* the associated data. */
37+
+ void *map; /* Handle, or other data, OS dependent. */
38+
+ /* Only non-null if a close operation should unmap */
39+
+ /* the associated data, and additional info */
40+
+ /* beyond the mapAddr is needed to do that. */
41+
+ int32_t length; /* Length of the data in bytes; -1 if unknown. */
42+
+};
43+
#else
44+
// Defined in builtins-temporal-zoneinfo64-data.cc, generated by
45+
// include-file-as-bytes.py
46+
-extern "C" uint32_t zoneinfo64_static_data[];
47+
-extern "C" size_t zoneinfo64_static_data_len;
48+
+static uint32_t zoneinfo64_static_data[] = {};
49+
+static size_t zoneinfo64_static_data_len = 0;
50+
#endif
51+
52+
namespace v8::internal {
53+
@@ -33,7 +65,7 @@ ZoneInfo64Provider::ZoneInfo64Provider() {
54+
// NOT udata_getLength: this ignores the header,
55+
// and we're parsing resb files with the header
56+
auto length = memory->length;
57+
- const void* data = udata_getRawMemory(memory);
58+
+ const void* data = udata_getMemory(memory);
59+
DCHECK_WITH_MSG(length % 4 == 0, "ICU4C should align udata to uint32_t");
60+
if (length % 4 != 0) {
61+
// This really shouldn't happen: ICU4C aligns these files
62+
--
63+
2.51.0

0 commit comments

Comments
 (0)