aboutsummaryrefslogtreecommitdiff
path: root/mingling_pathf
diff options
context:
space:
mode:
Diffstat (limited to 'mingling_pathf')
-rw-r--r--mingling_pathf/Cargo.toml1
-rw-r--r--mingling_pathf/src/error.rs6
-rw-r--r--mingling_pathf/src/lib.rs2
-rw-r--r--mingling_pathf/src/type_mapping_builder.rs76
-rw-r--r--mingling_pathf/test/Cargo.lock138
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"