feat: Custom attributes for extern fn blocks
chore: allow both wasm_import and raw-dylib
feat: Refactor specific attribute solution to general solution
chore: rustfmt
fix: wasm import module binding order
fix: Use different test attribute
diff --git a/bindgen-tests/tests/expectations/tests/extern-fn-block-attrs-many.rs b/bindgen-tests/tests/expectations/tests/extern-fn-block-attrs-many.rs
new file mode 100644
index 0000000..5aa9e45
--- /dev/null
+++ b/bindgen-tests/tests/expectations/tests/extern-fn-block-attrs-many.rs
@@ -0,0 +1,6 @@
+#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
+#[allow(dead_code)]
+#[cfg_attr(not(windows), link(wasm_import_module = "test-module"))]
+unsafe extern "C" {
+ pub fn test_function();
+}
diff --git a/bindgen-tests/tests/expectations/tests/extern-fn-block-attrs-wasm.rs b/bindgen-tests/tests/expectations/tests/extern-fn-block-attrs-wasm.rs
new file mode 100644
index 0000000..388594b
--- /dev/null
+++ b/bindgen-tests/tests/expectations/tests/extern-fn-block-attrs-wasm.rs
@@ -0,0 +1,6 @@
+#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
+#[link(wasm_import_module = "test-module")]
+#[allow(dead_code)]
+unsafe extern "C" {
+ pub fn test_function();
+}
diff --git a/bindgen-tests/tests/expectations/tests/extern-fn-block-attrs.rs b/bindgen-tests/tests/expectations/tests/extern-fn-block-attrs.rs
new file mode 100644
index 0000000..657cec1
--- /dev/null
+++ b/bindgen-tests/tests/expectations/tests/extern-fn-block-attrs.rs
@@ -0,0 +1,5 @@
+#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
+#[allow(dead_code)]
+unsafe extern "C" {
+ pub fn test_function();
+}
diff --git a/bindgen-tests/tests/headers/extern-fn-block-attrs-many.h b/bindgen-tests/tests/headers/extern-fn-block-attrs-many.h
new file mode 100644
index 0000000..0de6eeb
--- /dev/null
+++ b/bindgen-tests/tests/headers/extern-fn-block-attrs-many.h
@@ -0,0 +1,3 @@
+// bindgen-flags: --extern-fn-block-attrs '#[allow(dead_code)]' --extern-fn-block-attrs '#[cfg_attr(not(windows), link(wasm_import_module = "test-module"))]'
+
+void test_function();
\ No newline at end of file
diff --git a/bindgen-tests/tests/headers/extern-fn-block-attrs-wasm.h b/bindgen-tests/tests/headers/extern-fn-block-attrs-wasm.h
new file mode 100644
index 0000000..2f475f1
--- /dev/null
+++ b/bindgen-tests/tests/headers/extern-fn-block-attrs-wasm.h
@@ -0,0 +1,3 @@
+// bindgen-flags: --extern-fn-block-attrs '#[allow(dead_code)]' --wasm-import-module-name test-module
+
+void test_function();
\ No newline at end of file
diff --git a/bindgen-tests/tests/headers/extern-fn-block-attrs.h b/bindgen-tests/tests/headers/extern-fn-block-attrs.h
new file mode 100644
index 0000000..26480e2
--- /dev/null
+++ b/bindgen-tests/tests/headers/extern-fn-block-attrs.h
@@ -0,0 +1,3 @@
+// bindgen-flags: --extern-fn-block-attrs '#[allow(dead_code)]'
+
+void test_function();
\ No newline at end of file
diff --git a/bindgen/codegen/mod.rs b/bindgen/codegen/mod.rs
index 88a5416..eee4f46 100644
--- a/bindgen/codegen/mod.rs
+++ b/bindgen/codegen/mod.rs
@@ -4665,13 +4665,19 @@
}
}
- // Unfortunately this can't piggyback on the `attributes` list because
- // the #[link(wasm_import_module)] needs to happen before the `extern
- // "C"` block. It doesn't get picked up properly otherwise
- let wasm_link_attribute =
- ctx.options().wasm_import_module_name.as_ref().map(|name| {
- quote! { #[link(wasm_import_module = #name)] }
+ let mut block_attributes = quote! {};
+ for attr in &ctx.options().extern_fn_block_attrs {
+ let parsed_attr = proc_macro2::TokenStream::from_str(attr).unwrap_or_else(
+ |err| {
+ panic!(
+ "Error parsing extern fn block attribute `{attr}`: {err}"
+ )
+ },
+ );
+ block_attributes.extend(quote! {
+ #parsed_attr
});
+ }
let should_wrap = is_internal &&
ctx.options().wrap_static_fns &&
@@ -4725,7 +4731,7 @@
.then(|| quote!(unsafe));
let tokens = quote! {
- #wasm_link_attribute
+ #block_attributes
#safety extern #abi {
#(#attributes)*
pub fn #ident ( #( #args ),* ) #ret;
diff --git a/bindgen/options/cli.rs b/bindgen/options/cli.rs
index 4334e9c..972b487 100644
--- a/bindgen/options/cli.rs
+++ b/bindgen/options/cli.rs
@@ -423,6 +423,9 @@
/// The NAME to be used in a #[link(wasm_import_module = ...)] statement
#[arg(long, value_name = "NAME")]
wasm_import_module_name: Option<String>,
+ /// Attributes to apply to the extern function block.
+ #[arg(long, value_name = "ATTRS")]
+ extern_fn_block_attrs: Vec<String>,
/// Use dynamic loading mode with the given library NAME.
#[arg(long, value_name = "NAME")]
dynamic_loading: Option<String>,
@@ -647,6 +650,7 @@
enable_function_attribute_detection,
use_array_pointers_in_arguments,
wasm_import_module_name,
+ extern_fn_block_attrs,
dynamic_loading,
dynamic_link_require_all,
prefix_link_name,
@@ -907,6 +911,7 @@
time_phases,
use_array_pointers_in_arguments => Builder::array_pointers_in_arguments,
wasm_import_module_name,
+ extern_fn_block_attrs => Builder::extern_fn_block_attrs,
ctypes_prefix,
anon_fields_prefix,
generate => Builder::with_codegen_config,
diff --git a/bindgen/options/mod.rs b/bindgen/options/mod.rs
index edc979e..b9b33a8 100644
--- a/bindgen/options/mod.rs
+++ b/bindgen/options/mod.rs
@@ -1916,6 +1916,25 @@
},
as_args: "--use-array-pointers-in-arguments",
},
+ /// Attributes to add to all `extern` blocks.
+ extern_fn_block_attrs: Vec<String> {
+ methods: {
+ /// Add an attribute to all the `extern` blocks generated by `bindgen`.
+ ///
+ /// This can be used to add attributes such as `#[link(...)]` to all
+ /// the `extern` blocks.
+ pub fn extern_fn_block_attrs<T: Into<String>>(mut self, attr: T) -> Self {
+ self.options.extern_fn_block_attrs.push(attr.into());
+ self
+ }
+ },
+ as_args: |attrs, args| {
+ for attr in attrs {
+ args.push("--extern-fn-block-attrs".to_owned());
+ args.push(attr.clone());
+ }
+ },
+ },
/// The name of the `wasm_import_module`.
wasm_import_module_name: Option<String> {
methods: {
@@ -1927,7 +1946,9 @@
mut self,
import_name: T,
) -> Self {
- self.options.wasm_import_module_name = Some(import_name.into());
+ self.options.extern_fn_block_attrs.push(format!(
+ "#[link(wasm_import_module = \"{}\")]", import_name.into()
+ ));
self
}
},