Build test-macros in a build script

This commit is contained in:
Jonas Schievink 2021-06-09 17:16:52 +02:00
parent 5f592f4f58
commit 05b3a4bc93
9 changed files with 133 additions and 75 deletions

9
Cargo.lock generated
View file

@ -1158,6 +1158,15 @@ dependencies = [
[[package]]
name = "proc_macro_test"
version = "0.0.0"
dependencies = [
"cargo_metadata",
"proc_macro_test_impl",
"toolchain",
]
[[package]]
name = "proc_macro_test_impl"
version = "0.0.0"
[[package]]
name = "profile"

View file

@ -1,6 +1,7 @@
[workspace]
resolver = "2"
members = ["xtask/", "lib/*", "crates/*"]
exclude = ["crates/proc_macro_test/imp"]
[profile.dev]
# Disabling debug info speeds up builds a bunch,

View file

@ -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()
}
}

View file

@ -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"

View file

@ -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();
}

2
crates/proc_macro_test/imp/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
target/
Cargo.lock

View file

@ -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`

View file

@ -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()
}

View file

@ -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"));