From 05b3a4bc93cf6555857bfc68b5e85830a0da80dc Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Wed, 9 Jun 2021 17:16:52 +0200 Subject: Build test-macros in a build script --- crates/proc_macro_srv/src/tests/utils.rs | 29 +------------------ crates/proc_macro_test/Cargo.toml | 6 +++- crates/proc_macro_test/build.rs | 48 ++++++++++++++++++++++++++++++++ crates/proc_macro_test/imp/.gitignore | 2 ++ crates/proc_macro_test/imp/Cargo.toml | 17 +++++++++++ crates/proc_macro_test/imp/src/lib.rs | 48 ++++++++++++++++++++++++++++++++ crates/proc_macro_test/src/lib.rs | 48 ++------------------------------ 7 files changed, 123 insertions(+), 75 deletions(-) create mode 100644 crates/proc_macro_test/build.rs create mode 100644 crates/proc_macro_test/imp/.gitignore create mode 100644 crates/proc_macro_test/imp/Cargo.toml create mode 100644 crates/proc_macro_test/imp/src/lib.rs (limited to 'crates') diff --git a/crates/proc_macro_srv/src/tests/utils.rs b/crates/proc_macro_srv/src/tests/utils.rs index 2e950c113..2c093aa0a 100644 --- a/crates/proc_macro_srv/src/tests/utils.rs +++ b/crates/proc_macro_srv/src/tests/utils.rs @@ -7,35 +7,8 @@ use proc_macro_api::ListMacrosTask; use std::str::FromStr; pub mod fixtures { - use cargo_metadata::Message; - use std::path::PathBuf; - use std::process::Command; - - // Use current project metadata to get the proc-macro dylib path pub fn proc_macro_test_dylib_path() -> std::path::PathBuf { - let name = "proc_macro_test"; - let version = "0.0.0"; - let command = Command::new(toolchain::cargo()) - .args(&["check", "--tests", "--message-format", "json"]) - .output() - .unwrap() - .stdout; - - for message in Message::parse_stream(command.as_slice()) { - match message.unwrap() { - Message::CompilerArtifact(artifact) => { - if artifact.target.kind.contains(&"proc-macro".to_string()) { - let repr = format!("{} {}", name, version); - if artifact.package_id.repr.starts_with(&repr) { - return PathBuf::from(&artifact.filenames[0]); - } - } - } - _ => (), // Unknown message - } - } - - panic!("No proc-macro dylib for {} found!", name); + proc_macro_test::PROC_MACRO_TEST_LOCATION.into() } } diff --git a/crates/proc_macro_test/Cargo.toml b/crates/proc_macro_test/Cargo.toml index 753443be2..1a88e361e 100644 --- a/crates/proc_macro_test/Cargo.toml +++ b/crates/proc_macro_test/Cargo.toml @@ -8,4 +8,8 @@ publish = false [lib] doctest = false -proc-macro = true + +[build-dependencies] +proc_macro_test_impl = { path = "imp", version = "0.0.0" } +toolchain = { path = "../toolchain", version = "0.0.0" } +cargo_metadata = "0.13" diff --git a/crates/proc_macro_test/build.rs b/crates/proc_macro_test/build.rs new file mode 100644 index 000000000..4653a93dd --- /dev/null +++ b/crates/proc_macro_test/build.rs @@ -0,0 +1,48 @@ +//! This will build the proc macro in `imp`, and copy the resulting dylib artifact into the +//! `OUT_DIR`. +//! +//! `proc_macro_test` itself contains only a path to that artifact. + +use std::{ + env, fs, + path::{Path, PathBuf}, + process::Command, +}; + +use cargo_metadata::Message; + +fn main() { + let out_dir = env::var_os("OUT_DIR").unwrap(); + let out_dir = Path::new(&out_dir); + + let name = "proc_macro_test_impl"; + let version = "0.0.0"; + let output = Command::new(toolchain::cargo()) + .current_dir("imp") + .args(&["build", "-p", "proc_macro_test_impl", "--message-format", "json"]) + .output() + .unwrap(); + assert!(output.status.success()); + + let mut artifact_path = None; + for message in Message::parse_stream(output.stdout.as_slice()) { + match message.unwrap() { + Message::CompilerArtifact(artifact) => { + if artifact.target.kind.contains(&"proc-macro".to_string()) { + let repr = format!("{} {}", name, version); + if artifact.package_id.repr.starts_with(&repr) { + artifact_path = Some(PathBuf::from(&artifact.filenames[0])); + } + } + } + _ => (), // Unknown message + } + } + + let src_path = artifact_path.expect("no dylib for proc_macro_test_impl found"); + let dest_path = out_dir.join(src_path.file_name().unwrap()); + fs::copy(src_path, &dest_path).unwrap(); + + let info_path = out_dir.join("proc_macro_test_location.txt"); + fs::write(info_path, dest_path.to_str().unwrap()).unwrap(); +} diff --git a/crates/proc_macro_test/imp/.gitignore b/crates/proc_macro_test/imp/.gitignore new file mode 100644 index 000000000..2c96eb1b6 --- /dev/null +++ b/crates/proc_macro_test/imp/.gitignore @@ -0,0 +1,2 @@ +target/ +Cargo.lock diff --git a/crates/proc_macro_test/imp/Cargo.toml b/crates/proc_macro_test/imp/Cargo.toml new file mode 100644 index 000000000..1c2e75401 --- /dev/null +++ b/crates/proc_macro_test/imp/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "proc_macro_test_impl" +version = "0.0.0" +license = "MIT OR Apache-2.0" +authors = ["rust-analyzer developers"] +edition = "2018" +publish = false + +[lib] +doctest = false +proc-macro = true + +[workspace] + +[dependencies] +# this crate should not have any dependencies, since it uses its own workspace, +# and its own `Cargo.lock` diff --git a/crates/proc_macro_test/imp/src/lib.rs b/crates/proc_macro_test/imp/src/lib.rs new file mode 100644 index 000000000..4b26d2472 --- /dev/null +++ b/crates/proc_macro_test/imp/src/lib.rs @@ -0,0 +1,48 @@ +//! Exports a few trivial procedural macros for testing. + +use proc_macro::TokenStream; + +#[proc_macro] +pub fn fn_like_noop(args: TokenStream) -> TokenStream { + args +} + +#[proc_macro] +pub fn fn_like_panic(args: TokenStream) -> TokenStream { + panic!("fn_like_panic!({})", args); +} + +#[proc_macro] +pub fn fn_like_error(args: TokenStream) -> TokenStream { + format!("compile_error!(\"fn_like_error!({})\");", args).parse().unwrap() +} + +#[proc_macro_attribute] +pub fn attr_noop(_args: TokenStream, item: TokenStream) -> TokenStream { + item +} + +#[proc_macro_attribute] +pub fn attr_panic(args: TokenStream, item: TokenStream) -> TokenStream { + panic!("#[attr_panic {}] {}", args, item); +} + +#[proc_macro_attribute] +pub fn attr_error(args: TokenStream, item: TokenStream) -> TokenStream { + format!("compile_error!(\"#[attr_error({})] {}\");", args, item).parse().unwrap() +} + +#[proc_macro_derive(DeriveEmpty)] +pub fn derive_empty(_item: TokenStream) -> TokenStream { + TokenStream::new() +} + +#[proc_macro_derive(DerivePanic)] +pub fn derive_panic(item: TokenStream) -> TokenStream { + panic!("#[derive(DerivePanic)] {}", item); +} + +#[proc_macro_derive(DeriveError)] +pub fn derive_error(item: TokenStream) -> TokenStream { + format!("compile_error!(\"#[derive(DeriveError)] {}\");", item).parse().unwrap() +} diff --git a/crates/proc_macro_test/src/lib.rs b/crates/proc_macro_test/src/lib.rs index 4b26d2472..2edf23a63 100644 --- a/crates/proc_macro_test/src/lib.rs +++ b/crates/proc_macro_test/src/lib.rs @@ -1,48 +1,4 @@ //! Exports a few trivial procedural macros for testing. -use proc_macro::TokenStream; - -#[proc_macro] -pub fn fn_like_noop(args: TokenStream) -> TokenStream { - args -} - -#[proc_macro] -pub fn fn_like_panic(args: TokenStream) -> TokenStream { - panic!("fn_like_panic!({})", args); -} - -#[proc_macro] -pub fn fn_like_error(args: TokenStream) -> TokenStream { - format!("compile_error!(\"fn_like_error!({})\");", args).parse().unwrap() -} - -#[proc_macro_attribute] -pub fn attr_noop(_args: TokenStream, item: TokenStream) -> TokenStream { - item -} - -#[proc_macro_attribute] -pub fn attr_panic(args: TokenStream, item: TokenStream) -> TokenStream { - panic!("#[attr_panic {}] {}", args, item); -} - -#[proc_macro_attribute] -pub fn attr_error(args: TokenStream, item: TokenStream) -> TokenStream { - format!("compile_error!(\"#[attr_error({})] {}\");", args, item).parse().unwrap() -} - -#[proc_macro_derive(DeriveEmpty)] -pub fn derive_empty(_item: TokenStream) -> TokenStream { - TokenStream::new() -} - -#[proc_macro_derive(DerivePanic)] -pub fn derive_panic(item: TokenStream) -> TokenStream { - panic!("#[derive(DerivePanic)] {}", item); -} - -#[proc_macro_derive(DeriveError)] -pub fn derive_error(item: TokenStream) -> TokenStream { - format!("compile_error!(\"#[derive(DeriveError)] {}\");", item).parse().unwrap() -} +pub static PROC_MACRO_TEST_LOCATION: &str = + include_str!(concat!(env!("OUT_DIR"), "/proc_macro_test_location.txt")); -- cgit v1.2.3 From d236fc6abecb308dab5e21898fa40f3bddf27640 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Wed, 9 Jun 2021 18:02:04 +0200 Subject: Try to fix unique file names on Windows --- crates/proc_macro_srv/src/dylib.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'crates') diff --git a/crates/proc_macro_srv/src/dylib.rs b/crates/proc_macro_srv/src/dylib.rs index cccc53220..5133e7c50 100644 --- a/crates/proc_macro_srv/src/dylib.rs +++ b/crates/proc_macro_srv/src/dylib.rs @@ -188,7 +188,9 @@ impl Expander { /// Copy the dylib to temp directory to prevent locking in Windows #[cfg(windows)] fn ensure_file_with_lock_free_access(path: &Path) -> io::Result { - use std::{ffi::OsString, time::SystemTime}; + use std::collections::hash_map::RandomState; + use std::ffi::OsString; + use std::hash::{BuildHasher, Hasher}; let mut to = std::env::temp_dir(); @@ -199,10 +201,11 @@ fn ensure_file_with_lock_free_access(path: &Path) -> io::Result { ) })?; - // generate a time deps unique number - let t = SystemTime::now().duration_since(std::time::UNIX_EPOCH).expect("Time went backwards"); + // Generate a unique number by abusing `HashMap`'s hasher. + // Maybe this will also "inspire" a libs team member to finally put `rand` in libstd. + let t = RandomState::new().build_hasher().finish(); - let mut unique_name = OsString::from(t.as_millis().to_string()); + let mut unique_name = OsString::from(t.to_string()); unique_name.push(file_name); to.push(unique_name); -- cgit v1.2.3