Skip to content

Commit c769eb9

Browse files
committed
Replace unimplemented! panics with conditional #[link] attribute for WSL/Linux support
The `#[cfg]` structure is verbose and not needed for cross-compilation (where `target_os = "windows"` anyway). Furthermore, the `unimplemented!("Unsupported target OS")` panic prevents using all but the most basic features windows-rs provides on non-Windows systems. Use-cases relying on linking external functions include calling `dxcore` from WSL and `DirectXShaderCompiler` from Linux, both using a COM interface. By removing this `#[cfg]` and `unimplemented!()` panic altogether `windows`, just like `windows-sys`, now unconditionally link using `-lwindows`. This allows crates compiling on non-Windows targets to provide their own fallbacks for needed functions. Any required but missing symbol becomes a linker error rather than a runtime panic. However, such linking may not be desired or complicated to set up, and doesn't prevent the `tool_*` applications (needed to propagate `bindgen` changes in this PR to the final codebase, while working from a Linux environment) through the `metadata` -> `windows-sys` crate from linking against a `-lwindows` library (and failing). For this reason a `cfg_attr` with `windows` predicate has been chosen: `link(name = "windows")` will be enabled on `target_os = "windows"` exclusively. The guard is applied to `windows-sys` which previously didn't have any guarding at all (once again confirming that there's no impact on cross-compiling) to unblock `tool_*` usage on non-Windows systems. Users are able to provide fallbacks on their own within their consumer crate through a simple: #[no_mangle] pub extern "system" fn SysStringLen(..) -> ...; for example, without having to resort to compiling that inside a separate crate that emits a static library or shared object on the search path. This is however still possible, though. There are a few more issues to work out before this crate can _run_ on Linux and WSL, which have to be fleshed out before we can officially (build-)test this use-case in CI.
1 parent 28c2592 commit c769eb9

File tree

3 files changed

+35
-69
lines changed

3 files changed

+35
-69
lines changed

crates/libs/bindgen/src/functions.rs

Lines changed: 32 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ fn gen_win_function(gen: &Gen, def: MethodDef) -> TokenStream {
5050
Some(link) => quote! { #[link(name = #link, kind = "static")] },
5151
None => {
5252
if gen.namespace.starts_with("Windows.") {
53-
quote! { #[link(name = "windows")] }
53+
quote! { #[cfg_attr(windows, link(name = "windows"))] }
5454
} else {
5555
let impl_map = gen.reader.method_def_impl_map(def).expect("ImplMap not found");
5656
let scope = gen.reader.impl_map_scope(impl_map);
@@ -75,17 +75,12 @@ fn gen_win_function(gen: &Gen, def: MethodDef) -> TokenStream {
7575
#features
7676
#[inline]
7777
pub unsafe fn #name<#constraints T: ::windows::core::Interface>(#params) -> ::windows::core::Result<T> {
78-
#[cfg(windows)]
79-
{
80-
#link_attr
81-
extern "system" {
82-
fn #name(#(#abi_params),*) #abi_return_type;
83-
}
84-
let mut result__ = ::core::option::Option::None;
85-
#name(#args).and_some(result__)
78+
#link_attr
79+
extern "system" {
80+
fn #name(#(#abi_params),*) #abi_return_type;
8681
}
87-
#[cfg(not(windows))]
88-
unimplemented!("Unsupported target OS");
82+
let mut result__ = ::core::option::Option::None;
83+
#name(#args).and_some(result__)
8984
}
9085
}
9186
}
@@ -98,16 +93,11 @@ fn gen_win_function(gen: &Gen, def: MethodDef) -> TokenStream {
9893
#features
9994
#[inline]
10095
pub unsafe fn #name<#constraints T: ::windows::core::Interface>(#params result__: *mut ::core::option::Option<T>) -> ::windows::core::Result<()> {
101-
#[cfg(windows)]
102-
{
103-
#link_attr
104-
extern "system" {
105-
fn #name(#(#abi_params),*) #abi_return_type;
106-
}
107-
#name(#args).ok()
96+
#link_attr
97+
extern "system" {
98+
fn #name(#(#abi_params),*) #abi_return_type;
10899
}
109-
#[cfg(not(windows))]
110-
unimplemented!("Unsupported target OS");
100+
#name(#args).ok()
111101
}
112102
}
113103
}
@@ -124,17 +114,12 @@ fn gen_win_function(gen: &Gen, def: MethodDef) -> TokenStream {
124114
#features
125115
#[inline]
126116
pub unsafe fn #name<#constraints>(#params) -> ::windows::core::Result<#return_type_tokens> {
127-
#[cfg(windows)]
128-
{
129-
#link_attr
130-
extern "system" {
131-
fn #name(#(#abi_params),*) #abi_return_type;
132-
}
133-
let mut result__ = ::core::mem::MaybeUninit::<#abi_return_type_tokens>::zeroed();
134-
#name(#args ::core::mem::transmute(result__.as_mut_ptr())).from_abi::<#return_type_tokens>(result__)
117+
#link_attr
118+
extern "system" {
119+
fn #name(#(#abi_params),*) #abi_return_type;
135120
}
136-
#[cfg(not(windows))]
137-
unimplemented!("Unsupported target OS");
121+
let mut result__ = ::core::mem::MaybeUninit::<#abi_return_type_tokens>::zeroed();
122+
#name(#args ::core::mem::transmute(result__.as_mut_ptr())).from_abi::<#return_type_tokens>(result__)
138123
}
139124
}
140125
}
@@ -147,16 +132,11 @@ fn gen_win_function(gen: &Gen, def: MethodDef) -> TokenStream {
147132
#features
148133
#[inline]
149134
pub unsafe fn #name<#constraints>(#params) -> ::windows::core::Result<()> {
150-
#[cfg(windows)]
151-
{
152-
#link_attr
153-
extern "system" {
154-
fn #name(#(#abi_params),*) #abi_return_type;
155-
}
156-
#name(#args).ok()
135+
#link_attr
136+
extern "system" {
137+
fn #name(#(#abi_params),*) #abi_return_type;
157138
}
158-
#[cfg(not(windows))]
159-
unimplemented!("Unsupported target OS");
139+
#name(#args).ok()
160140
}
161141
}
162142
}
@@ -171,17 +151,12 @@ fn gen_win_function(gen: &Gen, def: MethodDef) -> TokenStream {
171151
#features
172152
#[inline]
173153
pub unsafe fn #name<#constraints>(#params) -> ::windows::core::Result<#return_type> {
174-
#[cfg(windows)]
175-
{
176-
#link_attr
177-
extern "system" {
178-
fn #name(#(#abi_params),*) -> #return_type;
179-
}
180-
let result__ = #name(#args);
181-
(!result__.is_invalid()).then(||result__).ok_or_else(::windows::core::Error::from_win32)
154+
#link_attr
155+
extern "system" {
156+
fn #name(#(#abi_params),*) -> #return_type;
182157
}
183-
#[cfg(not(windows))]
184-
unimplemented!("Unsupported target OS");
158+
let result__ = #name(#args);
159+
(!result__.is_invalid()).then(||result__).ok_or_else(::windows::core::Error::from_win32)
185160
}
186161
}
187162
} else {
@@ -193,16 +168,11 @@ fn gen_win_function(gen: &Gen, def: MethodDef) -> TokenStream {
193168
#features
194169
#[inline]
195170
pub unsafe fn #name<#constraints>(#params) #abi_return_type {
196-
#[cfg(windows)]
197-
{
198-
#link_attr
199-
extern "system" {
200-
fn #name(#(#abi_params),*) #abi_return_type;
201-
}
202-
::core::mem::transmute(#name(#args))
171+
#link_attr
172+
extern "system" {
173+
fn #name(#(#abi_params),*) #abi_return_type;
203174
}
204-
#[cfg(not(windows))]
205-
unimplemented!("Unsupported target OS");
175+
::core::mem::transmute(#name(#args))
206176
}
207177
}
208178
}
@@ -217,16 +187,11 @@ fn gen_win_function(gen: &Gen, def: MethodDef) -> TokenStream {
217187
#features
218188
#[inline]
219189
pub unsafe fn #name<#constraints>(#params) #does_not_return {
220-
#[cfg(windows)]
221-
{
222-
#link_attr
223-
extern "system" {
224-
fn #name(#(#abi_params),*) #does_not_return;
225-
}
226-
#name(#args)
190+
#link_attr
191+
extern "system" {
192+
fn #name(#(#abi_params),*) #does_not_return;
227193
}
228-
#[cfg(not(windows))]
229-
unimplemented!("Unsupported target OS");
194+
#name(#args)
230195
}
231196
}
232197
}

crates/libs/bindgen/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ pub fn namespace(gen: &Gen, tree: &Tree) -> String {
8080
if !methods.is_empty() {
8181
let methods = methods.values();
8282
functions = vec![quote! {
83-
#[link(name = "windows")]
83+
#[cfg_attr(windows, link(name = "windows"))]
8484
extern "system" {
8585
#(#methods)*
8686
}

crates/libs/metadata/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ default-target = "x86_64-pc-windows-msvc"
1212
targets = []
1313

1414
[dependencies.windows-sys]
15-
version = "0.36.1"
15+
path = "../sys"
16+
version = "0.38"
1617
features = [
1718
"Win32_System_SystemServices",
1819
"Win32_System_Diagnostics_Debug",

0 commit comments

Comments
 (0)