1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-22 07:14:47 -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:
Luke Channings 2022-10-15 16:21:04 +01:00 committed by GitHub
parent e32719c291
commit fa22956a86
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 350 additions and 61 deletions

10
Cargo.lock generated
View file

@ -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"

View file

@ -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"

View file

@ -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();

View 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

View 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

View file

@ -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
}
```

View file

@ -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;

View file

@ -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).

View file

@ -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(),

View file

@ -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 });

View 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 });
}