Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unify build directories. #6668

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ log = "0.4.6"
libgit2-sys = "0.7.9"
num_cpus = "1.0"
opener = "0.3.0"
pathdiff = "0.1"
rustfix = "0.4.4"
same-file = "1"
semver = { version = "0.9.0", features = ["serde"] }
Expand Down
17 changes: 12 additions & 5 deletions src/cargo/core/compiler/build_context/target_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,22 @@ pub enum FileFlavor {
DebugInfo,
}

/// A description about the type of file generated by a Unit.
pub struct FileType {
/// The type of the file.
pub flavor: FileFlavor,
/// The suffix of the filename, such as ".dll", ".rlib", ".exe", etc.
/// This is an empty string for executables on Unix-like platforms.
suffix: String,
/// The prefix of the filename, such as "lib".
/// This is an empty string for things like executables.
prefix: String,
// wasm bin target will generate two files in deps such as
// "web-stuff.js" and "web_stuff.wasm". Note the different usages of
// "-" and "_". should_replace_hyphens is a flag to indicate that
// we need to convert the stem "web-stuff" to "web_stuff", so we
// won't miss "web_stuff.wasm".
/// Flag to convert hyphen to underscore.
///
/// wasm bin targets will generate two files in deps such as
/// "web-stuff.js" and "web_stuff.wasm". Note the different usages of "-"
/// and "_". This flag indicates that the stem "web-stuff" should be
/// converted to "web_stuff".
should_replace_hyphens: bool,
}

