Skip to content

Commit bacc5bb

Browse files
authored
Merge pull request #20920 from ShoyuVanilla/target-dirs
fix: Resolve `target-dir` more precisely
2 parents fca718c + b50af95 commit bacc5bb

File tree

12 files changed

+140
-136
lines changed

12 files changed

+140
-136
lines changed

crates/project-model/src/build_dependencies.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ impl WorkspaceBuildScripts {
8686
config,
8787
&allowed_features,
8888
workspace.manifest_path(),
89+
workspace.target_directory().as_ref(),
8990
current_dir,
9091
sysroot,
9192
toolchain,
@@ -106,8 +107,9 @@ impl WorkspaceBuildScripts {
106107
let (_guard, cmd) = Self::build_command(
107108
config,
108109
&Default::default(),
109-
// This is not gonna be used anyways, so just construct a dummy here
110+
// These are not gonna be used anyways, so just construct a dummy here
110111
&ManifestPath::try_from(working_directory.clone()).unwrap(),
112+
working_directory.as_ref(),
111113
working_directory,
112114
&Sysroot::empty(),
113115
None,
@@ -430,6 +432,7 @@ impl WorkspaceBuildScripts {
430432
config: &CargoConfig,
431433
allowed_features: &FxHashSet<String>,
432434
manifest_path: &ManifestPath,
435+
target_dir: &Utf8Path,
433436
current_dir: &AbsPath,
434437
sysroot: &Sysroot,
435438
toolchain: Option<&semver::Version>,
@@ -450,8 +453,9 @@ impl WorkspaceBuildScripts {
450453
cmd.arg("--manifest-path");
451454
cmd.arg(manifest_path);
452455

453-
if let Some(target_dir) = &config.target_dir {
454-
cmd.arg("--target-dir").arg(target_dir);
456+
if let Some(target_dir) = config.target_dir_config.target_dir(Some(target_dir)) {
457+
cmd.arg("--target-dir");
458+
cmd.arg(target_dir.as_ref());
455459
}
456460

457461
if let Some(target) = &config.target {

crates/project-model/src/cargo_workspace.rs

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
//! See [`CargoWorkspace`].
22
3-
use std::ops;
4-
use std::str::from_utf8;
3+
use std::{borrow::Cow, ops, str::from_utf8};
54

65
use anyhow::Context;
76
use base_db::Env;
@@ -95,6 +94,29 @@ impl Default for CargoFeatures {
9594
}
9695
}
9796

97+
#[derive(Clone, Debug, Default, PartialEq, Eq)]
98+
pub enum TargetDirectoryConfig {
99+
#[default]
100+
None,
101+
UseSubdirectory,
102+
Directory(Utf8PathBuf),
103+
}
104+
105+
impl TargetDirectoryConfig {
106+
pub fn target_dir<'a>(
107+
&'a self,
108+
ws_target_dir: Option<&'a Utf8Path>,
109+
) -> Option<Cow<'a, Utf8Path>> {
110+
match self {
111+
TargetDirectoryConfig::None => None,
112+
TargetDirectoryConfig::UseSubdirectory => {
113+
Some(Cow::Owned(ws_target_dir?.join("rust-analyzer")))
114+
}
115+
TargetDirectoryConfig::Directory(dir) => Some(Cow::Borrowed(dir)),
116+
}
117+
}
118+
}
119+
98120
#[derive(Default, Clone, Debug, PartialEq, Eq)]
99121
pub struct CargoConfig {
100122
/// Whether to pass `--all-targets` to cargo invocations.
@@ -121,7 +143,7 @@ pub struct CargoConfig {
121143
pub extra_env: FxHashMap<String, Option<String>>,
122144
pub invocation_strategy: InvocationStrategy,
123145
/// Optional path to use instead of `target` when building
124-
pub target_dir: Option<Utf8PathBuf>,
146+
pub target_dir_config: TargetDirectoryConfig,
125147
/// Gate `#[test]` behind `#[cfg(test)]`
126148
pub set_test: bool,
127149
/// Load the project without any dependencies
@@ -715,21 +737,15 @@ impl FetchMetadata {
715737
}
716738
}
717739

718-
pub(crate) fn no_deps_metadata(&self) -> Option<&cargo_metadata::Metadata> {
719-
self.no_deps_result.as_ref().ok()
720-
}
721-
722740
/// Executes the metadata-fetching command.
723741
///
724742
/// A successful result may still contain a metadata error if the full fetch failed,
725743
/// but the fallback `--no-deps` pre-fetch succeeded during command construction.
726744
pub(crate) fn exec(
727745
self,
728-
target_dir: &Utf8Path,
729746
locked: bool,
730747
progress: &dyn Fn(String),
731748
) -> anyhow::Result<(cargo_metadata::Metadata, Option<anyhow::Error>)> {
732-
_ = target_dir;
733749
let Self {
734750
mut command,
735751
manifest_path: _,

crates/project-model/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ pub use crate::{
6262
build_dependencies::{ProcMacroDylibPath, WorkspaceBuildScripts},
6363
cargo_workspace::{
6464
CargoConfig, CargoFeatures, CargoMetadataConfig, CargoWorkspace, Package, PackageData,
65-
PackageDependency, RustLibSource, Target, TargetData, TargetKind,
65+
PackageDependency, RustLibSource, Target, TargetData, TargetDirectoryConfig, TargetKind,
6666
},
6767
manifest_path::ManifestPath,
6868
project_json::{ProjectJson, ProjectJsonData},

crates/project-model/src/sysroot.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::{env, fs, ops::Not, path::Path, process::Command};
99

1010
use anyhow::{Result, format_err};
1111
use itertools::Itertools;
12-
use paths::{AbsPath, AbsPathBuf, Utf8Path, Utf8PathBuf};
12+
use paths::{AbsPath, AbsPathBuf, Utf8PathBuf};
1313
use rustc_hash::FxHashMap;
1414
use stdx::format_to;
1515
use toolchain::{Tool, probe_for_binary};
@@ -219,7 +219,6 @@ impl Sysroot {
219219
&self,
220220
sysroot_source_config: &RustSourceWorkspaceConfig,
221221
no_deps: bool,
222-
target_dir: &Utf8Path,
223222
progress: &dyn Fn(String),
224223
) -> Option<RustLibSrcWorkspace> {
225224
assert!(matches!(self.workspace, RustLibSrcWorkspace::Empty), "workspace already loaded");
@@ -233,7 +232,6 @@ impl Sysroot {
233232
match self.load_library_via_cargo(
234233
&library_manifest,
235234
src_root,
236-
target_dir,
237235
cargo_config,
238236
no_deps,
239237
progress,
@@ -328,7 +326,6 @@ impl Sysroot {
328326
&self,
329327
library_manifest: &ManifestPath,
330328
current_dir: &AbsPath,
331-
target_dir: &Utf8Path,
332329
cargo_config: &CargoMetadataConfig,
333330
no_deps: bool,
334331
progress: &dyn Fn(String),
@@ -345,7 +342,7 @@ impl Sysroot {
345342
let locked = true;
346343
let (mut res, err) =
347344
FetchMetadata::new(library_manifest, current_dir, &cargo_config, self, no_deps)
348-
.exec(target_dir, locked, progress)?;
345+
.exec(locked, progress)?;
349346

350347
// Patch out `rustc-std-workspace-*` crates to point to the real crates.
351348
// This is done prior to `CrateGraph` construction to prevent de-duplication logic from failing.

crates/project-model/src/tests.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -238,12 +238,8 @@ fn smoke_test_real_sysroot_cargo() {
238238
);
239239
let cwd = AbsPathBuf::assert_utf8(temp_dir().join("smoke_test_real_sysroot_cargo"));
240240
std::fs::create_dir_all(&cwd).unwrap();
241-
let loaded_sysroot = sysroot.load_workspace(
242-
&RustSourceWorkspaceConfig::default_cargo(),
243-
false,
244-
&Utf8PathBuf::default(),
245-
&|_| (),
246-
);
241+
let loaded_sysroot =
242+
sysroot.load_workspace(&RustSourceWorkspaceConfig::default_cargo(), false, &|_| ());
247243
if let Some(loaded_sysroot) = loaded_sysroot {
248244
sysroot.set_workspace(loaded_sysroot);
249245
}

crates/project-model/src/workspace.rs

Lines changed: 12 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use paths::{AbsPath, AbsPathBuf, Utf8PathBuf};
1616
use rustc_hash::{FxHashMap, FxHashSet};
1717
use semver::Version;
1818
use span::{Edition, FileId};
19-
use toolchain::{NO_RUSTUP_AUTO_INSTALL_ENV, Tool};
19+
use toolchain::Tool;
2020
use tracing::instrument;
2121
use tracing::{debug, error, info};
2222
use triomphe::Arc;
@@ -295,11 +295,6 @@ impl ProjectWorkspace {
295295
&sysroot,
296296
*no_deps,
297297
);
298-
let target_dir = config
299-
.target_dir
300-
.clone()
301-
.or_else(|| fetch_metadata.no_deps_metadata().map(|m| m.target_directory.clone()))
302-
.unwrap_or_else(|| workspace_dir.join("target").into());
303298

304299
// We spawn a bunch of processes to query various information about the workspace's
305300
// toolchain and sysroot
@@ -345,7 +340,7 @@ impl ProjectWorkspace {
345340
},
346341
&sysroot,
347342
*no_deps,
348-
).exec(&target_dir, true, progress) {
343+
).exec(true, progress) {
349344
Ok((meta, _error)) => {
350345
let workspace = CargoWorkspace::new(
351346
meta,
@@ -374,7 +369,7 @@ impl ProjectWorkspace {
374369
})
375370
});
376371

377-
let cargo_metadata = s.spawn(|| fetch_metadata.exec(&target_dir, false, progress));
372+
let cargo_metadata = s.spawn(|| fetch_metadata.exec(false, progress));
378373
let loaded_sysroot = s.spawn(|| {
379374
sysroot.load_workspace(
380375
&RustSourceWorkspaceConfig::CargoMetadata(sysroot_metadata_config(
@@ -383,7 +378,6 @@ impl ProjectWorkspace {
383378
toolchain.clone(),
384379
)),
385380
config.no_deps,
386-
&target_dir,
387381
progress,
388382
)
389383
});
@@ -463,12 +457,6 @@ impl ProjectWorkspace {
463457
let targets = target_tuple::get(query_config, config.target.as_deref(), &config.extra_env)
464458
.unwrap_or_default();
465459
let toolchain = version::get(query_config, &config.extra_env).ok().flatten();
466-
let project_root = project_json.project_root();
467-
let target_dir = config
468-
.target_dir
469-
.clone()
470-
.or_else(|| cargo_target_dir(project_json.manifest()?, &config.extra_env, &sysroot))
471-
.unwrap_or_else(|| project_root.join("target").into());
472460

473461
// We spawn a bunch of processes to query various information about the workspace's
474462
// toolchain and sysroot
@@ -486,7 +474,6 @@ impl ProjectWorkspace {
486474
sysroot.load_workspace(
487475
&RustSourceWorkspaceConfig::Json(*sysroot_project),
488476
config.no_deps,
489-
&target_dir,
490477
progress,
491478
)
492479
} else {
@@ -497,7 +484,6 @@ impl ProjectWorkspace {
497484
toolchain.clone(),
498485
)),
499486
config.no_deps,
500-
&target_dir,
501487
progress,
502488
)
503489
}
@@ -545,11 +531,6 @@ impl ProjectWorkspace {
545531
.unwrap_or_default();
546532
let rustc_cfg = rustc_cfg::get(query_config, None, &config.extra_env);
547533
let target_data = target_data::get(query_config, None, &config.extra_env);
548-
let target_dir = config
549-
.target_dir
550-
.clone()
551-
.or_else(|| cargo_target_dir(detached_file, &config.extra_env, &sysroot))
552-
.unwrap_or_else(|| dir.join("target").into());
553534

554535
let loaded_sysroot = sysroot.load_workspace(
555536
&RustSourceWorkspaceConfig::CargoMetadata(sysroot_metadata_config(
@@ -558,7 +539,6 @@ impl ProjectWorkspace {
558539
toolchain.clone(),
559540
)),
560541
config.no_deps,
561-
&target_dir,
562542
&|_| (),
563543
);
564544
if let Some(loaded_sysroot) = loaded_sysroot {
@@ -579,21 +559,15 @@ impl ProjectWorkspace {
579559
&sysroot,
580560
config.no_deps,
581561
);
582-
let target_dir = config
583-
.target_dir
584-
.clone()
585-
.or_else(|| fetch_metadata.no_deps_metadata().map(|m| m.target_directory.clone()))
586-
.unwrap_or_else(|| dir.join("target").into());
587-
let cargo_script =
588-
fetch_metadata.exec(&target_dir, false, &|_| ()).ok().map(|(ws, error)| {
589-
let cargo_config_extra_env =
590-
cargo_config_env(detached_file, &config_file, &config.extra_env);
591-
(
592-
CargoWorkspace::new(ws, detached_file.clone(), cargo_config_extra_env, false),
593-
WorkspaceBuildScripts::default(),
594-
error.map(Arc::new),
595-
)
596-
});
562+
let cargo_script = fetch_metadata.exec(false, &|_| ()).ok().map(|(ws, error)| {
563+
let cargo_config_extra_env =
564+
cargo_config_env(detached_file, &config_file, &config.extra_env);
565+
(
566+
CargoWorkspace::new(ws, detached_file.clone(), cargo_config_extra_env, false),
567+
WorkspaceBuildScripts::default(),
568+
error.map(Arc::new),
569+
)
570+
});
597571

598572
Ok(ProjectWorkspace {
599573
kind: ProjectWorkspaceKind::DetachedFile {
@@ -1902,25 +1876,3 @@ fn sysroot_metadata_config(
19021876
kind: "sysroot",
19031877
}
19041878
}
1905-
1906-
fn cargo_target_dir(
1907-
manifest: &ManifestPath,
1908-
extra_env: &FxHashMap<String, Option<String>>,
1909-
sysroot: &Sysroot,
1910-
) -> Option<Utf8PathBuf> {
1911-
let cargo = sysroot.tool(Tool::Cargo, manifest.parent(), extra_env);
1912-
let mut meta = cargo_metadata::MetadataCommand::new();
1913-
meta.env(NO_RUSTUP_AUTO_INSTALL_ENV.0, NO_RUSTUP_AUTO_INSTALL_ENV.1);
1914-
meta.cargo_path(cargo.get_program());
1915-
meta.manifest_path(manifest);
1916-
// `--no-deps` doesn't (over)write lockfiles as it doesn't do any package resolve.
1917-
// So we can use it to get `target_directory` before copying lockfiles
1918-
meta.no_deps();
1919-
let mut other_options = vec![];
1920-
if manifest.is_rust_manifest() {
1921-
meta.env("RUSTC_BOOTSTRAP", "1");
1922-
other_options.push("-Zscript".to_owned());
1923-
}
1924-
meta.other_options(other_options);
1925-
meta.exec().map(|m| m.target_directory).ok()
1926-
}

crates/rust-analyzer/src/cli/rustc_tests.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use hir::{ChangeWithProcMacros, Crate};
99
use ide::{AnalysisHost, DiagnosticCode, DiagnosticsConfig};
1010
use ide_db::base_db;
1111
use itertools::Either;
12-
use paths::Utf8PathBuf;
1312
use profile::StopWatch;
1413
use project_model::toolchain_info::{QueryConfig, target_data};
1514
use project_model::{
@@ -75,12 +74,8 @@ impl Tester {
7574
};
7675

7776
let mut sysroot = Sysroot::discover(tmp_file.parent().unwrap(), &cargo_config.extra_env);
78-
let loaded_sysroot = sysroot.load_workspace(
79-
&RustSourceWorkspaceConfig::default_cargo(),
80-
false,
81-
&Utf8PathBuf::default(),
82-
&|_| (),
83-
);
77+
let loaded_sysroot =
78+
sysroot.load_workspace(&RustSourceWorkspaceConfig::default_cargo(), false, &|_| ());
8479
if let Some(loaded_sysroot) = loaded_sysroot {
8580
sysroot.set_workspace(loaded_sysroot);
8681
}

0 commit comments

Comments
 (0)