-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
Fix passing of linker with target-applies-to-host and an implicit target #14206
base: master
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,10 +20,12 @@ use serde::{Deserialize, Serialize}; | |
use std::cell::RefCell; | ||
use std::collections::hash_map::{Entry, HashMap}; | ||
use std::path::{Path, PathBuf}; | ||
use std::rc::Rc; | ||
use std::str::{self, FromStr}; | ||
use std::sync::Arc; | ||
|
||
/// Information about the platform target gleaned from querying rustc. | ||
/// Information about the platform target gleaned from querying rustc and from | ||
/// merging configs. | ||
/// | ||
/// [`RustcTargetData`] keeps several of these, one for the host and the others | ||
/// for other specified targets. If no target is specified, it uses a clone from | ||
|
@@ -54,6 +56,8 @@ pub struct TargetInfo { | |
pub rustflags: Arc<[String]>, | ||
/// Extra flags to pass to `rustdoc`, see [`extra_args`]. | ||
pub rustdocflags: Arc<[String]>, | ||
gmorenz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/// Linker to use. If the value is `None` it is left up to rustc. | ||
pub linker: Option<Rc<PathBuf>>, | ||
/// Whether or not rustc (stably) supports the `--check-cfg` flag. | ||
/// | ||
/// Can be removed once the minimum supported rustc version of Cargo is | ||
|
@@ -157,6 +161,11 @@ impl TargetInfo { | |
requested_kinds: &[CompileKind], | ||
rustc: &Rustc, | ||
kind: CompileKind, | ||
// This config is used for `links_overrides` and `linker`. | ||
// | ||
// In the case of target_applies_to_host=true (default) it may contain | ||
// incorrect rustflags. | ||
target_config: &TargetConfig, | ||
) -> CargoResult<TargetInfo> { | ||
let mut rustflags = | ||
extra_args(gctx, requested_kinds, &rustc.host, None, kind, Flags::Rust)?; | ||
|
@@ -321,6 +330,7 @@ impl TargetInfo { | |
Flags::Rustdoc, | ||
)? | ||
.into(), | ||
linker: target_linker(gctx, &cfg, target_config)?.map(Rc::new), | ||
cfg, | ||
support_split_debuginfo, | ||
support_check_cfg, | ||
|
@@ -826,6 +836,42 @@ fn rustflags_from_target( | |
} | ||
} | ||
|
||
/// Gets the user-specified linker for a particular host or target from the configuration. | ||
fn target_linker( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. After this PR the For example, [target.'cfg(target_arch = "x86_64")']
linker = "foo"
[target.'cfg(target_os = "linux")']
linker = "foo" This might not be ideal because those commands don't need target infos. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch! I entirely missed that this was a problem. I don't see a good solution to this, I'll come back with a fresh set of eyes tomorrow and see if that changes. Right now my take is it's either this (bad), don't fix this issue at all (also bad), or doing something involving not so clean code to defer actually returning the error (also bad). But I think there's a small chance I can find a better way. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Honestly, the current approach is not too bad for normal users. However, I know some enterprise users have weird multi-level configuration setup. And may move projects among different directories. This is also bad because you cannot opt out directory-probing for configuration files (which Cargo may provide an escape patch?). |
||
gctx: &GlobalContext, | ||
target_cfg: &[Cfg], | ||
target_config: &TargetConfig, | ||
) -> CargoResult<Option<PathBuf>> { | ||
// Try host.linker and target.{}.linker. | ||
if let Some(path) = target_config | ||
.linker | ||
.as_ref() | ||
.map(|l| l.val.clone().resolve_program(gctx)) | ||
{ | ||
return Ok(Some(path)); | ||
} | ||
|
||
// Try target.'cfg(...)'.linker. | ||
let mut cfgs = gctx | ||
.target_cfgs()? | ||
.iter() | ||
.filter_map(|(key, cfg)| cfg.linker.as_ref().map(|linker| (key, linker))) | ||
.filter(|(key, _linker)| CfgExpr::matches_key(key, target_cfg)); | ||
let matching_linker = cfgs.next(); | ||
if let Some((key, linker)) = cfgs.next() { | ||
anyhow::bail!( | ||
"several matching instances of `target.'cfg(..)'.linker` in configurations\n\ | ||
first match `{}` located in {}\n\ | ||
second match `{}` located in {}", | ||
matching_linker.unwrap().0, | ||
matching_linker.unwrap().1.definition, | ||
key, | ||
linker.definition | ||
); | ||
} | ||
Ok(matching_linker.map(|(_k, linker)| linker.val.clone().resolve_program(gctx))) | ||
} | ||
|
||
/// Gets compiler flags from `[host]` section in the config. | ||
/// See [`extra_args`] for more. | ||
fn rustflags_from_host( | ||
|
@@ -893,22 +939,28 @@ impl<'gctx> RustcTargetData<'gctx> { | |
let mut target_info = HashMap::new(); | ||
let target_applies_to_host = gctx.target_applies_to_host()?; | ||
let host_target = CompileTarget::new(&rustc.host)?; | ||
let host_info = TargetInfo::new(gctx, requested_kinds, &rustc, CompileKind::Host)?; | ||
|
||
// This config is used for link overrides and choosing a linker. | ||
let host_config = if target_applies_to_host { | ||
gctx.target_cfg_triple(&rustc.host)? | ||
} else { | ||
gctx.host_cfg_triple(&rustc.host)? | ||
}; | ||
let host_info = TargetInfo::new( | ||
gctx, | ||
requested_kinds, | ||
&rustc, | ||
CompileKind::Host, | ||
&host_config, | ||
)?; | ||
|
||
// This is a hack. The unit_dependency graph builder "pretends" that | ||
// `CompileKind::Host` is `CompileKind::Target(host)` if the | ||
// `--target` flag is not specified. Since the unit_dependency code | ||
// needs access to the target config data, create a copy so that it | ||
// can be found. See `rebuild_unit_graph_shared` for why this is done. | ||
if requested_kinds.iter().any(CompileKind::is_host) { | ||
target_config.insert(host_target, gctx.target_cfg_triple(&rustc.host)?); | ||
let host_target_config = gctx.target_cfg_triple(&rustc.host)?; | ||
|
||
// If target_applies_to_host is true, the host_info is the target info, | ||
// otherwise we need to build target info for the target. | ||
|
@@ -920,9 +972,12 @@ impl<'gctx> RustcTargetData<'gctx> { | |
requested_kinds, | ||
&rustc, | ||
CompileKind::Target(host_target), | ||
&host_target_config, | ||
)?; | ||
target_info.insert(host_target, host_target_info); | ||
} | ||
|
||
target_config.insert(host_target, host_target_config); | ||
}; | ||
|
||
let mut res = RustcTargetData { | ||
|
@@ -969,14 +1024,20 @@ impl<'gctx> RustcTargetData<'gctx> { | |
/// Insert `kind` into our `target_info` and `target_config` members if it isn't present yet. | ||
pub fn merge_compile_kind(&mut self, kind: CompileKind) -> CargoResult<()> { | ||
if let CompileKind::Target(target) = kind { | ||
if !self.target_config.contains_key(&target) { | ||
self.target_config | ||
.insert(target, self.gctx.target_cfg_triple(target.short_name())?); | ||
} | ||
let target_config: &TargetConfig = match self.target_config.entry(target) { | ||
Entry::Occupied(o) => o.into_mut(), | ||
Entry::Vacant(v) => v.insert(self.gctx.target_cfg_triple(target.short_name())?), | ||
}; | ||
if !self.target_info.contains_key(&target) { | ||
self.target_info.insert( | ||
target, | ||
TargetInfo::new(self.gctx, &self.requested_kinds, &self.rustc, kind)?, | ||
TargetInfo::new( | ||
self.gctx, | ||
&self.requested_kinds, | ||
&self.rustc, | ||
kind, | ||
target_config, | ||
)?, | ||
); | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment didn't really fit with this struct containing
rustflags
(which predates me working on target-applies-to-host). Puttinglinker
in it makes the mismatch slightly worse, so I thought I'd update the comment.I'm not entirely thrilled with the phrasing. If someone has a suggestion for better phrasing I'd be happy to take it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe somthing like?