diff --git a/bindgen-tests/tests/expectations/tests/windows-raw-dylib-verbatim.rs b/bindgen-tests/tests/expectations/tests/windows-raw-dylib-verbatim.rs new file mode 100644 index 0000000000..d2247e3523 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/windows-raw-dylib-verbatim.rs @@ -0,0 +1,5 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[cfg_attr(windows, link(name = "foo.exe", kind = "raw-dylib", modifiers = "+verbatim"))] +unsafe extern "C" { + pub fn test_function(); +} diff --git a/bindgen-tests/tests/expectations/tests/windows-raw-dylib.rs b/bindgen-tests/tests/expectations/tests/windows-raw-dylib.rs new file mode 100644 index 0000000000..602d82b053 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/windows-raw-dylib.rs @@ -0,0 +1,5 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[cfg_attr(windows, link(name = "foolib", kind = "raw-dylib"))] +unsafe extern "C" { + pub fn test_function(); +} diff --git a/bindgen-tests/tests/headers/windows-raw-dylib-verbatim.h b/bindgen-tests/tests/headers/windows-raw-dylib-verbatim.h new file mode 100644 index 0000000000..394b275b37 --- /dev/null +++ b/bindgen-tests/tests/headers/windows-raw-dylib-verbatim.h @@ -0,0 +1,3 @@ +// bindgen-flags: --windows-link-as-raw-dylib foo.exe --windows-link-as-raw-dylib-verbatim + +void test_function(); \ No newline at end of file diff --git a/bindgen-tests/tests/headers/windows-raw-dylib.h b/bindgen-tests/tests/headers/windows-raw-dylib.h new file mode 100644 index 0000000000..14c771540c --- /dev/null +++ b/bindgen-tests/tests/headers/windows-raw-dylib.h @@ -0,0 +1,3 @@ +// bindgen-flags: --windows-link-as-raw-dylib foolib + +void test_function(); \ No newline at end of file diff --git a/bindgen/codegen/mod.rs b/bindgen/codegen/mod.rs index 5425962bac..04f278299a 100644 --- a/bindgen/codegen/mod.rs +++ b/bindgen/codegen/mod.rs @@ -4717,10 +4717,24 @@ impl CodeGenerator for Function { // 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 link_attribute = match ( + ctx.options().wasm_import_module_name.as_ref(), + &ctx.options().windows_link_as_raw_dylib, + ) { + (Some(_), (Some(_), _)) => { + panic!("Cannot link against a wasm import module and a raw dylib at the same time"); + } + (Some(name), (None, _)) => { + Some(quote! { #[link(wasm_import_module = #name)] }) + } + (None, (Some(name), false)) => Some( + quote! { #[cfg_attr(windows, link(name = #name, kind = "raw-dylib"))] }, + ), + (None, (Some(name), true)) => Some( + quote! { #[cfg_attr(windows, link(name = #name, kind = "raw-dylib", modifiers = "+verbatim"))] }, + ), + _ => None, + }; let should_wrap = is_internal && ctx.options().wrap_static_fns && @@ -4774,7 +4788,7 @@ impl CodeGenerator for Function { .then(|| quote!(unsafe)); let tokens = quote! { - #wasm_link_attribute + #link_attribute #safety extern #abi { #(#attributes)* pub fn #ident ( #( #args ),* ) #ret; diff --git a/bindgen/options/cli.rs b/bindgen/options/cli.rs index bce7faed35..e2221e1080 100644 --- a/bindgen/options/cli.rs +++ b/bindgen/options/cli.rs @@ -420,6 +420,12 @@ struct BindgenCommand { /// The NAME to be used in a #[link(wasm_import_module = ...)] statement #[arg(long, value_name = "NAME")] wasm_import_module_name: Option, + /// On Windows, link against NAME with kind `raw-dylib`. + #[arg(long, value_name = "NAME")] + windows_link_as_raw_dylib: Option, + /// Do not append `.dll` suffix to the NAME provided to `--windows-link-as-raw-dylib`. + #[arg(long, requires = "windows_link_as_raw_dylib")] + windows_link_as_raw_dylib_verbatim: bool, /// Use dynamic loading mode with the given library NAME. #[arg(long, value_name = "NAME")] dynamic_loading: Option, @@ -643,6 +649,8 @@ where enable_function_attribute_detection, use_array_pointers_in_arguments, wasm_import_module_name, + windows_link_as_raw_dylib, + windows_link_as_raw_dylib_verbatim, dynamic_loading, dynamic_link_require_all, prefix_link_name, @@ -1083,6 +1091,13 @@ where builder = builder.emit_diagnostics(); } + if let Some(windows_link_as_raw_dylib) = windows_link_as_raw_dylib { + builder = builder.windows_link_as_raw_dylib( + windows_link_as_raw_dylib, + windows_link_as_raw_dylib_verbatim, + ); + } + Ok((builder, output, verbose)) } diff --git a/bindgen/options/mod.rs b/bindgen/options/mod.rs index b876b4d5b3..c2c53c4776 100644 --- a/bindgen/options/mod.rs +++ b/bindgen/options/mod.rs @@ -1908,6 +1908,34 @@ options! { }, as_args: "--wasm-import-module-name", }, + /// On Windows, link with kind `raw-dylib` + windows_link_as_raw_dylib: (Option, bool) { + methods: { + /// Adds the `#[cfg_attr(windows, link(name = "", kind = "raw-dylib"))]` attribute to all the `extern` + /// blocks generated by `bindgen`. + /// + /// This attribute is not added by default. + /// + /// If `verbatim` is set to `true`, instead `#[cfg_attr(windows, link(name = "", kind = "raw-dylib", modifiers = "+verbatim"))]` is used. + pub fn windows_link_as_raw_dylib>( + mut self, + dylib: T, + verbatim: bool, + ) -> Self { + self.options.windows_link_as_raw_dylib = (Some(dylib.into()), verbatim); + self + } + }, + as_args: |(dylib, verbatim), args| { + if let Some(dylib) = dylib { + args.push("--windows-link-as-raw-dylib".to_owned()); + args.push(dylib.into()); + if *verbatim { + args.push("--windows-link-as-raw-dylib-verbatim".to_owned()); + } + } + }, + }, /// The name of the dynamic library (if we are generating bindings for a shared library). dynamic_library_name: Option { methods: {