Skip to content

Commit

Permalink
More reliable target dir discovery (#951)
Browse files Browse the repository at this point in the history
  • Loading branch information
kennykerr authored Jul 7, 2021
1 parent 49ecfbc commit d5de34f
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 49 deletions.
2 changes: 1 addition & 1 deletion crates/bindings/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ fn main() -> std::io::Result<()> {
},
};

let mut path = windows_gen::workspace_dir();
let mut path: std::path::PathBuf = windows_gen::workspace_dir().into();
path.push("src");
path.push("bindings.rs");

Expand Down
2 changes: 1 addition & 1 deletion crates/fmt/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ fn walk_path(path: &Path) -> Result<()> {
}

fn main() -> Result<()> {
let dir = windows_gen::workspace_dir();
let dir: std::path::PathBuf = windows_gen::workspace_dir().into();
walk_path(&dir)?;

format_file(
Expand Down
74 changes: 42 additions & 32 deletions crates/gen/src/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,10 @@ pub fn crate_winmds() -> &'static [File] {
unsafe { &*VALUE.as_ptr() }
}

pub fn workspace_dir() -> std::path::PathBuf {
fn cargo_metadata() -> &'static str {
use std::{mem::MaybeUninit, sync::Once};
static ONCE: Once = Once::new();
static mut VALUE: MaybeUninit<std::path::PathBuf> = MaybeUninit::uninit();

// TODO: calling `cargo metadata` just to get the workspace dir takes about 40ms.
static mut VALUE: MaybeUninit<String> = MaybeUninit::uninit();

ONCE.call_once(|| {
let output = std::process::Command::new(env!("CARGO"))
Expand All @@ -30,27 +28,49 @@ pub fn workspace_dir() -> std::path::PathBuf {
.output()
.expect("Failed to run `cargo metadata`");

const JSON_KEY: &str = r#""workspace_root":"#;
let json = String::from_utf8(output.stdout).expect("Cargo metadata is not utf-8");
let beginning_index = json
.rfind(JSON_KEY)
.expect("Cargo metadata did not contain `workspace_root` key.")
+ JSON_KEY.len()
+ 1;
unsafe {
VALUE = MaybeUninit::new(
String::from_utf8(output.stdout).expect("Cargo metadata is not utf-8"),
)
}
});

// This is safe because `call_once` has already been called.
unsafe { &*VALUE.as_ptr() }
}

let ending_index = json[beginning_index..]
.find('"')
.expect("Cargo metadata ended before closing '\"' in `workspace_root` value");
pub fn workspace_dir() -> String {
const JSON_KEY: &str = r#""workspace_root":"#;
let json = cargo_metadata();

let workspace_root =
json[beginning_index..beginning_index + ending_index].replace("\\\\", "\\");
let beginning_index = json
.rfind(JSON_KEY)
.expect("Cargo metadata did not contain `workspace_root` key.")
+ JSON_KEY.len()
+ 1;

// This is safe because `Once` provides thread-safe one-time initialization
unsafe { VALUE = MaybeUninit::new(workspace_root.into()) }
});
let ending_index = json[beginning_index..]
.find('"')
.expect("Cargo metadata ended before closing '\"' in `workspace_root` value");

// This is safe because `call_once` has already been called.
unsafe { (*VALUE.as_ptr()).clone() }
json[beginning_index..beginning_index + ending_index].replace("\\\\", "\\")
}

pub fn target_dir() -> String {
const JSON_KEY: &str = r#""target_directory":"#;
let json = cargo_metadata();

let beginning_index = json
.rfind(JSON_KEY)
.expect("Cargo metadata did not contain `target_directory` key.")
+ JSON_KEY.len()
+ 1;

let ending_index = json[beginning_index..]
.find('"')
.expect("Cargo metadata ended before closing '\"' in `target_directory` value");

json[beginning_index..beginning_index + ending_index].replace("\\\\", "\\")
}

fn get_crate_winmds() -> Vec<File> {
Expand Down Expand Up @@ -81,17 +101,7 @@ fn get_crate_winmds() -> Vec<File> {
dir.push("winmd");
push_dir(&mut result, &dir);

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 = workspace_dir();
dir.push("target");
let mut dir: std::path::PathBuf = target_dir().into();
dir.push(".windows");
dir.push("winmd");
push_dir(&mut result, &dir);
Expand Down
17 changes: 2 additions & 15 deletions crates/macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ 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.into_tokens_string());
let target_dir = RawString(gen::target_dir());

let tokens = quote! {
{
Expand Down Expand Up @@ -118,22 +119,8 @@ 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 = ::std::env::var("OUT_DIR").expect("No `OUT_DIR` env variable set").into();

loop {
destination.pop();
destination.push("Cargo.toml");

if destination.exists() {
break;
}

destination.pop();
}

destination.pop();
destination.push("target");

let mut destination : ::std::path::PathBuf = #target_dir.into();
let profile = ::std::env::var("PROFILE").expect("No `PROFILE` env variable set");
copy_to_profile(&source, &destination, &profile);

Expand Down

0 comments on commit d5de34f

Please sign in to comment.