From 7c835e342554daa24b8ab9ee3777d25de29e5af6 Mon Sep 17 00:00:00 2001 From: Jake Shadle Date: Thu, 27 Apr 2023 16:19:43 +0200 Subject: [PATCH] Include nested dependencies in standalone code generation (#2480) --- crates/libs/bindgen/src/standalone.rs | 10 +- crates/libs/core/src/imp/bindings.rs | 4 +- crates/libs/core/src/imp/mod.rs | 2 +- crates/libs/metadata/src/reader/mod.rs | 22 +++ crates/tests/standalone/build.rs | 9 + crates/tests/standalone/src/b_nested.rs | 216 ++++++++++++++++++++++++ 6 files changed, 258 insertions(+), 5 deletions(-) create mode 100644 crates/tests/standalone/src/b_nested.rs diff --git a/crates/libs/bindgen/src/standalone.rs b/crates/libs/bindgen/src/standalone.rs index 5df1a872d6..1c49de09bf 100644 --- a/crates/libs/bindgen/src/standalone.rs +++ b/crates/libs/bindgen/src/standalone.rs @@ -156,7 +156,10 @@ fn standalone_imp(gen: &mut Gen, names: &[&str]) -> String { let name = gen.reader.type_def_name(def); if gen.sys { let ident = to_ident(name); - sorted.insert(name, quote! { type #ident = *mut ::core::ffi::c_void; }); + sorted.insert( + name, + quote! { pub type #ident = *mut ::core::ffi::c_void; }, + ); } else { sorted.insert(name, classes::gen(gen, def)); } @@ -165,7 +168,10 @@ fn standalone_imp(gen: &mut Gen, names: &[&str]) -> String { let name = gen.reader.type_def_name(def); if gen.sys { let ident = to_ident(name); - sorted.insert(name, quote! { type #ident = *mut ::core::ffi::c_void; }); + sorted.insert( + name, + quote! { pub type #ident = *mut ::core::ffi::c_void; }, + ); } else { sorted.insert(name, interfaces::gen(gen, def)); } diff --git a/crates/libs/core/src/imp/bindings.rs b/crates/libs/core/src/imp/bindings.rs index e48cdd7b60..d340263c84 100644 --- a/crates/libs/core/src/imp/bindings.rs +++ b/crates/libs/core/src/imp/bindings.rs @@ -56,8 +56,8 @@ pub type HEAP_FLAGS = u32; pub type HMODULE = isize; pub type HRESULT = i32; pub type HeapHandle = isize; -type IAgileReference = *mut ::core::ffi::c_void; -type IErrorInfo = *mut ::core::ffi::c_void; +pub type IAgileReference = *mut ::core::ffi::c_void; +pub type IErrorInfo = *mut ::core::ffi::c_void; pub type IUnknown = *mut ::core::ffi::c_void; pub const JSCRIPT_E_CANTEXECUTE: HRESULT = -1996357631i32; pub type LOAD_LIBRARY_FLAGS = u32; diff --git a/crates/libs/core/src/imp/mod.rs b/crates/libs/core/src/imp/mod.rs index a91879e531..4c3c77708e 100644 --- a/crates/libs/core/src/imp/mod.rs +++ b/crates/libs/core/src/imp/mod.rs @@ -9,7 +9,7 @@ mod sha1; mod waiter; mod weak_ref_count; -pub use bindings::*; +pub use bindings::{CloseHandle, CoCreateGuid, CoTaskMemAlloc, CoTaskMemFree, CreateEventW, EncodePointer, FormatMessageW, FreeLibrary, GetErrorInfo, GetLastError, GetProcAddress, GetProcessHeap, HeapAlloc, HeapFree, LoadLibraryExA, RoGetAgileReference, SetErrorInfo, SetEvent, SysAllocStringLen, SysFreeString, SysStringLen, WaitForSingleObject, AGILEREFERENCE_DEFAULT, CLASS_E_CLASSNOTAVAILABLE, CO_E_NOTINITIALIZED, ERROR_NO_UNICODE_TRANSLATION, E_BOUNDS, E_NOINTERFACE, E_OUTOFMEMORY, FORMAT_MESSAGE_ALLOCATE_BUFFER, FORMAT_MESSAGE_FROM_SYSTEM, FORMAT_MESSAGE_IGNORE_INSERTS, GUID, HRESULT, JSCRIPT_E_CANTEXECUTE, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS, RPC_E_DISCONNECTED, S_OK}; pub use com_bindings::*; pub use delay_load::*; pub use factory_cache::*; diff --git a/crates/libs/metadata/src/reader/mod.rs b/crates/libs/metadata/src/reader/mod.rs index 93b1e1f658..78f146190b 100644 --- a/crates/libs/metadata/src/reader/mod.rs +++ b/crates/libs/metadata/src/reader/mod.rs @@ -1535,9 +1535,31 @@ impl<'a> Reader<'a> { if self.type_def_kind(*def) == TypeKind::Struct && self.type_def_fields(*def).next().is_none() && self.type_def_guid(*def).is_some() { set.insert(Type::GUID); } + + self.type_collect_standalone_nested(*def, set); + } + } + } + + fn type_collect_standalone_nested(&self, td: TypeDef, set: &mut BTreeSet) { + for nested in self.nested_types(td) { + self.type_collect_standalone_nested(nested, set); + + for field in self.type_def_fields(nested) { + let ty = self.field_type(field, Some(nested)); + if let Type::TypeDef((def, _)) = &ty { + // Skip the fields that actually refer to the anonymous nested + // type, otherwise it will get added to the typeset and emitted + if self.type_def_namespace(*def).is_empty() { + continue; + } + + self.type_collect_standalone(&ty, set); + } } } } + pub fn type_cfg(&self, ty: &Type) -> Cfg { let mut cfg = Cfg::default(); self.type_cfg_combine(ty, &mut cfg); diff --git a/crates/tests/standalone/build.rs b/crates/tests/standalone/build.rs index 8a8b6898ca..7bd9d50e17 100644 --- a/crates/tests/standalone/build.rs +++ b/crates/tests/standalone/build.rs @@ -97,6 +97,15 @@ fn main() { "Windows.Win32.UI.WindowsAndMessaging.wsprintfA", ], ); + + // Ensures nested records write out all the types they depend on + write_sys( + "src/b_nested.rs", + &[ + "Windows.Win32.System.Com.STGMEDIUM", + "Windows.Win32.Graphics.Gdi.DEVMODEW", + ], + ); } fn write_sys(filename: &str, apis: &[&str]) { diff --git a/crates/tests/standalone/src/b_nested.rs b/crates/tests/standalone/src/b_nested.rs new file mode 100644 index 0000000000..ab55fe6d01 --- /dev/null +++ b/crates/tests/standalone/src/b_nested.rs @@ -0,0 +1,216 @@ +// Bindings generated by `windows-bindgen` 0.49.0 + +#![allow( + non_snake_case, + non_upper_case_globals, + non_camel_case_types, + dead_code, + clippy::all +)] +#[repr(C)] +pub struct DEVMODEW { + pub dmDeviceName: [u16; 32], + pub dmSpecVersion: u16, + pub dmDriverVersion: u16, + pub dmSize: u16, + pub dmDriverExtra: u16, + pub dmFields: DEVMODE_FIELD_FLAGS, + pub Anonymous1: DEVMODEW_0, + pub dmColor: DEVMODE_COLOR, + pub dmDuplex: DEVMODE_DUPLEX, + pub dmYResolution: i16, + pub dmTTOption: DEVMODE_TRUETYPE_OPTION, + pub dmCollate: DEVMODE_COLLATE, + pub dmFormName: [u16; 32], + pub dmLogPixels: u16, + pub dmBitsPerPel: u32, + pub dmPelsWidth: u32, + pub dmPelsHeight: u32, + pub Anonymous2: DEVMODEW_1, + pub dmDisplayFrequency: u32, + pub dmICMMethod: u32, + pub dmICMIntent: u32, + pub dmMediaType: u32, + pub dmDitherType: u32, + pub dmReserved1: u32, + pub dmReserved2: u32, + pub dmPanningWidth: u32, + pub dmPanningHeight: u32, +} +impl ::core::marker::Copy for DEVMODEW {} +impl ::core::clone::Clone for DEVMODEW { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +pub union DEVMODEW_0 { + pub Anonymous1: DEVMODEW_0_0, + pub Anonymous2: DEVMODEW_0_1, +} +impl ::core::marker::Copy for DEVMODEW_0 {} +impl ::core::clone::Clone for DEVMODEW_0 { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +pub struct DEVMODEW_0_0 { + pub dmOrientation: i16, + pub dmPaperSize: i16, + pub dmPaperLength: i16, + pub dmPaperWidth: i16, + pub dmScale: i16, + pub dmCopies: i16, + pub dmDefaultSource: i16, + pub dmPrintQuality: i16, +} +impl ::core::marker::Copy for DEVMODEW_0_0 {} +impl ::core::clone::Clone for DEVMODEW_0_0 { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +pub struct DEVMODEW_0_1 { + pub dmPosition: POINTL, + pub dmDisplayOrientation: DEVMODE_DISPLAY_ORIENTATION, + pub dmDisplayFixedOutput: DEVMODE_DISPLAY_FIXED_OUTPUT, +} +impl ::core::marker::Copy for DEVMODEW_0_1 {} +impl ::core::clone::Clone for DEVMODEW_0_1 { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +pub union DEVMODEW_1 { + pub dmDisplayFlags: u32, + pub dmNup: u32, +} +impl ::core::marker::Copy for DEVMODEW_1 {} +impl ::core::clone::Clone for DEVMODEW_1 { + fn clone(&self) -> Self { + *self + } +} +pub type DEVMODE_COLLATE = u16; +pub type DEVMODE_COLOR = u16; +pub type DEVMODE_DISPLAY_FIXED_OUTPUT = u32; +pub type DEVMODE_DISPLAY_ORIENTATION = u32; +pub type DEVMODE_DUPLEX = u16; +pub type DEVMODE_FIELD_FLAGS = u32; +pub type DEVMODE_TRUETYPE_OPTION = u16; +#[repr(C)] +pub struct FILETIME { + pub dwLowDateTime: u32, + pub dwHighDateTime: u32, +} +impl ::core::marker::Copy for FILETIME {} +impl ::core::clone::Clone for FILETIME { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +#[derive( + ::core::marker::Copy, + ::core::clone::Clone, + ::core::default::Default, + ::core::cmp::PartialEq, + ::core::cmp::Eq, + ::core::hash::Hash, +)] +pub struct GUID { + pub data1: u32, + pub data2: u16, + pub data3: u16, + pub data4: [u8; 8], +} +impl GUID { + pub const fn from_u128(uuid: u128) -> Self { + Self { + data1: (uuid >> 96) as u32, + data2: (uuid >> 80 & 0xffff) as u16, + data3: (uuid >> 64 & 0xffff) as u16, + data4: (uuid as u64).to_be_bytes(), + } + } +} +pub type HBITMAP = isize; +pub type HENHMETAFILE = isize; +pub type HGLOBAL = isize; +pub type HRESULT = i32; +pub type IEnumSTATSTG = *mut ::core::ffi::c_void; +pub type ISequentialStream = *mut ::core::ffi::c_void; +pub type IStorage = *mut ::core::ffi::c_void; +pub type IStream = *mut ::core::ffi::c_void; +pub type IUnknown = *mut ::core::ffi::c_void; +pub type LOCKTYPE = i32; +pub type PCWSTR = *const u16; +#[repr(C)] +pub struct POINTL { + pub x: i32, + pub y: i32, +} +impl ::core::marker::Copy for POINTL {} +impl ::core::clone::Clone for POINTL { + fn clone(&self) -> Self { + *self + } +} +pub type PWSTR = *mut u16; +pub type STATFLAG = i32; +#[repr(C)] +pub struct STATSTG { + pub pwcsName: PWSTR, + pub r#type: u32, + pub cbSize: u64, + pub mtime: FILETIME, + pub ctime: FILETIME, + pub atime: FILETIME, + pub grfMode: STGM, + pub grfLocksSupported: LOCKTYPE, + pub clsid: GUID, + pub grfStateBits: u32, + pub reserved: u32, +} +impl ::core::marker::Copy for STATSTG {} +impl ::core::clone::Clone for STATSTG { + fn clone(&self) -> Self { + *self + } +} +pub type STGC = i32; +pub type STGM = u32; +#[repr(C)] +pub struct STGMEDIUM { + pub tymed: TYMED, + pub u: STGMEDIUM_0, + pub pUnkForRelease: IUnknown, +} +impl ::core::marker::Copy for STGMEDIUM {} +impl ::core::clone::Clone for STGMEDIUM { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +pub union STGMEDIUM_0 { + pub hBitmap: HBITMAP, + pub hMetaFilePict: *mut ::core::ffi::c_void, + pub hEnhMetaFile: HENHMETAFILE, + pub hGlobal: HGLOBAL, + pub lpszFileName: PWSTR, + pub pstm: IStream, + pub pstg: IStorage, +} +impl ::core::marker::Copy for STGMEDIUM_0 {} +impl ::core::clone::Clone for STGMEDIUM_0 { + fn clone(&self) -> Self { + *self + } +} +pub type STGMOVE = i32; +pub type STREAM_SEEK = u32; +pub type TYMED = i32;