diff --git a/src/cargo/core/compiler/compilation.rs b/src/cargo/core/compiler/compilation.rs index 405b17b9884..8ec625d77a4 100644 --- a/src/cargo/core/compiler/compilation.rs +++ b/src/cargo/core/compiler/compilation.rs @@ -356,6 +356,7 @@ impl<'gctx> Compilation<'gctx> { // in BuildContext::target_metadata() let rust_version = pkg.rust_version().as_ref().map(ToString::to_string); cmd.env("CARGO_MANIFEST_DIR", pkg.root()) + .env("CARGO_MANIFEST_PATH", pkg.manifest_path()) .env("CARGO_PKG_VERSION_MAJOR", &pkg.version().major.to_string()) .env("CARGO_PKG_VERSION_MINOR", &pkg.version().minor.to_string()) .env("CARGO_PKG_VERSION_PATCH", &pkg.version().patch.to_string()) diff --git a/src/cargo/core/compiler/custom_build.rs b/src/cargo/core/compiler/custom_build.rs index 706783d9332..f36e741c65b 100644 --- a/src/cargo/core/compiler/custom_build.rs +++ b/src/cargo/core/compiler/custom_build.rs @@ -279,6 +279,7 @@ fn build_work(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> CargoResul let debug = unit.profile.debuginfo.is_turned_on(); cmd.env("OUT_DIR", &script_out_dir) .env("CARGO_MANIFEST_DIR", unit.pkg.root()) + .env("CARGO_MANIFEST_PATH", unit.pkg.manifest_path()) .env("NUM_JOBS", &bcx.jobs().to_string()) .env("TARGET", bcx.target_data.short_name(&unit.kind)) .env("DEBUG", debug.to_string()) diff --git a/src/doc/src/reference/environment-variables.md b/src/doc/src/reference/environment-variables.md index 3a7053675cc..415e6891890 100644 --- a/src/doc/src/reference/environment-variables.md +++ b/src/doc/src/reference/environment-variables.md @@ -226,6 +226,7 @@ corresponding environment variable is set to the empty string, `""`. * `CARGO` --- Path to the `cargo` binary performing the build. * `CARGO_MANIFEST_DIR` --- The directory containing the manifest of your package. +* `CARGO_MANIFEST_PATH` --- The path to the manifest of your package. * `CARGO_PKG_VERSION` --- The full version of your package. * `CARGO_PKG_VERSION_MAJOR` --- The major version of your package. * `CARGO_PKG_VERSION_MINOR` --- The minor version of your package. @@ -320,6 +321,7 @@ let out_dir = env::var("OUT_DIR").unwrap(); * `CARGO_MANIFEST_DIR` --- The directory containing the manifest for the package being built (the package containing the build script). Also note that this is the value of the current working directory of the build script when it starts. +* `CARGO_MANIFEST_PATH` --- The path to the manifest of your package. * `CARGO_MANIFEST_LINKS` --- the manifest `links` value. * `CARGO_MAKEFLAGS` --- Contains parameters needed for Cargo's [jobserver] implementation to parallelize subprocesses. Rustc or cargo invocations from diff --git a/src/doc/src/reference/unstable.md b/src/doc/src/reference/unstable.md index 18be45fc2b0..7e265a4a26d 100644 --- a/src/doc/src/reference/unstable.md +++ b/src/doc/src/reference/unstable.md @@ -1460,7 +1460,7 @@ This will not affect any hard-coded paths in the source code, such as in strings Values in a non-empty array would be joined into a comma-separated list. If the build script introduces absolute paths to built artifacts (such as by invoking a compiler), the user may request them to be sanitized in different types of artifacts. - Common paths requiring sanitization include `OUT_DIR` and `CARGO_MANIFEST_DIR`, + Common paths requiring sanitization include `OUT_DIR`, `CARGO_MANIFEST_DIR` and `CARGO_MANIFEST_PATH`, plus any other introduced by the build script, such as include directories. ## gc diff --git a/tests/testsuite/build.rs b/tests/testsuite/build.rs index 93254deadb1..db82c0f4f55 100644 --- a/tests/testsuite/build.rs +++ b/tests/testsuite/build.rs @@ -1625,6 +1625,7 @@ fn crate_env_vars() { static VERSION_PRE: &'static str = env!("CARGO_PKG_VERSION_PRE"); static VERSION: &'static str = env!("CARGO_PKG_VERSION"); static CARGO_MANIFEST_DIR: &'static str = env!("CARGO_MANIFEST_DIR"); + static CARGO_MANIFEST_PATH: &'static str = env!("CARGO_MANIFEST_PATH"); static PKG_NAME: &'static str = env!("CARGO_PKG_NAME"); static HOMEPAGE: &'static str = env!("CARGO_PKG_HOMEPAGE"); static REPOSITORY: &'static str = env!("CARGO_PKG_REPOSITORY"); @@ -1638,9 +1639,9 @@ fn crate_env_vars() { fn main() { - let s = format!("{}-{}-{} @ {} in {}", VERSION_MAJOR, + let s = format!("{}-{}-{} @ {} in {} file {}", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_PRE, - CARGO_MANIFEST_DIR); + CARGO_MANIFEST_DIR, CARGO_MANIFEST_PATH); assert_eq!(s, foo::version()); println!("{}", s); assert_eq!("foo", PKG_NAME); @@ -1674,12 +1675,13 @@ fn crate_env_vars() { use std::path::PathBuf; pub fn version() -> String { - format!("{}-{}-{} @ {} in {}", + format!("{}-{}-{} @ {} in {} file {}", env!("CARGO_PKG_VERSION_MAJOR"), env!("CARGO_PKG_VERSION_MINOR"), env!("CARGO_PKG_VERSION_PATCH"), env!("CARGO_PKG_VERSION_PRE"), - env!("CARGO_MANIFEST_DIR")) + env!("CARGO_MANIFEST_DIR"), + env!("CARGO_MANIFEST_PATH")) } pub fn check_no_int_test_env() { @@ -1795,7 +1797,7 @@ fn crate_env_vars() { println!("bin"); p.process(&p.bin("foo-bar")) .with_stdout_data(str![[r#" -0-5-1 @ alpha.1 in [ROOT]/foo +0-5-1 @ alpha.1 in [ROOT]/foo file [ROOT]/foo/Cargo.toml "#]]) .run(); @@ -1863,12 +1865,15 @@ fn cargo_rustc_current_dir_foreign_workspace_dep() { fn baz_env() { let workspace_dir = Path::new(option_env!("CARGO_RUSTC_CURRENT_DIR").expect("CARGO_RUSTC_CURRENT_DIR")); let manifest_dir = Path::new(option_env!("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR")); + let manifest_path = Path::new(option_env!("CARGO_MANIFEST_PATH").expect("CARGO_MANIFEST_PATH")); let current_dir = std::env::current_dir().expect("current_dir"); let file_path = workspace_dir.join(file!()); assert!(file_path.exists(), "{}", file_path.display()); let workspace_dir = std::fs::canonicalize(current_dir.join(workspace_dir)).expect("CARGO_RUSTC_CURRENT_DIR"); + let manifest_path = std::fs::canonicalize(current_dir.join(manifest_dir.clone()).join("Cargo.toml")).expect("CARGO_MANIFEST_PATH"); let manifest_dir = std::fs::canonicalize(current_dir.join(manifest_dir)).expect("CARGO_MANIFEST_DIR"); - assert_eq!(workspace_dir, manifest_dir); + assert_eq!(workspace_dir, manifest_dir.clone()); + assert_eq!(manifest_dir.join("Cargo.toml"), manifest_path); } "#, ) @@ -1957,12 +1962,15 @@ fn cargo_rustc_current_dir_non_local_dep() { fn bar_env() { let workspace_dir = Path::new(option_env!("CARGO_RUSTC_CURRENT_DIR").expect("CARGO_RUSTC_CURRENT_DIR")); let manifest_dir = Path::new(option_env!("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR")); + let manifest_path = Path::new(option_env!("CARGO_MANIFEST_PATH").expect("CARGO_MANIFEST_PATH")); let current_dir = std::env::current_dir().expect("current_dir"); let file_path = workspace_dir.join(file!()); assert!(file_path.exists(), "{}", file_path.display()); let workspace_dir = std::fs::canonicalize(current_dir.join(workspace_dir)).expect("CARGO_RUSTC_CURRENT_DIR"); + let manifest_path = std::fs::canonicalize(current_dir.join(manifest_dir.clone()).join("Cargo.toml")).expect("CARGO_MANIFEST_PATH"); let manifest_dir = std::fs::canonicalize(current_dir.join(manifest_dir)).expect("CARGO_MANIFEST_DIR"); - assert_eq!(workspace_dir, manifest_dir); + assert_eq!(workspace_dir, manifest_dir.clone()); + assert_eq!(manifest_dir.join("Cargo.toml"), manifest_path); } "#, ) diff --git a/tests/testsuite/script.rs b/tests/testsuite/script.rs index d5a2c5349a8..e8cd84073f3 100644 --- a/tests/testsuite/script.rs +++ b/tests/testsuite/script.rs @@ -1317,3 +1317,33 @@ fn cmd_publish_with_embedded() { "#]]) .run(); } + +#[cargo_test] +fn manifest_path_env() { + let p = cargo_test_support::project() + .file( + "script.rs", + r#"#!/usr/bin/env cargo + +fn main() { + let path = env!("CARGO_MANIFEST_PATH"); + println!("CARGO_MANIFEST_PATH: {}", path); +} +"#, + ) + .build(); + p.cargo("-Zscript -v script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" +CARGO_MANIFEST_PATH: [ROOT]/foo/script.rs + +"#]]) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2021` +[COMPILING] script v0.0.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/home/.cargo/target/[HASH]/debug/script[EXE]` + +"#]]) + .run(); +}