Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Find winmd files without reading PATH nor copying to target/ #1047

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 0 additions & 36 deletions crates/gen/build.rs

This file was deleted.

39 changes: 20 additions & 19 deletions crates/gen/src/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ fn get_crate_winmds() -> Vec<File> {
if let Ok(file_type) = file.file_type() {
if file_type.is_file() {
let path = file.path();
if let Some("winmd") =
path.extension().and_then(|extension| extension.to_str())
if path.extension().and_then(|extension| extension.to_str())
== Some("winmd")
{
result.push(File::new(path));
}
Expand All @@ -93,26 +93,27 @@ fn get_crate_winmds() -> Vec<File> {

let mut result = vec![];

// Manifest directory of the crate calling `build!`
if let Ok(dir) = std::env::var("CARGO_MANIFEST_DIR") {
let mut dir: std::path::PathBuf = dir.into();
dir.push(".windows");
dir.push("winmd");
push_dir(&mut result, &dir);
push_dir(
&mut result,
&std::path::Path::new(&dir).join(".windows/winmd"),
);
}

let dir = std::env::var("PATH").expect("No `PATH` env variable set");
let end = dir.find(';').expect("Path not ending in `;`");
let mut dir: std::path::PathBuf = dir[..end].into();
dir.pop();
dir.pop();
dir.push(".windows");
dir.push("winmd");
push_dir(&mut result, &dir);

let mut dir: std::path::PathBuf = target_dir().into();
dir.push(".windows");
dir.push("winmd");
push_dir(&mut result, &dir);
// Default manifests provided by windows_gen
// TODO: include_bytes is very slow - it takes an extra 60ms compared with memory mapped files.
// https://github.com/rust-lang/rust/issues/65818
if !result.iter().any(|file| file.name.starts_with("Windows.")) {
result.push(File::from_bytes(
"Windows.Win32.winmd".to_string(),
include_bytes!("../.windows/winmd/Windows.Win32.winmd").to_vec(),
));
result.push(File::from_bytes(
"Windows.WinRT.winmd".to_string(),
include_bytes!("../.windows/winmd/Windows.WinRT.winmd").to_vec(),
));
}

result
}
60 changes: 16 additions & 44 deletions crates/macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,6 @@ impl ToTokens for RawString {
pub fn build(stream: proc_macro::TokenStream) -> proc_macro::TokenStream {
let build = parse_macro_input!(stream as BuildMacro);
let tokens = RawString(build.to_tokens_string());
let target_dir = std::env::var("PATH").expect("No `PATH` env variable set");
let end = target_dir.find(';').expect("Path not ending in `;`");
let target_dir = RawString(target_dir[..end].to_string());

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

path.push("windows.rs");
println!("cargo:rerun-if-changed={}", path.to_str().expect("`OUT_DIR` not a UTF-8 string"));

::std::fs::write(&path, #tokens).expect("Could not write generated code to windows.rs");

let mut cmd = ::std::process::Command::new("rustfmt");
Expand All @@ -68,49 +67,27 @@ pub fn build(stream: proc_macro::TokenStream) -> proc_macro::TokenStream {
fn copy(source: &::std::path::Path, destination: &mut ::std::path::PathBuf) {
if let ::std::result::Result::Ok(entries) = ::std::fs::read_dir(source) {
for entry in entries.filter_map(|entry| entry.ok()) {
if let ::std::result::Result::Ok(entry_type) = entry.file_type() {
let path = entry.path();
if let ::std::option::Option::Some(last_path_component) = path.file_name() {
let _ = ::std::fs::create_dir_all(&destination);
destination.push(last_path_component);
if entry_type.is_file() {
let _ = ::std::fs::copy(path, &destination);
} else if entry_type.is_dir() {
let _ = ::std::fs::create_dir(&destination);
copy(&path, destination);
}
destination.pop();
}
}
}
}
}

fn copy_to_profile(source: &::std::path::Path, destination: &::std::path::Path, profile: &str) {
if let ::std::result::Result::Ok(files) = ::std::fs::read_dir(destination) {
for file in files.filter_map(|file| file.ok()) {
if let ::std::result::Result::Ok(file_type) = file.file_type() {
if file_type.is_dir() {
let mut path = file.path();
if let ::std::option::Option::Some(filename) = path.file_name() {
if filename == profile {
copy(source, &mut path);
} else {
copy_to_profile(source, &path, profile);
}
}
let path = entry.path();
if let ::std::option::Option::Some(last_path_component) = path.file_name() {
let _ = ::std::fs::create_dir_all(&destination);
destination.push(last_path_component);
if path.is_file() {
let _ = ::std::fs::copy(path, &destination);
} else if path.is_dir() {
let _ = ::std::fs::create_dir(&destination);
copy(&path, destination);
}
destination.pop();
}
}
}
}

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

if source.exists() {
println!("cargo:rerun-if-changed={}", source.to_str().expect("`CARGO_MANIFEST_DIR` not a valid path"));

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

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

let profile = ::std::env::var("PROFILE").expect("No `PROFILE` env variable set");
copy_to_profile(&source, &destination, &profile);

destination.push(".windows");
destination.push("winmd");
source.pop();
source.push("winmd");
copy(&source, &mut destination);
}
}
Expand Down