Skip to content

Commit 81e8abb

Browse files
committed
Find winmd files without reading PATH nor copying to target/
Non-Windows platforms - which are supported for cross-compiling - do not set the output directory in `PATH` nor use semicolons to separate this variable, resulting in errors. Replace it with the old `include_bytes!` logic that does not require paths at runtime (of the macro) at all. Copying of DLL targets to the `target/<profile>` dir for easy consumption and running of crates is still performed.
1 parent 1dd9a40 commit 81e8abb

File tree

3 files changed

+36
-99
lines changed

3 files changed

+36
-99
lines changed

crates/gen/build.rs

Lines changed: 0 additions & 36 deletions
This file was deleted.

crates/gen/src/workspace.rs

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ fn get_crate_winmds() -> Vec<File> {
8080
if let Ok(file_type) = file.file_type() {
8181
if file_type.is_file() {
8282
let path = file.path();
83-
if let Some("winmd") =
84-
path.extension().and_then(|extension| extension.to_str())
83+
if path.extension().and_then(|extension| extension.to_str())
84+
== Some("winmd")
8585
{
8686
result.push(File::new(path));
8787
}
@@ -93,26 +93,27 @@ fn get_crate_winmds() -> Vec<File> {
9393

9494
let mut result = vec![];
9595

96+
// Manifest directory of the crate calling `build!`
9697
if let Ok(dir) = std::env::var("CARGO_MANIFEST_DIR") {
97-
let mut dir: std::path::PathBuf = dir.into();
98-
dir.push(".windows");
99-
dir.push("winmd");
100-
push_dir(&mut result, &dir);
98+
push_dir(
99+
&mut result,
100+
&std::path::Path::new(&dir).join(".windows/winmd"),
101+
);
101102
}
102103

103-
let dir = std::env::var("PATH").expect("No `PATH` env variable set");
104-
let end = dir.find(';').expect("Path not ending in `;`");
105-
let mut dir: std::path::PathBuf = dir[..end].into();
106-
dir.pop();
107-
dir.pop();
108-
dir.push(".windows");
109-
dir.push("winmd");
110-
push_dir(&mut result, &dir);
111-
112-
let mut dir: std::path::PathBuf = target_dir().into();
113-
dir.push(".windows");
114-
dir.push("winmd");
115-
push_dir(&mut result, &dir);
104+
// Default manifests provided by windows_gen
105+
// TODO: include_bytes is very slow - it takes an extra 60ms compared with memory mapped files.
106+
// https://github.com/rust-lang/rust/issues/65818
107+
if !result.iter().any(|file| file.name.starts_with("Windows.")) {
108+
result.push(File::from_bytes(
109+
"Windows.Win32.winmd".to_string(),
110+
include_bytes!("../.windows/winmd/Windows.Win32.winmd").to_vec(),
111+
));
112+
result.push(File::from_bytes(
113+
"Windows.WinRT.winmd".to_string(),
114+
include_bytes!("../.windows/winmd/Windows.WinRT.winmd").to_vec(),
115+
));
116+
}
116117

117118
result
118119
}

crates/macros/src/lib.rs

Lines changed: 16 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,6 @@ impl ToTokens for RawString {
4444
pub fn build(stream: proc_macro::TokenStream) -> proc_macro::TokenStream {
4545
let build = parse_macro_input!(stream as BuildMacro);
4646
let tokens = RawString(build.to_tokens_string());
47-
let target_dir = std::env::var("PATH").expect("No `PATH` env variable set");
48-
let end = target_dir.find(';').expect("Path not ending in `;`");
49-
let target_dir = RawString(target_dir[..end].to_string());
5047

5148
let tokens = quote! {
5249
{
@@ -59,6 +56,8 @@ pub fn build(stream: proc_macro::TokenStream) -> proc_macro::TokenStream {
5956
);
6057

6158
path.push("windows.rs");
59+
println!("cargo:rerun-if-changed={}", path.to_str().expect("`OUT_DIR` not a UTF-8 string"));
60+
6261
::std::fs::write(&path, #tokens).expect("Could not write generated code to windows.rs");
6362

6463
let mut cmd = ::std::process::Command::new("rustfmt");
@@ -68,49 +67,27 @@ pub fn build(stream: proc_macro::TokenStream) -> proc_macro::TokenStream {
6867
fn copy(source: &::std::path::Path, destination: &mut ::std::path::PathBuf) {
6968
if let ::std::result::Result::Ok(entries) = ::std::fs::read_dir(source) {
7069
for entry in entries.filter_map(|entry| entry.ok()) {
71-
if let ::std::result::Result::Ok(entry_type) = entry.file_type() {
72-
let path = entry.path();
73-
if let ::std::option::Option::Some(last_path_component) = path.file_name() {
74-
let _ = ::std::fs::create_dir_all(&destination);
75-
destination.push(last_path_component);
76-
if entry_type.is_file() {
77-
let _ = ::std::fs::copy(path, &destination);
78-
} else if entry_type.is_dir() {
79-
let _ = ::std::fs::create_dir(&destination);
80-
copy(&path, destination);
81-
}
82-
destination.pop();
83-
}
84-
}
85-
}
86-
}
87-
}
88-
89-
fn copy_to_profile(source: &::std::path::Path, destination: &::std::path::Path, profile: &str) {
90-
if let ::std::result::Result::Ok(files) = ::std::fs::read_dir(destination) {
91-
for file in files.filter_map(|file| file.ok()) {
92-
if let ::std::result::Result::Ok(file_type) = file.file_type() {
93-
if file_type.is_dir() {
94-
let mut path = file.path();
95-
if let ::std::option::Option::Some(filename) = path.file_name() {
96-
if filename == profile {
97-
copy(source, &mut path);
98-
} else {
99-
copy_to_profile(source, &path, profile);
100-
}
101-
}
70+
let path = entry.path();
71+
if let ::std::option::Option::Some(last_path_component) = path.file_name() {
72+
let _ = ::std::fs::create_dir_all(&destination);
73+
destination.push(last_path_component);
74+
if path.is_file() {
75+
let _ = ::std::fs::copy(path, &destination);
76+
} else if path.is_dir() {
77+
let _ = ::std::fs::create_dir(&destination);
78+
copy(&path, destination);
10279
}
80+
destination.pop();
10381
}
10482
}
10583
}
10684
}
10785

10886
let mut source : ::std::path::PathBuf = ::std::env::var("CARGO_MANIFEST_DIR").expect("No `CARGO_MANIFEST_DIR` env variable set").into();
10987
source.push(".windows");
88+
println!("cargo:rerun-if-changed={}", source.to_str().expect("`CARGO_MANIFEST_DIR` not a UTF-8 string"));
11089

11190
if source.exists() {
112-
println!("cargo:rerun-if-changed={}", source.to_str().expect("`CARGO_MANIFEST_DIR` not a valid path"));
113-
11491
// The `target_arch` cfg is not set for build scripts so we need to sniff it out from the environment variable.
11592
source.push(match ::std::env::var("CARGO_CFG_TARGET_ARCH").expect("No `CARGO_CFG_TARGET_ARCH` env variable set").as_str() {
11693
"x86_64" => "x64",
@@ -124,17 +101,12 @@ pub fn build(stream: proc_macro::TokenStream) -> proc_macro::TokenStream {
124101
println!("cargo:rustc-link-search=native={}", source.to_str().expect("`CARGO_MANIFEST_DIR` not a valid path"));
125102
}
126103

127-
let mut destination : ::std::path::PathBuf = #target_dir.into();
104+
let mut destination: ::std::path::PathBuf = ::std::env::var("OUT_DIR").expect("No `OUT_DIR` env variable set").into();
105+
// Of `target/<profile>/build/<crate_name>/out`, pop the last 3 folders
106+
destination.pop();
128107
destination.pop();
129108
destination.pop();
130109

131-
let profile = ::std::env::var("PROFILE").expect("No `PROFILE` env variable set");
132-
copy_to_profile(&source, &destination, &profile);
133-
134-
destination.push(".windows");
135-
destination.push("winmd");
136-
source.pop();
137-
source.push("winmd");
138110
copy(&source, &mut destination);
139111
}
140112
}

0 commit comments

Comments
 (0)