diff options
Diffstat (limited to 'mingling_pathf')
| -rw-r--r-- | mingling_pathf/Cargo.toml | 1 | ||||
| -rw-r--r-- | mingling_pathf/src/error.rs | 6 | ||||
| -rw-r--r-- | mingling_pathf/src/lib.rs | 2 | ||||
| -rw-r--r-- | mingling_pathf/src/type_mapping_builder.rs | 76 | ||||
| -rw-r--r-- | mingling_pathf/test/Cargo.lock | 138 |
5 files changed, 202 insertions, 21 deletions
diff --git a/mingling_pathf/Cargo.toml b/mingling_pathf/Cargo.toml index 0d4e37a..a649cb4 100644 --- a/mingling_pathf/Cargo.toml +++ b/mingling_pathf/Cargo.toml @@ -12,3 +12,4 @@ description = "A library for automatically finding internal types generated by M syn.workspace = true proc-macro2.workspace = true just_fmt.workspace = true +cargo_metadata.workspace = true diff --git a/mingling_pathf/src/error.rs b/mingling_pathf/src/error.rs index 5a748c4..bd850a8 100644 --- a/mingling_pathf/src/error.rs +++ b/mingling_pathf/src/error.rs @@ -53,6 +53,11 @@ pub enum MinglingPathfinderError { /// Details from the parser about the parse failure. message: String, }, + + /// `cargo metadata` could not be executed or parsed. + /// + /// `message` contains the underlying error from the cargo invocation. + CargoMetadata(String), } impl fmt::Display for MinglingPathfinderError { @@ -82,6 +87,7 @@ impl fmt::Display for MinglingPathfinderError { Self::SynError { path, message } => { write!(f, "Failed to parse {}: {message}", path.display()) } + Self::CargoMetadata(message) => write!(f, "cargo metadata failed: {message}"), } } } diff --git a/mingling_pathf/src/lib.rs b/mingling_pathf/src/lib.rs index 492bfc7..f0637e8 100644 --- a/mingling_pathf/src/lib.rs +++ b/mingling_pathf/src/lib.rs @@ -13,3 +13,5 @@ pub mod patterns; mod type_mapping_builder; pub use type_mapping_builder::analyze_and_build_type_mapping; pub use type_mapping_builder::analyze_and_build_type_mapping_for; +pub use type_mapping_builder::build_output_dir; +pub use type_mapping_builder::target_directory; diff --git a/mingling_pathf/src/type_mapping_builder.rs b/mingling_pathf/src/type_mapping_builder.rs index 1ccd267..4d0799f 100644 --- a/mingling_pathf/src/type_mapping_builder.rs +++ b/mingling_pathf/src/type_mapping_builder.rs @@ -5,7 +5,9 @@ use std::collections::HashSet; use std::fmt::Write as FmtWrite; -use std::path::Path; +use std::path::{Path, PathBuf}; + +use cargo_metadata::MetadataCommand; use crate::error::MinglingPathfinderError; use crate::module_pathf; @@ -87,40 +89,74 @@ pub fn analyze_and_build_type_mapping_for( Ok(()) } -/// Convenience version to be called from `build.rs`, automatically reading configuration -/// from environment variables. +/// Runs `cargo metadata` from the given crate directory and returns the +/// workspace's target directory. +/// +/// The subprocess resolves the target directory exactly as Cargo does, +/// honoring `.cargo/config.toml`, `CARGO_TARGET_DIR`, and `--target-dir`. +/// +/// `crate_dir` — crate root directory (i.e., the directory containing Cargo.toml). +/// +/// # Errors +/// +/// Returns a [`MinglingPathfinderError::CargoMetadata`] if `cargo metadata` +/// cannot be executed or its output cannot be parsed. +pub fn target_directory(crate_dir: &Path) -> Result<PathBuf, MinglingPathfinderError> { + let metadata = MetadataCommand::new() + .current_dir(crate_dir) + .no_deps() + .exec() + .map_err(|e| MinglingPathfinderError::CargoMetadata(e.to_string()))?; + Ok(metadata.target_directory.into_std_path_buf()) +} + +/// The directory where all of Mingling's compile-time build artifacts are +/// written for the current crate: `{target_directory}/mingling/`. +/// +/// Reads `CARGO_MANIFEST_DIR` from the environment to locate the crate, then +/// resolves the target directory via [`target_directory`]. Works both from a +/// `build.rs` and from proc-macro expansion (no `OUT_DIR` required). +/// +/// # Errors +/// +/// Returns a [`MinglingPathfinderError`] if the environment variables are +/// missing or the target directory cannot be resolved. +pub fn build_output_dir() -> Result<PathBuf, MinglingPathfinderError> { + let crate_dir = std::env::var("CARGO_MANIFEST_DIR").map_err(|_| { + MinglingPathfinderError::IoError(std::io::Error::new( + std::io::ErrorKind::NotFound, + "CARGO_MANIFEST_DIR not set", + )) + })?; + Ok(target_directory(Path::new(&crate_dir))?.join("mingling")) +} + +/// Convenience version to be called from `build.rs` or macro expansion, +/// automatically reading configuration from environment variables. /// -/// Reads `CARGO_PKG_NAME` and `OUT_DIR`, and outputs to `{OUT_DIR}/{CARGO_PKG_NAME}/`. +/// Reads `CARGO_PKG_NAME` and `CARGO_MANIFEST_DIR`, and outputs to +/// `{target_directory}/mingling/{CARGO_PKG_NAME}/` (see [`build_output_dir`]). /// /// # Errors /// /// Returns a [`MinglingPathfinderError`] if the required environment variables -/// (`CARGO_PKG_NAME`, `OUT_DIR`) are not set, the current directory cannot be -/// determined, or the type mapping generation fails. +/// (`CARGO_PKG_NAME`, `CARGO_MANIFEST_DIR`) are not set or the type mapping +/// generation fails. pub fn analyze_and_build_type_mapping() -> Result<(), MinglingPathfinderError> { let crate_name = std::env::var("CARGO_PKG_NAME").map_err(|_| { MinglingPathfinderError::IoError(std::io::Error::new( std::io::ErrorKind::NotFound, - "CARGO_PKG_NAME not set (not running in build.rs?)", + "CARGO_PKG_NAME not set", )) })?; - - let out_dir = std::env::var("OUT_DIR").map_err(|_| { + let crate_dir = std::env::var("CARGO_MANIFEST_DIR").map_err(|_| { MinglingPathfinderError::IoError(std::io::Error::new( std::io::ErrorKind::NotFound, - "OUT_DIR not set (not running in build.rs?)", + "CARGO_MANIFEST_DIR not set", )) })?; - let crate_dir = std::env::current_dir()?; - let output_dir = Path::new(&out_dir).join(&crate_name); - - analyze_and_build_type_mapping_for(&crate_dir, &output_dir)?; + let output_dir = build_output_dir()?.join(&crate_name); - // Notify Cargo to re-run build.rs when source files change - println!("cargo:rerun-if-changed=src/"); - println!("cargo:rerun-if-env-changed=CARGO_CFG_TARGET_OS"); - println!("cargo:rerun-if-env-changed=CARGO_CFG_TARGET_ARCH"); - - Ok(()) + analyze_and_build_type_mapping_for(Path::new(&crate_dir), &output_dir) } diff --git a/mingling_pathf/test/Cargo.lock b/mingling_pathf/test/Cargo.lock index 58c7c9a..7dc772a 100644 --- a/mingling_pathf/test/Cargo.lock +++ b/mingling_pathf/test/Cargo.lock @@ -3,6 +3,45 @@ version = 4 [[package]] +name = "camino" +version = "1.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d" +dependencies = [ + "serde_core", +] + +[[package]] +name = "cargo-platform" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0061da739915fae12ea00e16397555ed4371a6bb285431aab930f61b0aa4ba" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "cargo_metadata" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] name = "just_fmt" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -15,12 +54,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6170dccbc3ea15dfb7f2da964097f814aba1dd8f746d4ffc56f33245c38e6d96" [[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] name = "mingling_pathf" version = "0.5.0" dependencies = [ + "cargo_metadata", "just_fmt 0.2.0", "proc-macro2", - "syn", + "syn 2.0.118", ] [[package]] @@ -42,6 +88,59 @@ dependencies = [ ] [[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "serde" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "serde_json" +version = "1.0.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] name = "syn" version = "2.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -53,6 +152,17 @@ dependencies = [ ] [[package]] +name = "syn" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] name = "test-mingling-pathf" version = "0.1.0" dependencies = [ @@ -61,7 +171,33 @@ dependencies = [ ] [[package]] +name = "thiserror" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] name = "unicode-ident" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" |
