From 19fea6b12a0509874c5a8ab4a3fbeee471f35164 Mon Sep 17 00:00:00 2001 From: Daniel Henry-Mantilla Date: Tue, 15 Oct 2024 15:08:26 +0200 Subject: [PATCH] Workaround to ensure the `js::ffi_helpers` are properly registered to nodejs (#241) Workaround to ensure the `js::ffi_helpers` are properly registered to nodejs even on release mode under macos --- src/js/ffi_helpers.rs | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/src/js/ffi_helpers.rs b/src/js/ffi_helpers.rs index 78ea8354b4..8bdc93b3b5 100644 --- a/src/js/ffi_helpers.rs +++ b/src/js/ffi_helpers.rs @@ -8,6 +8,43 @@ use ::core::convert::TryFrom; type JsOf = as ReprNapi>::NapiValue; type JsOfCSliceRef = JsOf>; +/// This module can, oddly enough, end up optimized by the linkage step, especially on macOS (on +/// `--[profile ]release`). +/// +/// See: +/// - +/// - +/// +/// The most heavyweight but effective workaround is to add `-C link-dead-code` to the `rustflags`, +/// so that `rustc` not invoke the linker with the `--gc-sections` flag from which these problematic +/// elisions stem. +/// - +/// - Due to worries about the resulting binary size, other venues are explored. +/// +/// The aforementioned `inventory` issue also suggests forcing the `--[profile ]release` to use +/// `codegen-units = 1`. This slows down compilation, and, seems quite brittle, so we keep looking. +/// +/// The comments over suggest another trick: to +/// have a non-`static` item be "exported" / visible "outside" (the crate? This remains unclear, but +/// seems plausible). +/// - +/// +/// Experiments show that this does work, here, but only when adding `#[no_mangle]`/`#[export_name]` +/// (probably just because it ensures the seemingly necessary cross-crate visibility). +/// - (`export_name` is used over `no_mangle` to more easily guarantee unicity of the so-exported +/// symbol, should this approach end up needed elsewhere.) +/// +/// Notable failed attempt: the official proper tool for this task, the `#[used(linker)]` directive, +/// did not help in this case, alas, no matter how much was tweaked the codegen of `#[js_export]`, +/// of `inventory::submit!`, or of custom hard-coded things. +/// - +#[export_name = "_ZN9safer_ffi2js11ffi_helpers42_prevent_improper_linker_dead_code_elisionE"] +pub +fn _prevent_improper_linker_dead_code_elision(unreachable: ::core::convert::Infallible) +{ + match unreachable {} +} + #[js_export(js_name = withCString, __skip_napi_import)] pub fn with_js_string_as_utf8 ( @@ -135,7 +172,7 @@ fn set_deadlock_timeout_js( { let ctx = ::safer_ffi::js::derive::__js_ctx!(); let val: Option = match val.try_into() { - // Maps an input 0 to `None` + // Maps an input 0 to `None` Ok(val) => std::num::NonZeroU32::new(val), Err(_) => Err(Error::new( Status::InvalidArg,