From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Jeremy Apthorp Date: Tue, 26 Feb 2019 17:07:45 -0800 Subject: build: add GN build files This adds GN build files for Node, so we don't have to build with GYP. Note that there always GN files in upstream Node in 20/21 branches, however those files were cherry-picked from main branch and do not really in 20/21. We have to wait until 22 is released to be able to build with upstream GN files. diff --git a/configure.py b/configure.py index 4560bac7b8e3c707ecea5a425f642efb9de9ed36..e9c2a4391f4058a21a259cacaac4fde5d199288e 100755 --- a/configure.py +++ b/configure.py @@ -1722,7 +1722,7 @@ def configure_v8(o, configs): # Until we manage to get rid of all those, v8_enable_sandbox cannot be used. # Note that enabling pointer compression without enabling sandbox is unsupported by V8, # so this can be broken at any time. - o['variables']['v8_enable_sandbox'] = 0 + o['variables']['v8_enable_sandbox'] = 1 if options.enable_pointer_compression else 0 o['variables']['v8_enable_pointer_compression_shared_cage'] = 1 if options.enable_pointer_compression else 0 o['variables']['v8_enable_external_code_space'] = 1 if options.enable_pointer_compression else 0 o['variables']['v8_enable_31bit_smis_on_64bit_arch'] = 1 if options.enable_pointer_compression else 0 diff --git a/node.gni b/node.gni index 35ccd0487f20cece033d58827ecb7ed016908ee4..b4450e3dd17994d1eaf59eb5cff5912545e89793 100644 --- a/node.gni +++ b/node.gni @@ -5,10 +5,10 @@ # Embedder options. declare_args() { # The location of Node.js in source code tree. - node_path = "//node" + node_path = "//third_party/electron_node" # The location of V8 - use the one from node's deps by default. - node_v8_path = "$node_path/deps/v8" + node_v8_path = "//v8" # The location of OpenSSL - use the one from node's deps by default. node_openssl_path = "$node_path/deps/openssl" @@ -44,7 +44,7 @@ declare_args() { node_openssl_system_ca_path = "" # Initialize v8 platform during node.js startup. - node_use_v8_platform = true + node_use_v8_platform = false # Custom build tag. node_tag = "" @@ -64,10 +64,16 @@ declare_args() { # TODO(zcbenz): There are few broken things for now: # 1. cross-os compilation is not supported. # 2. node_mksnapshot crashes when cross-compiling for x64 from arm64. - node_use_node_snapshot = (host_os == target_os) && !(host_cpu == "arm64" && target_cpu == "x64") + node_use_node_snapshot = false # Build with Amaro (TypeScript utils). node_use_amaro = true + + # Allows downstream packagers (eg. Linux distributions) to build against system shared libraries. + use_system_cares = false + use_system_nghttp2 = false + use_system_llhttp = false + use_system_histogram = false } assert(!node_enable_inspector || node_use_openssl, diff --git a/src/node_builtins.cc b/src/node_builtins.cc index 092341dbfbabe15b15ed43057d399f754505f6fd..f14b45850e42585f5686b7201e2b8281ed8c24e1 100644 --- a/src/node_builtins.cc +++ b/src/node_builtins.cc @@ -788,6 +788,7 @@ void BuiltinLoader::RegisterExternalReferences( registry->Register(GetNatives); RegisterExternalReferencesForInternalizedBuiltinCode(registry); + EmbedderRegisterExternalReferencesForInternalizedBuiltinCode(registry); } } // namespace builtins diff --git a/src/node_builtins.h b/src/node_builtins.h index f9426599f2d5dc6ad061407f0c4eb2c9203a4433..302030f610965f07dd6998d282275c1bdf738009 100644 --- a/src/node_builtins.h +++ b/src/node_builtins.h @@ -74,6 +74,8 @@ using BuiltinCodeCacheMap = // Generated by tools/js2c.cc as node_javascript.cc void RegisterExternalReferencesForInternalizedBuiltinCode( ExternalReferenceRegistry* registry); +void EmbedderRegisterExternalReferencesForInternalizedBuiltinCode( + ExternalReferenceRegistry* registry); // Handles compilation and caching of built-in JavaScript modules and // bootstrap scripts, whose source are bundled into the binary as static data. diff --git a/tools/install.py b/tools/install.py index 8797b59e59c85a8877b977fa3281e50165e6f6b2..0af01e075616195f38fb242626dcab770ec1eb57 100755 --- a/tools/install.py +++ b/tools/install.py @@ -222,6 +222,7 @@ def headers(options, action): 'include/cppgc/internal/caged-heap-local-data.h', 'include/cppgc/internal/caged-heap.h', 'include/cppgc/internal/compiler-specific.h', + 'include/cppgc/internal/conditional-stack-allocated.h', 'include/cppgc/internal/finalizer-trait.h', 'include/cppgc/internal/gc-info.h', 'include/cppgc/internal/logging.h', @@ -301,6 +302,7 @@ def headers(options, action): 'include/v8-promise.h', 'include/v8-proxy.h', 'include/v8-regexp.h', + 'include/v8-sandbox.h', 'include/v8-script.h', 'include/v8-snapshot.h', 'include/v8-source-location.h', diff --git a/tools/js2c.cc b/tools/js2c.cc old mode 100644 new mode 100755 index 21992cbe894a880e3223c379326b62db22f2f12d..1296a5457422099035ba34f2b02624f2e9dfb0f0 --- a/tools/js2c.cc +++ b/tools/js2c.cc @@ -28,6 +28,7 @@ namespace js2c { int Main(int argc, char* argv[]); static bool is_verbose = false; +static bool only_js = false; void Debug(const char* format, ...) { va_list arguments; @@ -175,6 +176,7 @@ const char* kTemplate = R"( #include "node_builtins.h" #include "node_external_reference.h" #include "node_internals.h" +#include "node_threadsafe_cow-inl.h" namespace node { @@ -190,7 +192,11 @@ const ThreadsafeCopyOnWrite global_source_map { } // anonymous namespace void BuiltinLoader::LoadJavaScriptSource() { - source_ = global_source_map; + BuiltinSourceMap map = *source_.read(); + BuiltinSourceMap new_map = *global_source_map.read(); + + map.merge(new_map); + source_ = ThreadsafeCopyOnWrite(map); } void RegisterExternalReferencesForInternalizedBuiltinCode( @@ -207,6 +213,45 @@ UnionBytes BuiltinLoader::GetConfig() { } // namespace node )"; +const char* kEmbedderTemplate = R"( +#include "env-inl.h" +#include "node_builtins.h" +#include "node_external_reference.h" +#include "node_internals.h" +#include "node_threadsafe_cow-inl.h" + +namespace node { + +namespace builtins { + +%.*s +namespace { +const ThreadsafeCopyOnWrite global_source_map { + BuiltinSourceMap { +%.*s + } // BuiltinSourceMap + +}; // ThreadsafeCopyOnWrite +} // anonymous namespace + +void BuiltinLoader::LoadEmbedderJavaScriptSource() { + BuiltinSourceMap map = *source_.read(); + BuiltinSourceMap new_map = *global_source_map.read(); + + map.merge(new_map); + source_ = ThreadsafeCopyOnWrite(map); +} + +void EmbedderRegisterExternalReferencesForInternalizedBuiltinCode( + ExternalReferenceRegistry* registry) { +%.*s +} + +} // namespace builtins + +} // namespace node +)"; + Fragment Format(const Fragments& definitions, const Fragments& initializers, const Fragments& registrations) { @@ -216,13 +261,12 @@ Fragment Format(const Fragments& definitions, size_t init_size = init_buf.size(); std::vector reg_buf = Join(registrations, "\n"); size_t reg_size = reg_buf.size(); - - size_t result_size = - def_size + init_size + reg_size + strlen(kTemplate) + 100; + size_t result_size = def_size + init_size + reg_size + + strlen(only_js ? kEmbedderTemplate: kTemplate) + 300; std::vector result(result_size, 0); int r = snprintf(result.data(), result_size, - kTemplate, + only_js ? kEmbedderTemplate: kTemplate, static_cast(def_buf.size()), def_buf.data(), static_cast(init_buf.size()), @@ -846,12 +890,15 @@ int JS2C(const FileList& js_files, } } + if (!only_js) { assert(FilenameIsConfigGypi(config)); // "config.gypi" -> config_raw. int r = AddGypi("config", config, &definitions); if (r != 0) { return r; } + } + Fragment out = Format(definitions, initializers, registrations); return WriteIfChanged(out, dest); } @@ -877,6 +924,8 @@ int Main(int argc, char* argv[]) { std::string arg(argv[i]); if (arg == "--verbose") { is_verbose = true; + } else if (arg == "--only-js") { + only_js = true; } else if (arg == "--root") { if (i == argc - 1) { fprintf(stderr, "--root must be followed by a path\n"); @@ -925,6 +974,14 @@ int Main(int argc, char* argv[]) { } } + if (only_js) { + auto js_it = file_map.find(".js"); + + assert(file_map.size() == 1); + assert(js_it != file_map.end()); + + return JS2C(js_it->second, FileList(), std::string(), output); + } else { // Should have exactly 3 types: `.js`, `.mjs` and `.gypi`. assert(file_map.size() == 3); auto gypi_it = file_map.find(".gypi"); @@ -951,6 +1008,7 @@ int Main(int argc, char* argv[]) { std::sort(mjs_it->second.begin(), mjs_it->second.end()); return JS2C(js_it->second, mjs_it->second, gypi_it->second[0], output); + } } } // namespace js2c } // namespace node diff --git a/tools/search_files.py b/tools/search_files.py index 856878c33681a73d41016729dabe48b0a6a80589..91a11852d206b65485fe90fd037a0bd17a16c20b 100755 --- a/tools/search_files.py +++ b/tools/search_files.py @@ -14,6 +14,7 @@ if __name__ == '__main__': try: files = SearchFiles(*sys.argv[2:]) files = [ os.path.relpath(x, sys.argv[1]) for x in files ] + files = [os.path.normpath(x).replace(os.sep, '/') for x in files] # Apply the same transform in SearchFiles after relpath if sys.platform == 'win32': files = [ x.replace('\\', '/') for x in files ] diff --git a/unofficial.gni b/unofficial.gni index 44641b92678ab2f28e6f5de75a92878f9f3d322d..e17e4f043af6e4047ab82723ffd83187f3c04c5c 100644 --- a/unofficial.gni +++ b/unofficial.gni @@ -142,32 +142,42 @@ template("node_gn_build") { public_configs = [ ":node_external_config", "deps/googletest:googletest_config", + ":zstd_include_config" ] public_deps = [ "deps/ada", "deps/uv", + "//electron:electron_js2c", "deps/simdjson", "$node_v8_path", ] deps = [ ":run_node_js2c", - "deps/brotli", "deps/cares", "deps/histogram", "deps/llhttp", "deps/nbytes", "deps/nghttp2", - "deps/ngtcp2", "deps/postject", "deps/sqlite", "deps/uvwasi", - "deps/zstd", "//third_party/zlib", + "//third_party/brotli:dec", + "//third_party/brotli:enc", + "//third_party/zstd:decompress", + "//third_party/zstd:headers", "$node_simdutf_path", "$node_v8_path:v8_libplatform", ] + cflags_cc = [ + "-Wno-unguarded-availability-new", + "-Wno-return-stack-address" + ] + sources = [ + "src/node_snapshot_stub.cc", + "$root_gen_dir/electron_natives.cc", "$target_gen_dir/node_javascript.cc", ] + gypi_values.node_sources @@ -190,7 +200,7 @@ template("node_gn_build") { } if (node_use_openssl) { deps += [ "deps/ncrypto" ] - public_deps += [ "$node_openssl_path" ] + public_deps += [ "//third_party/boringssl" ] sources += gypi_values.node_crypto_sources } if (node_enable_inspector) { @@ -214,6 +224,10 @@ template("node_gn_build") { } } + config("zstd_include_config") { + include_dirs = [ "//third_party/zstd/src/lib" ] + } + executable(target_name) { forward_variables_from(invoker, "*") @@ -288,6 +302,7 @@ template("node_gn_build") { } executable("node_js2c") { + defines = [] deps = [ "deps/uv", "$node_simdutf_path", @@ -298,26 +313,75 @@ template("node_gn_build") { "src/embedded_data.cc", "src/embedded_data.h", ] - include_dirs = [ "src" ] + include_dirs = [ "src", "tools" ] + + if (!is_win) { + defines += [ "NODE_JS2C_USE_STRING_LITERALS" ] + } + } + + node_deps_files = gypi_values.deps_files + node_builtin_shareable_builtins + node_library_files = exec_script("./tools/search_files.py", + [ rebase_path(".", root_build_dir), + rebase_path("lib", root_build_dir), + "js" ], + "list lines") + + fs_files = [ + "lib/internal/fs/cp/cp-sync.js", + "lib/internal/fs/cp/cp.js", + "lib/internal/fs/dir.js", + "lib/internal/fs/glob.js", + "lib/internal/fs/promises.js", + "lib/internal/fs/read/context.js", + "lib/internal/fs/recursive_watch.js", + "lib/internal/fs/rimraf.js", + "lib/internal/fs/streams.js", + "lib/internal/fs/sync_write_stream.js", + "lib/internal/fs/utils.js", + "lib/internal/fs/watchers.js", + "lib/fs.js", + "lib/fs/promises.js" + ] + + original_fs_files = [] + foreach(file, fs_files) { + original_fs_files += [string_replace(string_replace(string_replace(file, "internal/fs/", "internal/original-fs/"), "lib/fs.js", "lib/original-fs.js"), "lib/fs/", "lib/original-fs/")] + } + + copy("node_js2c_inputs") { + sources = node_deps_files + node_library_files + outputs = [ + "$target_gen_dir/js2c_inputs/{{source_target_relative}}", + ] + } + + action("node_js2c_original_fs") { + script = "//electron/script/node/generate_original_fs.py" + inputs = fs_files + deps = [ ":node_js2c_inputs" ] + + outputs = [] + foreach(file, original_fs_files) { + outputs += ["$target_gen_dir/js2c_inputs/$file"] + } + + args = [rebase_path("$target_gen_dir/js2c_inputs")] + fs_files } action("run_node_js2c") { - script = "$node_v8_path/tools/run.py" + script = "//electron/build/run-in-dir.py" deps = [ + ":node_js2c_original_fs", ":node_js2c($host_toolchain)", ":generate_config_gypi", ] - node_deps_files = gypi_values.deps_files + node_builtin_shareable_builtins - node_library_files = exec_script("./tools/search_files.py", - [ rebase_path(".", root_build_dir), - rebase_path("lib", root_build_dir), - "js" ], - "list lines") - + config_gypi = [ "$target_gen_dir/config.gypi" ] inputs = node_library_files + node_deps_files + - [ "$target_gen_dir/config.gypi" ] + get_target_outputs(":node_js2c_original_fs") + + config_gypi outputs = [ "$target_gen_dir/node_javascript.cc" ] # Get the path to node_js2c executable of the host toolchain. @@ -331,11 +395,11 @@ template("node_gn_build") { get_label_info(":node_js2c($host_toolchain)", "name") + host_executable_suffix - args = [ rebase_path(node_js2c_path), - rebase_path("$target_gen_dir/node_javascript.cc"), - "--root", rebase_path("."), - "lib", rebase_path("$target_gen_dir/config.gypi") ] + - node_deps_files + args = [ rebase_path("$target_gen_dir/js2c_inputs"), + rebase_path(node_js2c_path), + rebase_path("$target_gen_dir/node_javascript.cc")] + + rebase_path(config_gypi) + node_deps_files + + original_fs_files + node_library_files } executable("node_cctest") {