Skip to content

WIP: Implementation for multiple build scripts #15704

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

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
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
65 changes: 39 additions & 26 deletions src/cargo/core/compiler/build_runner/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,23 +248,25 @@ impl<'a, 'gctx> BuildRunner<'a, 'gctx> {
args.extend(compiler::features_args(unit));
args.extend(compiler::check_cfg_args(unit));

let script_meta = self.find_build_script_metadata(unit);
if let Some(meta) = script_meta {
if let Some(output) = self.build_script_outputs.lock().unwrap().get(meta) {
for cfg in &output.cfgs {
args.push("--cfg".into());
args.push(cfg.into());
}
let script_metas = self.find_build_script_metadatas(unit);
if let Some(meta_vec) = script_metas.clone() {
for meta in meta_vec {
if let Some(output) = self.build_script_outputs.lock().unwrap().get(meta) {
for cfg in &output.cfgs {
args.push("--cfg".into());
args.push(cfg.into());
}

for check_cfg in &output.check_cfgs {
args.push("--check-cfg".into());
args.push(check_cfg.into());
}
for check_cfg in &output.check_cfgs {
args.push("--check-cfg".into());
args.push(check_cfg.into());
}

for (lt, arg) in &output.linker_args {
if lt.applies_to(&unit.target, unit.mode) {
args.push("-C".into());
args.push(format!("link-arg={}", arg).into());
for (lt, arg) in &output.linker_args {
if lt.applies_to(&unit.target, unit.mode) {
args.push("-C".into());
args.push(format!("link-arg={}", arg).into());
}
}
}
}
Expand All @@ -285,7 +287,7 @@ impl<'a, 'gctx> BuildRunner<'a, 'gctx> {
args,
unstable_opts,
linker: self.compilation.target_linker(unit.kind).clone(),
script_meta,
script_metas,
env: artifact::get_env(&self, self.unit_deps(unit))?,
});
}
Expand Down Expand Up @@ -420,29 +422,40 @@ impl<'a, 'gctx> BuildRunner<'a, 'gctx> {
&self.bcx.unit_graph[unit]
}

/// Returns the `RunCustomBuild` Unit associated with the given Unit.
/// Returns the `RunCustomBuild` Units associated with the given Unit.
///
/// If the package does not have a build script, this returns None.
pub fn find_build_script_unit(&self, unit: &Unit) -> Option<Unit> {
pub fn find_build_script_units(&self, unit: &Unit) -> Option<Vec<Unit>> {
if unit.mode.is_run_custom_build() {
return Some(unit.clone());
return Some(vec![unit.clone()]);
}
self.bcx.unit_graph[unit]

let build_script_units: Vec<Unit> = self.bcx.unit_graph[unit]
.iter()
.find(|unit_dep| {
.filter(|unit_dep| {
unit_dep.unit.mode.is_run_custom_build()
&& unit_dep.unit.pkg.package_id() == unit.pkg.package_id()
})
.map(|unit_dep| unit_dep.unit.clone())
.collect();
if build_script_units.is_empty() {
None
} else {
Some(build_script_units)
}
}
Comment on lines +428 to 446
Copy link
Contributor

Choose a reason for hiding this comment

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

What order is this returning units? We should do it in a deterministic order, preferably one controlled by the user.

Copy link
Contributor

Choose a reason for hiding this comment

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

If this commit is just about changing types, we can always add this in a later commit


/// Returns the metadata hash for the `RunCustomBuild` Unit associated with
/// the given unit.
///
/// If the package does not have a build script, this returns None.
pub fn find_build_script_metadata(&self, unit: &Unit) -> Option<UnitHash> {
let script_unit = self.find_build_script_unit(unit)?;
Some(self.get_run_build_script_metadata(&script_unit))
pub fn find_build_script_metadatas(&self, unit: &Unit) -> Option<Vec<UnitHash>> {
self.find_build_script_units(unit).map(|units| {
units
.iter()
.map(|u| self.get_run_build_script_metadata(u))
.collect()
})
}

/// Returns the metadata hash for a `RunCustomBuild` unit.
Expand Down Expand Up @@ -480,11 +493,11 @@ impl<'a, 'gctx> BuildRunner<'a, 'gctx> {
/// Returns a [`UnitOutput`] which represents some information about the
/// output of a unit.
pub fn unit_output(&self, unit: &Unit, path: &Path) -> UnitOutput {
let script_meta = self.find_build_script_metadata(unit);
let script_metas = self.find_build_script_metadatas(unit);
UnitOutput {
unit: unit.clone(),
path: path.to_path_buf(),
script_meta,
script_metas,
}
}

Expand Down
26 changes: 14 additions & 12 deletions src/cargo/core/compiler/compilation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ pub struct Doctest {
/// The script metadata, if this unit's package has a build script.
///
/// This is used for indexing [`Compilation::extra_env`].
pub script_meta: Option<UnitHash>,
pub script_metas: Option<Vec<UnitHash>>,

/// Environment variables to set in the rustdoc process.
pub env: HashMap<String, OsString>,
Expand All @@ -61,7 +61,7 @@ pub struct UnitOutput {
/// The script metadata, if this unit's package has a build script.
///
/// This is used for indexing [`Compilation::extra_env`].
pub script_meta: Option<UnitHash>,
pub script_metas: Option<Vec<UnitHash>>,
}

/// A structure returning the result of a compilation.
Expand Down Expand Up @@ -197,14 +197,14 @@ impl<'gctx> Compilation<'gctx> {
pub fn rustdoc_process(
&self,
unit: &Unit,
script_meta: Option<UnitHash>,
script_metas: Option<&Vec<UnitHash>>,
) -> CargoResult<ProcessBuilder> {
let mut rustdoc = ProcessBuilder::new(&*self.gctx.rustdoc()?);
if self.gctx.extra_verbose() {
rustdoc.display_env_vars();
}
let cmd = fill_rustc_tool_env(rustdoc, unit);
let mut cmd = self.fill_env(cmd, &unit.pkg, script_meta, unit.kind, ToolKind::Rustdoc)?;
let mut cmd = self.fill_env(cmd, &unit.pkg, script_metas, unit.kind, ToolKind::Rustdoc)?;
cmd.retry_with_argfile(true);
unit.target.edition().cmd_edition_arg(&mut cmd);

Expand Down Expand Up @@ -248,15 +248,15 @@ impl<'gctx> Compilation<'gctx> {
/// target platform. This is typically used for `cargo run` and `cargo
/// test`.
///
/// `script_meta` is the metadata for the `RunCustomBuild` unit that this
/// `script_metas` is the metadata for the `RunCustomBuild` unit that this
/// unit used for its build script. Use `None` if the package did not have
/// a build script.
pub fn target_process<T: AsRef<OsStr>>(
&self,
cmd: T,
kind: CompileKind,
pkg: &Package,
script_meta: Option<UnitHash>,
script_metas: Option<&Vec<UnitHash>>,
) -> CargoResult<ProcessBuilder> {
let builder = if let Some((runner, args)) = self.target_runner(kind) {
let mut builder = ProcessBuilder::new(runner);
Expand All @@ -267,7 +267,7 @@ impl<'gctx> Compilation<'gctx> {
ProcessBuilder::new(cmd)
};
let tool_kind = ToolKind::TargetProcess;
let mut builder = self.fill_env(builder, pkg, script_meta, kind, tool_kind)?;
let mut builder = self.fill_env(builder, pkg, script_metas, kind, tool_kind)?;

if let Some(client) = self.gctx.jobserver_from_env() {
builder.inherit_jobserver(client);
Expand All @@ -285,7 +285,7 @@ impl<'gctx> Compilation<'gctx> {
&self,
mut cmd: ProcessBuilder,
pkg: &Package,
script_meta: Option<UnitHash>,
script_metas: Option<&Vec<UnitHash>>,
kind: CompileKind,
tool_kind: ToolKind,
) -> CargoResult<ProcessBuilder> {
Expand Down Expand Up @@ -343,10 +343,12 @@ impl<'gctx> Compilation<'gctx> {
let search_path = paths::join_paths(&search_path, paths::dylib_path_envvar())?;

cmd.env(paths::dylib_path_envvar(), &search_path);
if let Some(meta) = script_meta {
if let Some(env) = self.extra_env.get(&meta) {
for (k, v) in env {
cmd.env(k, v);
if let Some(meta_vec) = script_metas {
for meta in meta_vec {
if let Some(env) = self.extra_env.get(meta) {
for (k, v) in env {
cmd.env(k, v);
}
}
}
}
Expand Down
8 changes: 5 additions & 3 deletions src/cargo/core/compiler/custom_build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1283,10 +1283,12 @@ pub fn build_map(build_runner: &mut BuildRunner<'_, '_>) -> CargoResult<()> {

// If a package has a build script, add itself as something to inspect for linking.
if !unit.target.is_custom_build() && unit.pkg.has_custom_build() {
let script_meta = build_runner
.find_build_script_metadata(unit)
let script_metas = build_runner
.find_build_script_metadatas(unit)
.expect("has_custom_build should have RunCustomBuild");
add_to_link(&mut ret, unit.pkg.package_id(), script_meta);
for script_meta in script_metas {
add_to_link(&mut ret, unit.pkg.package_id(), script_meta);
}
}

if unit.mode.is_run_custom_build() {
Expand Down
40 changes: 21 additions & 19 deletions src/cargo/core/compiler/job_queue/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -981,28 +981,30 @@ impl<'gctx> DrainState<'gctx> {
show_warnings: bool,
) -> CargoResult<()> {
let outputs = build_runner.build_script_outputs.lock().unwrap();
let Some(metadata) = build_runner.find_build_script_metadata(unit) else {
let Some(metadata_vec) = build_runner.find_build_script_metadatas(unit) else {
return Ok(());
};
let bcx = &mut build_runner.bcx;
if let Some(output) = outputs.get(metadata) {
if !output.log_messages.is_empty()
&& (show_warnings
|| output
.log_messages
.iter()
.any(|(severity, _)| *severity == Severity::Error))
{
let msg_with_package =
|msg: &str| format!("{}@{}: {}", unit.pkg.name(), unit.pkg.version(), msg);

for (severity, message) in output.log_messages.iter() {
match severity {
Severity::Error => {
bcx.gctx.shell().error(msg_with_package(message))?;
}
Severity::Warning => {
bcx.gctx.shell().warn(msg_with_package(message))?;
for metadata in metadata_vec {
if let Some(output) = outputs.get(metadata) {
if !output.log_messages.is_empty()
&& (show_warnings
|| output
.log_messages
.iter()
.any(|(severity, _)| *severity == Severity::Error))
{
let msg_with_package =
|msg: &str| format!("{}@{}: {}", unit.pkg.name(), unit.pkg.version(), msg);

for (severity, message) in output.log_messages.iter() {
match severity {
Severity::Error => {
bcx.gctx.shell().error(msg_with_package(message))?;
}
Severity::Warning => {
bcx.gctx.shell().warn(msg_with_package(message))?;
}
}
}
}
Expand Down
32 changes: 17 additions & 15 deletions src/cargo/core/compiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ fn rustc(
.unwrap_or_else(|| build_runner.bcx.gctx.cwd())
.to_path_buf();
let fingerprint_dir = build_runner.files().fingerprint_dir(unit);
let script_metadata = build_runner.find_build_script_metadata(unit);
let script_metadatas = build_runner.find_build_script_metadatas(unit);
let is_local = unit.is_local();
let artifact = unit.artifact;
let sbom_files = build_runner.sbom_output_files(unit)?;
Expand Down Expand Up @@ -371,7 +371,7 @@ fn rustc(
)?;
add_plugin_deps(&mut rustc, &script_outputs, &build_scripts, &root_output)?;
}
add_custom_flags(&mut rustc, &script_outputs, script_metadata)?;
add_custom_flags(&mut rustc, &script_outputs, script_metadatas)?;
}

for output in outputs.iter() {
Expand Down Expand Up @@ -920,7 +920,7 @@ fn rustdoc(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> CargoResult<W
let rustdoc_depinfo_enabled = build_runner.bcx.gctx.cli_unstable().rustdoc_depinfo;

let mut output_options = OutputOptions::new(build_runner, unit);
let script_metadata = build_runner.find_build_script_metadata(unit);
let script_metadatas = build_runner.find_build_script_metadatas(unit);
let scrape_outputs = if should_include_scrape_units(build_runner.bcx, unit) {
Some(
build_runner
Expand Down Expand Up @@ -960,7 +960,7 @@ fn rustdoc(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> CargoResult<W
add_custom_flags(
&mut rustdoc,
&build_script_outputs.lock().unwrap(),
script_metadata,
script_metadatas,
)?;

// Add the output of scraped examples to the rustdoc command.
Expand Down Expand Up @@ -1686,18 +1686,20 @@ fn build_deps_args(
fn add_custom_flags(
cmd: &mut ProcessBuilder,
build_script_outputs: &BuildScriptOutputs,
metadata: Option<UnitHash>,
metadata_vec: Option<Vec<UnitHash>>,
) -> CargoResult<()> {
if let Some(metadata) = metadata {
if let Some(output) = build_script_outputs.get(metadata) {
for cfg in output.cfgs.iter() {
cmd.arg("--cfg").arg(cfg);
}
for check_cfg in &output.check_cfgs {
cmd.arg("--check-cfg").arg(check_cfg);
}
for (name, value) in output.env.iter() {
cmd.env(name, value);
if let Some(metadata_vec) = metadata_vec {
for metadata in metadata_vec {
if let Some(output) = build_script_outputs.get(metadata) {
for cfg in output.cfgs.iter() {
cmd.arg("--cfg").arg(cfg);
}
for check_cfg in &output.check_cfgs {
cmd.arg("--check-cfg").arg(check_cfg);
}
for (name, value) in output.env.iter() {
cmd.env(name, value);
}
}
}
}
Expand Down
26 changes: 14 additions & 12 deletions src/cargo/core/compiler/output_depinfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,18 +75,20 @@ fn add_deps_for_unit(
}

// Add rerun-if-changed dependencies
if let Some(metadata) = build_runner.find_build_script_metadata(unit) {
if let Some(output) = build_runner
.build_script_outputs
.lock()
.unwrap()
.get(metadata)
{
for path in &output.rerun_if_changed {
// The paths we have saved from the unit are of arbitrary relativeness and may be
// relative to the crate root of the dependency.
let path = unit.pkg.root().join(path);
deps.insert(path);
if let Some(metadata_vec) = build_runner.find_build_script_metadatas(unit) {
for metadata in metadata_vec {
if let Some(output) = build_runner
.build_script_outputs
.lock()
.unwrap()
.get(metadata)
{
for path in &output.rerun_if_changed {
// The paths we have saved from the unit are of arbitrary relativeness and may be
// relative to the crate root of the dependency.
let path = unit.pkg.root().join(path);
deps.insert(path);
}
}
}
}
Expand Down
Loading
Loading