Skip to content

Commit 9b13310

Browse files
committed
Auto merge of #12996 - epage:current_dir, r=weihanglo
feat: Add `CARGO_RUSTC_CURRENT_DIR` (unstable) ### What does this PR try to resolve? This is an alternative to #12158's `CARGO_WORKSPACE_DIR` that was implementing the solution to #3946 that previously discussed in the cargo team meeting. `CARGO_WORKSPACE_DIR` is a bit awkward to document / describe because its the effective workspace directory of the thing being built. If the thing being built doesn't have a workspace, it falls back to `CARGO_MANIFEST_DIR`. It would also be hard to take into account what the `CARGO_WORKSPACE_DIR` would be for path dependencies into foreign workspaces *and* it wouldn't solve the problem the user is having. What the user really wants is the CWD of rustc when it is invoked. This is much simpler to describe and is accurate when using a path dependency to a foreign package. Because the CWD is a much simpler mechanism to talk about, I figured we could diverge from our prior consensus and make it always present, rather than limiting it to tests. ### How should we test and review this PR? The preparatory refactor commits have explanation for why they were to help ### Additional information Remaining work for #3946: get this stabilized
2 parents 22bbc95 + e81d84c commit 9b13310

File tree

3 files changed

+225
-15
lines changed

3 files changed

+225
-15
lines changed

src/cargo/core/compiler/mod.rs

+19-8
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,15 @@ fn prepare_rustc(cx: &Context<'_, '_>, unit: &Unit) -> CargoResult<ProcessBuilde
662662
let mut base = cx
663663
.compilation
664664
.rustc_process(unit, is_primary, is_workspace)?;
665+
build_base_args(cx, &mut base, unit)?;
666+
667+
base.inherit_jobserver(&cx.jobserver);
668+
build_deps_args(&mut base, cx, unit)?;
669+
add_cap_lints(cx.bcx, unit, &mut base);
670+
base.args(cx.bcx.rustflags_args(unit));
671+
if cx.bcx.config.cli_unstable().binary_dep_depinfo {
672+
base.arg("-Z").arg("binary-dep-depinfo");
673+
}
665674

666675
if is_primary {
667676
base.env("CARGO_PRIMARY_PACKAGE", "1");
@@ -671,15 +680,17 @@ fn prepare_rustc(cx: &Context<'_, '_>, unit: &Unit) -> CargoResult<ProcessBuilde
671680
let tmp = cx.files().layout(unit.kind).prepare_tmp()?;
672681
base.env("CARGO_TARGET_TMPDIR", tmp.display().to_string());
673682
}
674-
675-
base.inherit_jobserver(&cx.jobserver);
676-
build_base_args(cx, &mut base, unit)?;
677-
build_deps_args(&mut base, cx, unit)?;
678-
add_cap_lints(cx.bcx, unit, &mut base);
679-
base.args(cx.bcx.rustflags_args(unit));
680-
if cx.bcx.config.cli_unstable().binary_dep_depinfo {
681-
base.arg("-Z").arg("binary-dep-depinfo");
683+
if cx.bcx.config.nightly_features_allowed {
684+
// This must come after `build_base_args` (which calls `add_path_args`) so that the `cwd`
685+
// is set correctly.
686+
base.env(
687+
"CARGO_RUSTC_CURRENT_DIR",
688+
base.get_cwd()
689+
.map(|c| c.display().to_string())
690+
.unwrap_or(String::new()),
691+
);
682692
}
693+
683694
Ok(base)
684695
}
685696

src/doc/src/reference/environment-variables.md

+1
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ corresponding environment variable is set to the empty string, `""`.
265265
where integration tests or benchmarks are free to put any data needed by
266266
the tests/benches. Cargo initially creates this directory but doesn't
267267
manage its content in any way, this is the responsibility of the test code.
268+
* `CARGO_RUSTC_CURRENT_DIR` --- This is a path that `rustc` is invoked from **(nightly only)**.
268269

269270
[Cargo target]: cargo-targets.md
270271
[binaries]: cargo-targets.md#binaries

tests/testsuite/build.rs

