Skip to content

Commit

Permalink
The build macro redirects to pre-packaged Windows APIs (#1338)
Browse files Browse the repository at this point in the history
  • Loading branch information
kennykerr committed Nov 17, 2021
1 parent 3ba8e57 commit 3866b6d
Show file tree
Hide file tree
Showing 42 changed files with 137 additions and 53 deletions.
52 changes: 51 additions & 1 deletion crates/deps/gen/src/build.rs
@@ -1,7 +1,15 @@
use super::*;

pub fn gen_build() -> TokenStream {
let tokens = RawString(gen_source_tree().into_string());
gen_build_redirect(true)
}

pub fn gen_build_legacy() -> TokenStream {
gen_build_redirect(false)
}

pub fn gen_build_redirect(redirect: bool) -> TokenStream {
let tokens = RawString(gen_source_tree(redirect).into_string());
let target_dir = RawString(target_dir());
let workspace_dir = RawString(workspace_dir());

Expand Down Expand Up @@ -94,3 +102,45 @@ impl ToTokens for RawString {
tokens.push_str("\"#");
}
}

fn gen_source_tree(redirect: bool) -> TokenStream {
let reader = TypeReader::get();

namespace_iter(&reader.types, redirect).fold(TokenStream::with_capacity(), |mut accum, n| {
accum.combine(&n);
accum
})
}

fn namespace_iter(tree: &TypeTree, redirect: bool) -> impl Iterator<Item = TokenStream> + '_ {
let gen = Gen::build(tree.namespace, redirect);

tree.types.iter().map(move |t| gen_type_entry(t.1, &gen)).chain(gen_namespaces(&tree.namespaces, redirect))
}

fn gen_namespaces<'a>(namespaces: &'a BTreeMap<&'static str, TypeTree>, redirect: bool) -> impl Iterator<Item = TokenStream> + 'a {
namespaces.iter().map(move |(name, tree)| {
if tree.include && (!redirect || redirect && !tree.namespace.starts_with("Windows.") && tree.namespace != "Windows") {
// TODO: https://github.com/microsoft/windows-rs/issues/212
// TODO: https://github.com/microsoft/win32metadata/issues/380

let allow = if name == &tree.namespace {
quote! { #[allow(unused_variables, non_upper_case_globals, non_snake_case, unused_unsafe, non_camel_case_types, dead_code, clippy::all)] }
} else {
quote! {}
};

let name = to_ident(name);
let tokens = namespace_iter(tree, redirect);

quote! {
#allow
pub mod #name {
#(#tokens)*
}
}
} else {
TokenStream::new()
}
})
}
27 changes: 20 additions & 7 deletions crates/deps/gen/src/gen.rs
Expand Up @@ -5,15 +5,26 @@ pub struct Gen {
pub root: &'static str,
pub ignore_windows_features: bool,
pub docs: bool,
pub build: bool,
}

