mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -05:00
refactor(build): better handle old glibc (#16238)
Follow-up to #16208. - Refactors build.rs behaviour to use `-exported_symbols_list` / `--export-dynamic-symbol-list` - Since all build systems now rely on a symbols list file, I have added `generate_exported_symbols_list`, which derives the symbol list file depending on the platform, which makes `tools/napi/generate_link_win.js` redundant. - Fixes a missed instance of `i8` being used instead of `c_char` Co-authored-by: Divy Srivastava <dj.srivastava23@gmail.com>
This commit is contained in:
parent
e32719c291
commit
fa22956a86
12 changed files with 350 additions and 61 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -843,6 +843,7 @@ dependencies = [
|
|||
"flaky_test",
|
||||
"flate2",
|
||||
"fwdansi",
|
||||
"glibc_version",
|
||||
"google-storage1",
|
||||
"http",
|
||||
"import_map",
|
||||
|
@ -2047,6 +2048,15 @@ dependencies = [
|
|||
"polyval",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glibc_version"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "803ff7635f1ab4e2c064b68a0c60da917d3d18dc8d086130f689d62ce4f1c33e"
|
||||
dependencies = [
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.0"
|
||||
|
|
|
@ -43,6 +43,7 @@ regex = "=1.6.0"
|
|||
serde = { version = "=1.0.144", features = ["derive"] }
|
||||
serde_json = "1.0.64"
|
||||
zstd = '=0.11.2'
|
||||
glibc_version = "0.1.2"
|
||||
|
||||
[target.'cfg(windows)'.build-dependencies]
|
||||
winapi = "=0.3.9"
|
||||
|
|
62
cli/build.rs
62
cli/build.rs
|
@ -332,56 +332,40 @@ fn main() {
|
|||
panic!("Cross compiling with snapshot is not supported.");
|
||||
}
|
||||
|
||||
let symbols_path = std::path::Path::new(
|
||||
format!("generated_symbol_exports_list_{}.def", env::consts::OS).as_str(),
|
||||
)
|
||||
.canonicalize()
|
||||
.expect(
|
||||
"Missing symbols list! Generate using tools/napi/generate_symbols_lists.js",
|
||||
);
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
println!(
|
||||
"cargo:rustc-link-arg-bin=deno=/DEF:{}",
|
||||
std::path::Path::new("exports.def")
|
||||
.canonicalize()
|
||||
.expect(
|
||||
"Missing exports.def! Generate using tools/napi/generate_link_win.js"
|
||||
)
|
||||
.display(),
|
||||
symbols_path.display()
|
||||
);
|
||||
|
||||
#[cfg(all(
|
||||
not(target_os = "windows"),
|
||||
not(all(target_os = "linux", target_arch = "aarch64"))
|
||||
))]
|
||||
{
|
||||
// Load the symbols file generated by the `napi_sym` macro.
|
||||
#[derive(serde::Deserialize)]
|
||||
struct Symbols {
|
||||
symbols: Vec<String>,
|
||||
}
|
||||
let symbols_json =
|
||||
std::fs::read_to_string("./napi_sym/symbol_exports.json").expect(
|
||||
"Missing ./napi_sym/symbol_exports.json! This is a bug in napi_sym",
|
||||
);
|
||||
let symbols: Symbols = serde_json::from_str(&symbols_json)
|
||||
.expect("./napi_sym/symbol_exports.json is not valid JSON");
|
||||
#[cfg(target_os = "macos")]
|
||||
println!(
|
||||
"cargo:rustc-link-arg-bin=deno=-Wl,-exported_symbols_list,{}",
|
||||
symbols_path.display()
|
||||
);
|
||||
|
||||
// Don't export all symbols into the dynamic symbol table. -rdynamic exports *all* symbols introducing binary bloat.
|
||||
// We only need to export Node API symbols.
|
||||
for symbol in symbols.symbols {
|
||||
// TODO(@littledivy): We _might_ hit an argument size limit?
|
||||
// Maybe use `--export-dynamic-symbol-list` / `--exported_symbols_list` instead? https://reviews.llvm.org/D107317
|
||||
#[cfg(target_os = "macos")]
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
let ver = glibc_version::get_version().unwrap();
|
||||
if ver.major <= 2 && ver.minor < 35 {
|
||||
println!("cargo:warning=Compiling with all symbols exported, this will result in a larger binary. Please use glibc 2.35 or later for an optimised build.");
|
||||
println!("cargo:rustc-link-arg-bin=deno=-rdynamic");
|
||||
} else {
|
||||
println!(
|
||||
"cargo:rustc-link-arg-bin=deno=-Wl,-exported_symbol,_{}",
|
||||
symbol
|
||||
);
|
||||
#[cfg(target_os = "linux")]
|
||||
println!(
|
||||
"cargo:rustc-link-arg-bin=deno=-Wl,--export-dynamic-symbol={}",
|
||||
symbol
|
||||
"cargo:rustc-link-arg-bin=deno=-Wl,--export-dynamic-symbol-list={}",
|
||||
symbols_path.display()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Linux + aarch64 does not support a glibc version that supports `--export-dynamic-symbol`.
|
||||
#[cfg(all(target_os = "linux", target_arch = "aarch64"))]
|
||||
println!("cargo:rustc-link-arg-bin=deno=-rdynamic");
|
||||
|
||||
// To debug snapshot issues uncomment:
|
||||
// op_fetch_asset::trace_serializer();
|
||||
|
||||
|
|
144
cli/generated_symbol_exports_list_linux.def
Normal file
144
cli/generated_symbol_exports_list_linux.def
Normal file
|
@ -0,0 +1,144 @@
|
|||
node_api_create_syntax_error
|
||||
napi_make_callback
|
||||
napi_has_named_property
|
||||
napi_async_destroy
|
||||
napi_coerce_to_object
|
||||
napi_get_arraybuffer_info
|
||||
napi_detach_arraybuffer
|
||||
napi_get_undefined
|
||||
napi_reference_unref
|
||||
napi_fatal_error
|
||||
napi_open_callback_scope
|
||||
napi_close_callback_scope
|
||||
napi_get_value_uint32
|
||||
napi_create_function
|
||||
napi_create_arraybuffer
|
||||
napi_get_value_int64
|
||||
napi_get_all_property_names
|
||||
napi_resolve_deferred
|
||||
napi_is_detached_arraybuffer
|
||||
napi_create_string_utf8
|
||||
napi_create_threadsafe_function
|
||||
node_api_throw_syntax_error
|
||||
napi_create_bigint_int64
|
||||
napi_wrap
|
||||
napi_set_property
|
||||
napi_get_value_bigint_int64
|
||||
napi_open_handle_scope
|
||||
napi_create_error
|
||||
napi_create_buffer
|
||||
napi_cancel_async_work
|
||||
napi_is_exception_pending
|
||||
napi_acquire_threadsafe_function
|
||||
napi_create_external
|
||||
napi_get_threadsafe_function_context
|
||||
napi_get_null
|
||||
napi_create_string_utf16
|
||||
napi_get_value_bigint_uint64
|
||||
napi_module_register
|
||||
napi_is_typedarray
|
||||
napi_create_external_buffer
|
||||
napi_get_new_target
|
||||
napi_get_instance_data
|
||||
napi_close_handle_scope
|
||||
napi_get_value_string_utf16
|
||||
napi_get_property_names
|
||||
napi_is_arraybuffer
|
||||
napi_get_cb_info
|
||||
napi_define_properties
|
||||
napi_add_env_cleanup_hook
|
||||
node_api_get_module_file_name
|
||||
napi_get_node_version
|
||||
napi_create_int64
|
||||
napi_create_double
|
||||
napi_get_and_clear_last_exception
|
||||
napi_create_reference
|
||||
napi_get_typedarray_info
|
||||
napi_call_threadsafe_function
|
||||
napi_get_last_error_info
|
||||
napi_create_array_with_length
|
||||
napi_coerce_to_number
|
||||
napi_get_global
|
||||
napi_is_error
|
||||
napi_set_instance_data
|
||||
napi_create_typedarray
|
||||
napi_throw_type_error
|
||||
napi_has_property
|
||||
napi_get_value_external
|
||||
napi_create_range_error
|
||||
napi_typeof
|
||||
napi_ref_threadsafe_function
|
||||
napi_create_bigint_uint64
|
||||
napi_get_prototype
|
||||
napi_adjust_external_memory
|
||||
napi_release_threadsafe_function
|
||||
napi_delete_async_work
|
||||
napi_create_string_latin1
|
||||
napi_is_array
|
||||
napi_unref_threadsafe_function
|
||||
napi_throw_error
|
||||
napi_has_own_property
|
||||
napi_get_reference_value
|
||||
napi_remove_env_cleanup_hook
|
||||
napi_get_value_string_utf8
|
||||
napi_is_promise
|
||||
napi_get_boolean
|
||||
napi_run_script
|
||||
napi_get_element
|
||||
napi_get_named_property
|
||||
napi_get_buffer_info
|
||||
napi_get_value_bool
|
||||
napi_reference_ref
|
||||
napi_create_object
|
||||
napi_create_promise
|
||||
napi_create_int32
|
||||
napi_escape_handle
|
||||
napi_open_escapable_handle_scope
|
||||
napi_throw
|
||||
napi_get_value_double
|
||||
napi_set_named_property
|
||||
napi_call_function
|
||||
napi_create_date
|
||||
napi_object_freeze
|
||||
napi_get_uv_event_loop
|
||||
napi_get_value_string_latin1
|
||||
napi_reject_deferred
|
||||
napi_add_finalizer
|
||||
napi_create_array
|
||||
napi_delete_reference
|
||||
napi_get_date_value
|
||||
napi_create_dataview
|
||||
napi_get_version
|
||||
napi_define_class
|
||||
napi_is_date
|
||||
napi_remove_wrap
|
||||
napi_delete_property
|
||||
napi_instanceof
|
||||
napi_create_buffer_copy
|
||||
napi_delete_element
|
||||
napi_object_seal
|
||||
napi_queue_async_work
|
||||
napi_get_value_bigint_words
|
||||
napi_is_buffer
|
||||
napi_get_array_length
|
||||
napi_get_property
|
||||
napi_new_instance
|
||||
napi_set_element
|
||||
napi_create_bigint_words
|
||||
napi_strict_equals
|
||||
napi_is_dataview
|
||||
napi_close_escapable_handle_scope
|
||||
napi_get_dataview_info
|
||||
napi_get_value_int32
|
||||
napi_unwrap
|
||||
napi_throw_range_error
|
||||
napi_coerce_to_bool
|
||||
napi_create_uint32
|
||||
napi_has_element
|
||||
napi_create_external_arraybuffer
|
||||
napi_create_symbol
|
||||
napi_coerce_to_string
|
||||
napi_create_type_error
|
||||
napi_fatal_exception
|
||||
napi_create_async_work
|
||||
napi_async_init
|
144
cli/generated_symbol_exports_list_macos.def
Normal file
144
cli/generated_symbol_exports_list_macos.def
Normal file
|
@ -0,0 +1,144 @@
|
|||
_node_api_create_syntax_error
|
||||
_napi_make_callback
|
||||
_napi_has_named_property
|
||||
_napi_async_destroy
|
||||
_napi_coerce_to_object
|
||||
_napi_get_arraybuffer_info
|
||||
_napi_detach_arraybuffer
|
||||
_napi_get_undefined
|
||||
_napi_reference_unref
|
||||
_napi_fatal_error
|
||||
_napi_open_callback_scope
|
||||
_napi_close_callback_scope
|
||||
_napi_get_value_uint32
|
||||
_napi_create_function
|
||||
_napi_create_arraybuffer
|
||||
_napi_get_value_int64
|
||||
_napi_get_all_property_names
|
||||
_napi_resolve_deferred
|
||||
_napi_is_detached_arraybuffer
|
||||
_napi_create_string_utf8
|
||||
_napi_create_threadsafe_function
|
||||
_node_api_throw_syntax_error
|
||||
_napi_create_bigint_int64
|
||||
_napi_wrap
|
||||
_napi_set_property
|
||||
_napi_get_value_bigint_int64
|
||||
_napi_open_handle_scope
|
||||
_napi_create_error
|
||||
_napi_create_buffer
|
||||
_napi_cancel_async_work
|
||||
_napi_is_exception_pending
|
||||
_napi_acquire_threadsafe_function
|
||||
_napi_create_external
|
||||
_napi_get_threadsafe_function_context
|
||||
_napi_get_null
|
||||
_napi_create_string_utf16
|
||||
_napi_get_value_bigint_uint64
|
||||
_napi_module_register
|
||||
_napi_is_typedarray
|
||||
_napi_create_external_buffer
|
||||
_napi_get_new_target
|
||||
_napi_get_instance_data
|
||||
_napi_close_handle_scope
|
||||
_napi_get_value_string_utf16
|
||||
_napi_get_property_names
|
||||
_napi_is_arraybuffer
|
||||
_napi_get_cb_info
|
||||
_napi_define_properties
|
||||
_napi_add_env_cleanup_hook
|
||||
_node_api_get_module_file_name
|
||||
_napi_get_node_version
|
||||
_napi_create_int64
|
||||
_napi_create_double
|
||||
_napi_get_and_clear_last_exception
|
||||
_napi_create_reference
|
||||
_napi_get_typedarray_info
|
||||
_napi_call_threadsafe_function
|
||||
_napi_get_last_error_info
|
||||
_napi_create_array_with_length
|
||||
_napi_coerce_to_number
|
||||
_napi_get_global
|
||||
_napi_is_error
|
||||
_napi_set_instance_data
|
||||
_napi_create_typedarray
|
||||
_napi_throw_type_error
|
||||
_napi_has_property
|
||||
_napi_get_value_external
|
||||
_napi_create_range_error
|
||||
_napi_typeof
|
||||
_napi_ref_threadsafe_function
|
||||
_napi_create_bigint_uint64
|
||||
_napi_get_prototype
|
||||
_napi_adjust_external_memory
|
||||
_napi_release_threadsafe_function
|
||||
_napi_delete_async_work
|
||||
_napi_create_string_latin1
|
||||
_napi_is_array
|
||||
_napi_unref_threadsafe_function
|
||||
_napi_throw_error
|
||||
_napi_has_own_property
|
||||
_napi_get_reference_value
|
||||
_napi_remove_env_cleanup_hook
|
||||
_napi_get_value_string_utf8
|
||||
_napi_is_promise
|
||||
_napi_get_boolean
|
||||
_napi_run_script
|
||||
_napi_get_element
|
||||
_napi_get_named_property
|
||||
_napi_get_buffer_info
|
||||
_napi_get_value_bool
|
||||
_napi_reference_ref
|
||||
_napi_create_object
|
||||
_napi_create_promise
|
||||
_napi_create_int32
|
||||
_napi_escape_handle
|
||||
_napi_open_escapable_handle_scope
|
||||
_napi_throw
|
||||
_napi_get_value_double
|
||||
_napi_set_named_property
|
||||
_napi_call_function
|
||||
_napi_create_date
|
||||
_napi_object_freeze
|
||||
_napi_get_uv_event_loop
|
||||
_napi_get_value_string_latin1
|
||||
_napi_reject_deferred
|
||||
_napi_add_finalizer
|
||||
_napi_create_array
|
||||
_napi_delete_reference
|
||||
_napi_get_date_value
|
||||
_napi_create_dataview
|
||||
_napi_get_version
|
||||
_napi_define_class
|
||||
_napi_is_date
|
||||
_napi_remove_wrap
|
||||
_napi_delete_property
|
||||
_napi_instanceof
|
||||
_napi_create_buffer_copy
|
||||
_napi_delete_element
|
||||
_napi_object_seal
|
||||
_napi_queue_async_work
|
||||
_napi_get_value_bigint_words
|
||||
_napi_is_buffer
|
||||
_napi_get_array_length
|
||||
_napi_get_property
|
||||
_napi_new_instance
|
||||
_napi_set_element
|
||||
_napi_create_bigint_words
|
||||
_napi_strict_equals
|
||||
_napi_is_dataview
|
||||
_napi_close_escapable_handle_scope
|
||||
_napi_get_dataview_info
|
||||
_napi_get_value_int32
|
||||
_napi_unwrap
|
||||
_napi_throw_range_error
|
||||
_napi_coerce_to_bool
|
||||
_napi_create_uint32
|
||||
_napi_has_element
|
||||
_napi_create_external_arraybuffer
|
||||
_napi_create_symbol
|
||||
_napi_coerce_to_string
|
||||
_napi_create_type_error
|
||||
_napi_fatal_exception
|
||||
_napi_create_async_work
|
||||
_napi_async_init
|
|
@ -44,10 +44,10 @@ pub fn napi_get_boolean(
|
|||
}
|
||||
```
|
||||
|
||||
Update the Windows `.def` file using the script:
|
||||
Update the generated symbol lists using the script:
|
||||
|
||||
```
|
||||
deno run --allow-write tools/napi/generate_link_win.js
|
||||
deno run --allow-write tools/napi/generate_symbols_lists.js
|
||||
```
|
||||
|
||||
Add a test in [`/test_napi`](../../test_napi/). You can also refer to Node.js
|
||||
|
@ -109,7 +109,7 @@ unsafe extern "C" fn napi_register_module_v1(
|
|||
) -> napi_value {
|
||||
...
|
||||
+ boolean::init(env, exports);
|
||||
|
||||
|
||||
exports
|
||||
}
|
||||
```
|
||||
|
|
|
@ -7,13 +7,13 @@
|
|||
//! Symbols to be exported are now defined in this JSON file.
|
||||
//! The `#[napi_sym]` macro checks for missing entries and panics.
|
||||
//!
|
||||
//! `./tools/napi/generate_link_win.js` is used to generate the LINK `cli/exports.def` on Windows,
|
||||
//! `./tools/napi/generate_symbols_list.js` is used to generate the LINK `cli/exports.def` on Windows,
|
||||
//! which is also checked into git.
|
||||
//!
|
||||
//! To add a new napi function:
|
||||
//! 1. Place `#[napi_sym]` on top of your implementation.
|
||||
//! 2. Add the function's identifier to this JSON list.
|
||||
//! 3. Finally, run `./tools/napi/generate_link_win.js` to update `cli/exports.def`.
|
||||
//! 3. Finally, run `./tools/napi/generate_symbols_list.js` to update `cli/generated_symbol_exports_list_*.def`.
|
||||
|
||||
pub mod r#async;
|
||||
pub mod env;
|
||||
|
|
|
@ -24,11 +24,11 @@ fn napi_get_boolean(
|
|||
|
||||
### `symbol_exports.json`
|
||||
|
||||
A file containing the symbols that need to be put into the exectable's dynamic
|
||||
A file containing the symbols that need to be put into the executable's dynamic
|
||||
symbol table at link-time.
|
||||
|
||||
This is done using `/DEF:` on Windows, `-exported_symbol,_` on macOS and
|
||||
`--export-dynamic-symbol=` on Linux. See [`cli/build.rs`](../build.rs).
|
||||
|
||||
On Windows, you need to generate the `.def` file by running
|
||||
[`tools/napi/generate_link_win.js`](../../tools/napi/generate_link_win.js).
|
||||
[`tools/napi/generate_symbols_lists.js`](../../tools/napi/generate_symbols_lists.js).
|
||||
|
|
|
@ -130,7 +130,7 @@ pub fn init(env: napi_env, exports: napi_value) {
|
|||
unsafe {
|
||||
napi_define_class(
|
||||
env,
|
||||
"NapiObject\0".as_ptr() as *mut i8,
|
||||
"NapiObject\0".as_ptr() as *mut c_char,
|
||||
usize::MAX,
|
||||
Some(NapiObject::new),
|
||||
ptr::null_mut(),
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
#!/usr/bin/env -S deno run --unstable --allow-read --allow-write
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
import exports from "../../cli/napi_sym/symbol_exports.json" assert {
|
||||
type: "json",
|
||||
};
|
||||
|
||||
let def = "LIBRARY\nEXPORTS\n";
|
||||
for (const symbol of exports.symbols) {
|
||||
def += ` ${symbol}\n`;
|
||||
}
|
||||
|
||||
const defUrl = new URL("../../cli/exports.def", import.meta.url);
|
||||
await Deno.writeTextFile(defUrl.pathname, def, { create: true });
|
20
tools/napi/generate_symbols_lists.js
Executable file
20
tools/napi/generate_symbols_lists.js
Executable file
|
@ -0,0 +1,20 @@
|
|||
#!/usr/bin/env -S deno run --unstable --allow-read --allow-write
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
import exports from "../../cli/napi_sym/symbol_exports.json" assert {
|
||||
type: "json",
|
||||
};
|
||||
|
||||
for await (const os of ["linux", "macos", "windows"]) {
|
||||
let def = os === "windows" ? "LIBRARY\nEXPORTS\n" : "";
|
||||
const prefix = os === "windows" ? " " : os === "macos" ? "_" : "";
|
||||
for (const symbol of exports.symbols) {
|
||||
def += `${prefix}${symbol}\n`;
|
||||
}
|
||||
|
||||
const defUrl = new URL(
|
||||
`../../cli/generated_symbol_exports_list_${os}.def`,
|
||||
import.meta.url,
|
||||
);
|
||||
await Deno.writeTextFile(defUrl.pathname, def, { create: true });
|
||||
}
|
Loading…
Reference in a new issue