+205-7
Original file line numberDiff line numberDiff line change
@@ -1545,6 +1545,11 @@ fn crate_env_vars() {
15451545
15461546
// Verify CARGO_TARGET_TMPDIR isn't set for bins
15471547
assert!(option_env!("CARGO_TARGET_TMPDIR").is_none());
1548+
1549+
// Verify CARGO_RUSTC_CURRENT_DIR is set for examples
1550+
let workspace_dir = std::path::Path::new(option_env!("CARGO_RUSTC_CURRENT_DIR").expect("CARGO_RUSTC_CURRENT_DIR"));
1551+
let file_path = workspace_dir.join(file!());
1552+
assert!(file_path.exists(), "{}", file_path.display());
15481553
}
15491554
"#,
15501555
)
@@ -1581,14 +1586,26 @@ fn crate_env_vars() {
15811586
// Check that CARGO_TARGET_TMPDIR isn't set for lib code
15821587
assert!(option_env!("CARGO_TARGET_TMPDIR").is_none());
15831588
env::var("CARGO_TARGET_TMPDIR").unwrap_err();
1589+
1590+
// Verify CARGO_RUSTC_CURRENT_DIR is set for examples
1591+
let workspace_dir = std::path::Path::new(option_env!("CARGO_RUSTC_CURRENT_DIR").expect("CARGO_RUSTC_CURRENT_DIR"));
1592+
let file_path = workspace_dir.join(file!());
1593+
assert!(file_path.exists(), "{}", file_path.display());
15841594
}
15851595
15861596
#[test]
1587-
fn env() {
1597+
fn unit_env_cargo_target_tmpdir() {
15881598
// Check that CARGO_TARGET_TMPDIR isn't set for unit tests
15891599
assert!(option_env!("CARGO_TARGET_TMPDIR").is_none());
15901600
env::var("CARGO_TARGET_TMPDIR").unwrap_err();
15911601
}
1602+
1603+
#[test]
1604+
fn unit_env_cargo_rustc_current_dir() {
1605+
let workspace_dir = std::path::Path::new(option_env!("CARGO_RUSTC_CURRENT_DIR").expect("CARGO_RUSTC_CURRENT_DIR"));
1606+
let file_path = workspace_dir.join(file!());
1607+
assert!(file_path.exists(), "{}", file_path.display());
1608+
}
15921609
"#,
15931610
)
15941611
.file(
@@ -1605,16 +1622,28 @@ fn crate_env_vars() {
16051622
16061623
// Verify CARGO_TARGET_TMPDIR isn't set for examples
16071624
assert!(option_env!("CARGO_TARGET_TMPDIR").is_none());
1625+
1626+
// Verify CARGO_RUSTC_CURRENT_DIR is set for examples
1627+
let workspace_dir = std::path::Path::new(option_env!("CARGO_RUSTC_CURRENT_DIR").expect("CARGO_RUSTC_CURRENT_DIR"));
1628+
let file_path = workspace_dir.join(file!());
1629+
assert!(file_path.exists(), "{}", file_path.display());
16081630
}
16091631
"#,
16101632
)
16111633
.file(
16121634
"tests/env.rs",
16131635
r#"
16141636
#[test]
1615-
fn env() {
1637+
fn integration_env_cargo_target_tmpdir() {
16161638
foo::check_tmpdir(option_env!("CARGO_TARGET_TMPDIR"));
16171639
}
1640+
1641+
#[test]
1642+
fn integration_env_cargo_rustc_current_dir() {
1643+
let workspace_dir = std::path::Path::new(option_env!("CARGO_RUSTC_CURRENT_DIR").expect("CARGO_RUSTC_CURRENT_DIR"));
1644+
let file_path = workspace_dir.join(file!());
1645+
assert!(file_path.exists(), "{}", file_path.display());
1646+
}
16181647
"#,
16191648
);
16201649

@@ -1627,9 +1656,16 @@ fn crate_env_vars() {
16271656
use test::Bencher;
16281657
16291658
#[bench]
1630-
fn env(_: &mut Bencher) {
1659+
fn bench_env_cargo_target_tmpdir(_: &mut Bencher) {
16311660
foo::check_tmpdir(option_env!("CARGO_TARGET_TMPDIR"));
16321661
}
1662+
1663+
#[test]
1664+
fn bench_env_cargo_rustc_current_dir() {
1665+
let workspace_dir = std::path::Path::new(option_env!("CARGO_RUSTC_CURRENT_DIR").expect("CARGO_RUSTC_CURRENT_DIR"));
1666+
let file_path = workspace_dir.join(file!());
1667+
assert!(file_path.exists(), "{}", file_path.display());
1668+
}
16331669
"#,
16341670
)
16351671
.build()
@@ -1638,25 +1674,187 @@ fn crate_env_vars() {
16381674
};
16391675

16401676
println!("build");
1641-
p.cargo("build -v").run();
1677+
p.cargo("build -v")
1678+
.masquerade_as_nightly_cargo(&["CARGO_RUSTC_CURRENT_DIR"])
1679+
.run();
16421680

16431681
println!("bin");
16441682
p.process(&p.bin("foo-bar"))
16451683
.with_stdout("0-5-1 @ alpha.1 in [CWD]")
16461684
.run();
16471685

16481686
println!("example");
1649-
p.cargo("run --example ex-env-vars -v").run();
1687+
p.cargo("run --example ex-env-vars -v")
1688+
.masquerade_as_nightly_cargo(&["CARGO_RUSTC_CURRENT_DIR"])
1689+
.run();
16501690

16511691
println!("test");
1652-
p.cargo("test -v").run();
1692+
p.cargo("test -v")
1693+
.masquerade_as_nightly_cargo(&["CARGO_RUSTC_CURRENT_DIR"])
1694+
.run();
16531695

16541696
if is_nightly() {
16551697
println!("bench");
1656-
p.cargo("bench -v").run();
1698+
p.cargo("bench -v")
1699+
.masquerade_as_nightly_cargo(&["CARGO_RUSTC_CURRENT_DIR"])
1700+
.run();
16571701
}
16581702
}
16591703

1704+
#[cargo_test]
1705+
fn cargo_rustc_current_dir_foreign_workspace_dep() {
1706+
let foo = project()
1707+
.file(
1708+
"Cargo.toml",
1709+
r#"
1710+
[workspace]
1711+
1712+
[package]
1713+
name = "foo"
1714+
version = "0.0.1"
1715+
authors = []
1716+
1717+
[dependencies]
1718+
baz.path = "../baz"
1719+
baz_member.path = "../baz/baz_member"
1720+
"#,
1721+
)
1722+
.file("src/lib.rs", "")
1723+
.build();
1724+
let _baz = project()
1725+
.at("baz")
1726+
.file(
1727+
"Cargo.toml",
1728+
r#"
1729+
[workspace]
1730+
members = ["baz_member"]
1731+
1732+
[package]
1733+
name = "baz"
1734+
version = "0.1.0"
1735+
"#,
1736+
)
1737+
.file("src/lib.rs", "")
1738+
.file(
1739+
"tests/env.rs",
1740+
r#"
1741+
use std::path::Path;
1742+
1743+
#[test]
1744+
fn baz_env() {
1745+
let workspace_dir = Path::new(option_env!("CARGO_RUSTC_CURRENT_DIR").expect("CARGO_RUSTC_CURRENT_DIR"));
1746+
let manifest_dir = Path::new(option_env!("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR"));
1747+
let current_dir = std::env::current_dir().expect("current_dir");
1748+
let file_path = workspace_dir.join(file!());
1749+
assert!(file_path.exists(), "{}", file_path.display());
1750+
let workspace_dir = std::fs::canonicalize(current_dir.join(workspace_dir)).expect("CARGO_RUSTC_CURRENT_DIR");
1751+
let manifest_dir = std::fs::canonicalize(current_dir.join(manifest_dir)).expect("CARGO_MANIFEST_DIR");
1752+
assert_eq!(workspace_dir, manifest_dir);
1753+
}
1754+
"#,
1755+
)
1756+
.file(
1757+
"baz_member/Cargo.toml",
1758+
r#"
1759+
[package]
1760+
name = "baz_member"
1761+
version = "0.1.0"
1762+
authors = []
1763+
"#,
1764+
)
1765+
.file("baz_member/src/lib.rs", "")
1766+
.file(
1767+
"baz_member/tests/env.rs",
1768+
r#"
1769+
use std::path::Path;
1770+
1771+
#[test]
1772+
fn baz_member_env() {
1773+
let workspace_dir = Path::new(option_env!("CARGO_RUSTC_CURRENT_DIR").expect("CARGO_RUSTC_CURRENT_DIR"));
1774+
let file_path = workspace_dir.join(file!());
1775+
assert!(file_path.exists(), "{}", file_path.display());
1776+
}
1777+
"#,
1778+
)
1779+
.build();
1780+
1781+
// Verify it works from a different workspace
1782+
foo.cargo("test -p baz")
1783+
.masquerade_as_nightly_cargo(&["CARGO_RUSTC_CURRENT_DIR"])
1784+
.with_stdout_contains("running 1 test\ntest baz_env ... ok")
1785+
.run();
1786+
foo.cargo("test -p baz_member")
1787+
.masquerade_as_nightly_cargo(&["CARGO_RUSTC_CURRENT_DIR"])
1788+
.with_stdout_contains("running 1 test\ntest baz_member_env ... ok")
1789+
.run();
1790+
}
1791+
1792+
#[cargo_test]
1793+
fn cargo_rustc_current_dir_non_local_dep() {
1794+
Package::new("bar", "0.1.0")
1795+
.file(
1796+
"tests/bar_env.rs",
1797+
r#"
1798+
use std::path::Path;
1799+
1800+
#[test]
1801+
fn bar_env() {
1802+
let workspace_dir = Path::new(option_env!("CARGO_RUSTC_CURRENT_DIR").expect("CARGO_RUSTC_CURRENT_DIR"));
1803+
let manifest_dir = Path::new(option_env!("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR"));
1804+
let current_dir = std::env::current_dir().expect("current_dir");
1805+
let file_path = workspace_dir.join(file!());
1806+
assert!(file_path.exists(), "{}", file_path.display());
1807+
let workspace_dir = std::fs::canonicalize(current_dir.join(workspace_dir)).expect("CARGO_RUSTC_CURRENT_DIR");
1808+
let manifest_dir = std::fs::canonicalize(current_dir.join(manifest_dir)).expect("CARGO_MANIFEST_DIR");
1809+
assert_eq!(workspace_dir, manifest_dir);
1810+
}
1811+
"#,
1812+
)
1813+
.publish();
1814+
1815+
let p = project()
1816+
.file("src/lib.rs", "")
1817+
.file(
1818+
"Cargo.toml",
1819+
r#"
1820+
[package]
1821+
name = "foo"
1822+
version = "0.0.1"
1823+
1824+
[dependencies]
1825+
bar = "0.1.0"
1826+
"#,
1827+
)
1828+
.build();
1829+
1830+
p.cargo("test -p bar")
1831+
.masquerade_as_nightly_cargo(&["CARGO_RUSTC_CURRENT_DIR"])
1832+
.with_stdout_contains("running 1 test\ntest bar_env ... ok")
1833+
.run();
1834+
}
1835+
1836+
#[cargo_test]
1837+
fn cargo_rustc_current_dir_is_not_stable() {
1838+
if is_nightly() {
1839+
return;
1840+
}
1841+
let p = project()
1842+
.file(
1843+
"tests/env.rs",
1844+
r#"
1845+
use std::path::Path;
1846+
1847+
#[test]
1848+
fn env() {
1849+
assert_eq!(option_env!("CARGO_RUSTC_CURRENT_DIR"), None);
1850+
}
1851+
"#,
1852+
)
1853+
.build();
1854+
1855+
p.cargo("test").run();
1856+
}
1857+
16601858
#[cargo_test]
16611859
fn crate_authors_env_vars() {
16621860
let p = project()

0 commit comments

Comments
 (0)