impl Gen {
pub fn absolute() -> Self {
Gen { relative: "", root: "", ignore_windows_features: false, docs: false }
Gen { relative: "", root: "", ignore_windows_features: false, docs: false, build: false }
}

pub fn relative(namespace: &'static str) -> Self {
Gen { relative: namespace, root: "", ignore_windows_features: false, docs: false }
Gen { relative: namespace, root: "", ignore_windows_features: false, docs: false, build: false }
}

pub fn build(namespace: &'static str, redirect: bool) -> Self {
Gen {
relative: namespace,
root: "",
ignore_windows_features: false,
docs: false,
build: redirect,
}
}

pub fn namespace(&self, namespace: &str) -> TokenStream {
Expand All @@ -31,7 +42,7 @@ impl Gen {
return TokenStream::new();
}

if !self.root.is_empty() && self.root != "Windows" && namespace.starts_with("Windows.") {
if (self.build || (!self.root.is_empty() && self.root != "Windows")) && namespace.starts_with("Windows.") {
let mut tokens: TokenStream = "::windows::".into();

for namespace in namespace.split('.').skip(1) {
Expand Down Expand Up @@ -236,13 +247,14 @@ mod tests {
fn test_features() {
let mut features = BTreeSet::new();
features.insert("Windows.Foundation");
assert_eq!(Gen { root: "Microsoft", relative: "", ignore_windows_features: false, docs: false }.gen_cfg(&features).as_str(), r#"#[cfg(feature = "Windows_Foundation")]"#);
assert_eq!(Gen { root: "Microsoft", relative: "", ignore_windows_features: false, docs: false, build: false }.gen_cfg(&features).as_str(), r#"#[cfg(feature = "Windows_Foundation")]"#);
assert_eq!(
Gen {
root: "Microsoft",
relative: "Microsoft.UI.Composition.Diagnostics",
ignore_windows_features: false,
docs: true
docs: true,
build: false,
}
.gen_cfg_doc(&features)
.as_str(),
Expand All @@ -251,13 +263,14 @@ mod tests {

let mut features = BTreeSet::new();
features.insert("Microsoft.Foundation");
assert_eq!(Gen { root: "Microsoft", relative: "", ignore_windows_features: false, docs: false }.gen_cfg(&features).as_str(), r#"#[cfg(feature = "Foundation")]"#);
assert_eq!(Gen { root: "Microsoft", relative: "", ignore_windows_features: false, docs: false, build: false }.gen_cfg(&features).as_str(), r#"#[cfg(feature = "Foundation")]"#);
assert_eq!(
Gen {
root: "Microsoft",
relative: "Microsoft.UI.Composition.Diagnostics",
ignore_windows_features: false,
docs: true
docs: true,
build: false,
}
.gen_cfg_doc(&features)
.as_str(),
Expand Down
6 changes: 3 additions & 3 deletions crates/deps/gen/src/tree.rs
@@ -1,7 +1,7 @@
use super::*;

pub fn gen_sys_file(root: &'static str, tree: &TypeTree, ignore_windows_features: bool) -> TokenStream {
let gen = Gen { relative: tree.namespace, root, ignore_windows_features, docs: false };
let gen = Gen { relative: tree.namespace, root, ignore_windows_features, docs: false, build: false };
let types = gen_sys(tree, &gen);

let namespaces = tree.namespaces.iter().filter_map(move |(name, tree)| {
Expand All @@ -24,7 +24,7 @@ pub fn gen_sys_file(root: &'static str, tree: &TypeTree, ignore_windows_features
}

pub fn gen_source_file(root: &'static str, tree: &TypeTree, ignore_windows_features: bool) -> TokenStream {
let gen = Gen { relative: tree.namespace, root, ignore_windows_features, docs: false };
let gen = Gen { relative: tree.namespace, root, ignore_windows_features, docs: false, build: false };

let types = tree.types.values().map(move |t| gen_type_entry(t, &gen));

Expand Down Expand Up @@ -89,7 +89,7 @@ fn gen_namespaces<'a>(namespaces: &'a BTreeMap<&'static str, TypeTree>) -> impl
})
}

fn gen_type_entry(entry: &TypeEntry, gen: &Gen) -> TokenStream {
pub fn gen_type_entry(entry: &TypeEntry, gen: &Gen) -> TokenStream {
if entry.include == TypeInclude::None {
return TokenStream::new();
}
Expand Down
7 changes: 7 additions & 0 deletions crates/deps/macros/src/lib.rs
Expand Up @@ -38,6 +38,13 @@ pub fn build(stream: proc_macro::TokenStream) -> proc_macro::TokenStream {
gen_build().as_str().parse().unwrap()
}

#[doc(hidden)]
#[proc_macro]
pub fn build_legacy(stream: proc_macro::TokenStream) -> proc_macro::TokenStream {
parse_macro_input!(stream as BuildMacro);
gen_build_legacy().as_str().parse().unwrap()
}

/// A macro for generating Windows API bindings ahead of time.
#[proc_macro]
pub fn generate(stream: proc_macro::TokenStream) -> proc_macro::TokenStream {
Expand Down
2 changes: 1 addition & 1 deletion crates/tests/legacy/alternate_success_code/build.rs
@@ -1,3 +1,3 @@
fn main() {
windows::core::build! {Windows::Win32::Foundation::CO_E_NOTINITIALIZED, Windows::Win32::System::Ole::DoDragDrop};
windows::core::build_legacy! {Windows::Win32::Foundation::CO_E_NOTINITIALIZED, Windows::Win32::System::Ole::DoDragDrop};
}
2 changes: 1 addition & 1 deletion crates/tests/legacy/build_groups/build.rs
@@ -1,5 +1,5 @@
fn main() {
windows::core::build! {
windows::core::build_legacy! {
Windows::Foundation::{
Collections::{IMap, IVector},
IStringable,
Expand Down
2 changes: 1 addition & 1 deletion crates/tests/legacy/build_wildcard/build.rs
@@ -1,5 +1,5 @@
fn main() {
windows::core::build! {
windows::core::build_legacy! {
Windows::Foundation::*,
};
}
2 changes: 1 addition & 1 deletion crates/tests/legacy/convertible/build.rs
@@ -1,7 +1,7 @@
fn main() {
// GetProcessHeap returns HeapHandle. So including GetProcessHeap
// should also include HeapHandle.
windows::core::build! {
windows::core::build_legacy! {
Windows::Win32::System::Memory::GetProcessHeap,
};
// Note: don't add anything else to this build macro!
Expand Down
2 changes: 1 addition & 1 deletion crates/tests/legacy/data_object/build.rs
@@ -1,5 +1,5 @@
fn main() {
windows::core::build! {
windows::core::build_legacy! {
Windows::Win32::System::Com::IDataObject,
};
}
2 changes: 1 addition & 1 deletion crates/tests/legacy/deprecated/build.rs
@@ -1,5 +1,5 @@
fn main() {
windows::core::build! {
windows::core::build_legacy! {
Windows::ApplicationModel::Contacts::KnownContactField,
};
}
2 changes: 1 addition & 1 deletion crates/tests/legacy/helpers/build.rs
@@ -1,5 +1,5 @@
fn main() {
windows::core::build! {
windows::core::build_legacy! {
Windows::Win32::Globalization::{SetThreadPreferredUILanguages, MUI_LANGUAGE_NAME},
};
}
2 changes: 1 addition & 1 deletion crates/tests/legacy/implement/build.rs
@@ -1,5 +1,5 @@
fn main() {
windows::core::build! {
windows::core::build_legacy! {
Windows::Foundation::Collections::{IIterable, IVectorView},
Windows::Foundation::{IClosable, IStringable, Uri},
Windows::Storage::Streams::Buffer,
Expand Down
2 changes: 1 addition & 1 deletion crates/tests/legacy/implement_null_result/build.rs
@@ -1,3 +1,3 @@
fn main() {
windows::core::build! {Windows::Win32::Foundation::S_OK, Windows::UI::Xaml::Markup::IXamlType2};
windows::core::build_legacy! {Windows::Win32::Foundation::S_OK, Windows::UI::Xaml::Markup::IXamlType2};
}
2 changes: 1 addition & 1 deletion crates/tests/legacy/interfaces/build.rs
@@ -1,5 +1,5 @@
fn main() {
windows::core::build! {
windows::core::build_legacy! {
// Test for https://github.com/microsoft/windows-rs/issues/1055
Windows::Win32::Data::Xml::MsXml::IMXWriter,

Expand Down
2 changes: 1 addition & 1 deletion crates/tests/legacy/interop/build.rs
@@ -1,3 +1,3 @@
fn main() {
windows::core::build! {Windows::Foundation::Collections::StringMap, Windows::Win32::System::Com::CoInitializeEx, Windows::Win32::System::WinRT::RoActivateInstance, Windows::Win32::UI::Input::Radial::IRadialControllerInterop};
windows::core::build_legacy! {Windows::Foundation::Collections::StringMap, Windows::Win32::System::Com::CoInitializeEx, Windows::Win32::System::WinRT::RoActivateInstance, Windows::Win32::UI::Input::Radial::IRadialControllerInterop};
}
2 changes: 1 addition & 1 deletion crates/tests/legacy/matrix3x2/build.rs
@@ -1,7 +1,7 @@
fn main() {
// The Windows crate manually injects a functions needed to implement Matrix3x2.
// This test validates this is included.
windows::core::build! {
windows::core::build_legacy! {
Windows::Foundation::Numerics::Matrix3x2,
};
}
2 changes: 1 addition & 1 deletion crates/tests/legacy/ntstatus/build.rs
@@ -1,5 +1,5 @@
fn main() {
windows::core::build! {
windows::core::build_legacy! {
Windows::Win32::Foundation::{STATUS_INVALID_SIGNATURE, STATUS_NOT_FOUND, STATUS_SUCCESS},
Windows::Win32::Security::Cryptography::{BCryptGenRandom, BCryptOpenAlgorithmProvider},
};
Expand Down
2 changes: 1 addition & 1 deletion crates/tests/legacy/pwstr/build.rs
@@ -1,5 +1,5 @@
fn main() {
windows::core::build! {
windows::core::build_legacy! {
Windows::Win32::Foundation::PWSTR
}
}
2 changes: 1 addition & 1 deletion crates/tests/legacy/return_com_interface/build.rs
@@ -1,5 +1,5 @@
fn main() {
windows::core::build! {
windows::core::build_legacy! {
Windows::Win32::Graphics::Direct3D12::ID3D12FunctionReflection,
};
}
2 changes: 1 addition & 1 deletion crates/tests/legacy/return_struct/build.rs
@@ -1,5 +1,5 @@
fn main() {
windows::core::build! {
windows::core::build_legacy! {
// Tests for SignatureKind::ReturnStruct

// This free function returns a struct
Expand Down
2 changes: 1 addition & 1 deletion crates/tests/legacy/structs/build.rs
@@ -1,5 +1,5 @@
fn main() {
windows::core::build! {
windows::core::build_legacy! {
// Test to verify property key constants are generated
// https://github.com/microsoft/win32metadata/issues/339
Windows::Win32::Devices::Properties::DEVPKEY_Device_BiosDeviceName,
Expand Down
2 changes: 1 addition & 1 deletion crates/tests/legacy/unions/build.rs
@@ -1,3 +1,3 @@
fn main() {
windows::core::build! {Windows::Win32::Graphics::Direct3D12::D3D12_INDIRECT_ARGUMENT_DESC, Windows::Win32::System::IO::OVERLAPPED};
windows::core::build_legacy! {Windows::Win32::Graphics::Direct3D12::D3D12_INDIRECT_ARGUMENT_DESC, Windows::Win32::System::IO::OVERLAPPED};
}
2 changes: 1 addition & 1 deletion crates/tests/legacy/win32/build.rs
@@ -1,5 +1,5 @@
fn main() {
windows::core::build! {
windows::core::build_legacy! {
Windows::Win32::Foundation::{CloseHandle, GetLastError, BSTR, RECT, WIN32_ERROR},
Windows::Win32::Gaming::HasExpandedResources,
Windows::Win32::Graphics::Direct2D::CLSID_D2D1Shadow,
Expand Down
2 changes: 1 addition & 1 deletion crates/tests/legacy/win32_arrays/build.rs
@@ -1,3 +1,3 @@
fn main() {
windows::core::build! {Windows::Win32::Graphics::Dxgi::DXGI_ADAPTER_DESC1, Windows::Win32::NetworkManagement::IpHelper::IPV6_ADDRESS_EX, Windows::Win32::System::Diagnostics::Debug::MINIDUMP_MEMORY_LIST, Windows::Win32::UI::WindowsAndMessaging::NCCALCSIZE_PARAMS};
windows::core::build_legacy! {Windows::Win32::Graphics::Dxgi::DXGI_ADAPTER_DESC1, Windows::Win32::NetworkManagement::IpHelper::IPV6_ADDRESS_EX, Windows::Win32::System::Diagnostics::Debug::MINIDUMP_MEMORY_LIST, Windows::Win32::UI::WindowsAndMessaging::NCCALCSIZE_PARAMS};
}
2 changes: 1 addition & 1 deletion crates/tests/legacy/winrt/build.rs
@@ -1,5 +1,5 @@
fn main() {
windows::core::build! {
windows::core::build_legacy! {
Windows::ApplicationModel::Activation::{BackgroundActivatedEventArgs, CachedFileUpdaterActivatedEventArgs, FileActivatedEventArgs, FileOpenPickerActivatedEventArgs, FileSavePickerActivatedEventArgs, IActivatedEventArgs, LaunchActivatedEventArgs, SearchActivatedEventArgs, ShareTargetActivatedEventArgs},
Windows::ApplicationModel::Appointments::AppointmentDaysOfWeek,
// Test for https://github.com/microsoft/windows-rs/issues/280
Expand Down
2 changes: 1 addition & 1 deletion crates/tests/win32/arch/build.rs
Expand Up @@ -2,7 +2,7 @@ fn main() {
// This struct presents unique challenges to the type reader as it is both arch-specific
// and one of those definitions has nested types. This combination is tricky because
// traditional scope resolution is insufficient.
windows::core::build! {
windows::core::build_legacy! {
Windows::Win32::System::Diagnostics::Debug::KNONVOLATILE_CONTEXT_POINTERS,
};
}
2 changes: 1 addition & 1 deletion crates/tests/win32/bstr/build.rs
@@ -1,7 +1,7 @@
fn main() {
// The Windows crate manually injects various functions needed to implement BSTR.
// This test validates these are included.
windows::core::build! {
windows::core::build_legacy! {
Windows::Win32::Foundation::BSTR,
};
}
2 changes: 1 addition & 1 deletion crates/tests/win32/class_factory/build.rs
@@ -1,5 +1,5 @@
fn main() {
windows::core::build!(
windows::core::build_legacy!(
Windows::Foundation::{IClosable, IStringable},
Windows::Win32::System::Com::IClassFactory
);
Expand Down
2 changes: 1 addition & 1 deletion crates/tests/win32/lib/build.rs
@@ -1,5 +1,5 @@
fn main() {
windows::core::build! {
windows::core::build_legacy! {
Windows::Win32::Graphics::Direct3D::Fxc::D3DCreateLinker,
};
}
2 changes: 1 addition & 1 deletion crates/tests/win32/query/build.rs
@@ -1,3 +1,3 @@
fn main() {
windows::core::build! {Component::Win32::Query::*, Windows::Win32::Foundation::E_NOINTERFACE};
windows::core::build_legacy! {Component::Win32::Query::*, Windows::Win32::Foundation::E_NOINTERFACE};
}
2 changes: 1 addition & 1 deletion crates/tests/win32/return/build.rs
@@ -1,5 +1,5 @@
fn main() {
windows::core::build! {
windows::core::build_legacy! {
Component::Win32::Return::*,
Windows::Win32::Foundation::{E_APPLICATION_EXITING, STATUS_NOT_FOUND, STATUS_SUCCESS, S_OK},
};
Expand Down
8 changes: 6 additions & 2 deletions crates/tests/winrt/async/Cargo.toml
Expand Up @@ -4,8 +4,12 @@ version = "0.0.0"
authors = ["Microsoft"]
edition = "2018"

[dependencies]
windows = { path = "../../../.." }
[dependencies.windows]
path = "../../../.."
features = [
"std",
"Foundation",
]

[build-dependencies]
windows = { path = "../../../..", features = ["build"] }
Expand Down
9 changes: 7 additions & 2 deletions crates/tests/winrt/collections/Cargo.toml
Expand Up @@ -4,8 +4,13 @@ version = "0.0.0"
authors = ["Microsoft"]
edition = "2018"

[dependencies]
windows = { path = "../../../.." }
[dependencies.windows]
path = "../../../.."
features = [
"std",
"alloc",
"Foundation_Collections",
]

[build-dependencies]
windows = { path = "../../../..", features = ["build"] }

0 comments on commit 3866b6d

Please sign in to comment.