Expand Down
1 change: 1 addition & 0 deletions src/cargo/core/compiler/compilation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub struct Doctest {
/// A structure returning the result of a compilation.
pub struct Compilation<'cfg> {
/// An array of all tests created during this compilation.
/// (package, target_kind, test_name, path_to_test_exe)
pub tests: Vec<(Package, TargetKind, String, PathBuf)>,

/// An array of all binaries created.
Expand Down
157 changes: 76 additions & 81 deletions src/cargo/core/compiler/context/compilation_files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use lazycell::LazyCell;
use log::info;

use super::{BuildContext, Context, FileFlavor, Kind, Layout, Unit};
use crate::core::{TargetKind, Workspace};
use crate::core::{compiler::CompileMode, TargetKind, Workspace};
use crate::util::{self, CargoResult};

/// The `Metadata` is a hash used to make unique file names for each unit in a build.
Expand Down Expand Up @@ -144,11 +144,13 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> {
/// target.
pub fn out_dir(&self, unit: &Unit<'a>) -> PathBuf {
if unit.mode.is_doc() {
self.layout(unit.kind).root().parent().unwrap().join("doc")
self.layout(unit.kind).doc().to_path_buf()
} else if unit.target.is_custom_build() {
self.build_script_dir(unit)
} else if unit.target.is_example() {
self.layout(unit.kind).examples().to_path_buf()
} else if unit.mode == CompileMode::Test || unit.mode == CompileMode::Bench {
self.layout(unit.kind).legacy_deps().to_path_buf()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that tests & benches should be treated as "public" outputs: it's not uncommon to launch test executable manually, to attach gdb. Should we use the following layout?

target/release
  examples/
  tests/
  benches/
  bins & libs

?

} else {
self.deps_dir(unit).to_path_buf()
}
Expand All @@ -168,7 +170,7 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> {

/// Return the root of the build output tree
pub fn target_root(&self) -> &Path {
self.host.dest()
self.host.root()
}

pub fn host_deps(&self) -> &Path {
Expand Down Expand Up @@ -239,8 +241,8 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> {
/// (eg a dependent lib)
fn link_stem(&self, unit: &Unit<'a>) -> Option<(PathBuf, String)> {
let out_dir = self.out_dir(unit);
let bin_stem = self.bin_stem(unit);
let file_stem = self.file_stem(unit);
let bin_stem = self.bin_stem(unit); // Stem without metadata.
let file_stem = self.file_stem(unit); // Stem with metadata.

// We currently only lift files up from the `deps` directory. If
// it was compiled into something like `example/` or `doc/` then
Expand All @@ -249,7 +251,7 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> {
// Don't lift up library dependencies
if unit.target.is_bin() || self.roots.contains(unit) {
Some((
out_dir.parent().unwrap().to_owned(),
self.layout(unit.kind).dest().to_path_buf(),
if unit.mode.is_any_test() {
file_stem
} else {
Expand Down Expand Up @@ -284,85 +286,78 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> {

let mut ret = Vec::new();
let mut unsupported = Vec::new();
{
if unit.mode.is_check() {
// This may be confusing. rustc outputs a file named `lib*.rmeta`
// for both libraries and binaries.
let path = out_dir.join(format!("lib{}.rmeta", file_stem));
ret.push(OutputFile {
path,
hardlink: None,
export_path: None,
flavor: FileFlavor::Linkable,
});
} else {
let mut add = |crate_type: &str, flavor: FileFlavor| -> CargoResult<()> {
let crate_type = if crate_type == "lib" {
"rlib"
} else {
crate_type
};
let file_types = info.file_types(
crate_type,
flavor,
unit.target.kind(),
bcx.target_triple(),
)?;

match file_types {
Some(types) => {
for file_type in types {
let path = out_dir.join(file_type.filename(&file_stem));
let hardlink = link_stem
.as_ref()
.map(|&(ref ld, ref ls)| ld.join(file_type.filename(ls)));
let export_path = if unit.target.is_custom_build() {
None
} else {
self.export_dir.as_ref().and_then(|export_dir| {
hardlink.as_ref().and_then(|hardlink| {
Some(export_dir.join(hardlink.file_name().unwrap()))
})
if unit.mode.is_check() {
// This may be confusing. rustc outputs a file named `lib*.rmeta`
// for both libraries and binaries.
let path = out_dir.join(format!("lib{}.rmeta", file_stem));
ret.push(OutputFile {
path,
hardlink: None,
export_path: None,
flavor: FileFlavor::Linkable,
});
} else {
let mut add = |crate_type: &str, flavor: FileFlavor| -> CargoResult<()> {
let crate_type = if crate_type == "lib" {
"rlib"
} else {
crate_type
};
let file_types =
info.file_types(crate_type, flavor, unit.target.kind(), bcx.target_triple())?;

match file_types {
Some(types) => {
for file_type in types {
let path = out_dir.join(file_type.filename(&file_stem));
let hardlink = link_stem
.as_ref()
.map(|&(ref ld, ref ls)| ld.join(file_type.filename(ls)));
let export_path = if unit.target.is_custom_build() {
None
} else {
self.export_dir.as_ref().and_then(|export_dir| {
hardlink.as_ref().and_then(|hardlink| {
Some(export_dir.join(hardlink.file_name().unwrap()))
})
};
ret.push(OutputFile {
path,
hardlink,
export_path,
flavor: file_type.flavor,
});
}
}
// not supported, don't worry about it
None => {
unsupported.push(crate_type.to_string());
})
};
ret.push(OutputFile {
path,
hardlink,
export_path,
flavor: file_type.flavor,
});
}
}
Ok(())
};
//info!("{:?}", unit);
match *unit.target.kind() {
TargetKind::Bin
| TargetKind::CustomBuild
| TargetKind::ExampleBin
| TargetKind::Bench
| TargetKind::Test => {
add("bin", FileFlavor::Normal)?;
}
TargetKind::Lib(..) | TargetKind::ExampleLib(..) if unit.mode.is_any_test() => {
add("bin", FileFlavor::Normal)?;
// not supported, don't worry about it
None => {
unsupported.push(crate_type.to_string());
}
TargetKind::ExampleLib(ref kinds) | TargetKind::Lib(ref kinds) => {
for kind in kinds {
add(
kind.crate_type(),
if kind.linkable() {
FileFlavor::Linkable
} else {
FileFlavor::Normal
},
)?;
}
}
Ok(())
};
match *unit.target.kind() {
TargetKind::Bin
| TargetKind::CustomBuild
| TargetKind::ExampleBin
| TargetKind::Bench
| TargetKind::Test => {
add("bin", FileFlavor::Normal)?;
}
TargetKind::Lib(..) | TargetKind::ExampleLib(..) if unit.mode.is_any_test() => {
add("bin", FileFlavor::Normal)?;
}
TargetKind::ExampleLib(ref kinds) | TargetKind::Lib(ref kinds) => {
for kind in kinds {
add(
kind.crate_type(),
if kind.linkable() {
FileFlavor::Linkable
} else {
FileFlavor::Normal
},
)?;
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/cargo/core/compiler/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {

let files = self.files.as_ref().unwrap();
let layout = files.target.as_ref().unwrap_or(&files.host);
self.compilation.root_output = layout.dest().to_path_buf();
self.compilation.root_output = layout.root().to_path_buf();
self.compilation.deps_output = layout.deps().to_path_buf();
Ok(())
}
Expand Down
Loading