-
-
Notifications
You must be signed in to change notification settings - Fork 99
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
Add rustc folder to dynamic linker search path #1499
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1499 +/- ##
==========================================
+ Coverage 78.46% 79.14% +0.68%
==========================================
Files 75 76 +1
Lines 18076 18569 +493
==========================================
+ Hits 14183 14697 +514
+ Misses 3893 3872 -21 ☔ View full report in Codecov by Sentry. |
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 looks really, really great. Thank you for all your hard work! Just a few comments but I think this is ready to go.
One general comment is that this won't yet work with archived builds, because we don't archive the sysroot. But I'd like to document that for now, and address that after getting a fix out to stop the bleeding.
nextest-metadata/src/test_list.rs
Outdated
@@ -485,7 +485,7 @@ pub struct RustBuildMetaSummary { | |||
|
|||
/// The target platforms used while compiling the Rust artifacts. | |||
#[serde(default)] | |||
pub target_platforms: Vec<PlatformSummary>, | |||
pub target_platforms: Vec<BuildPlatformsSummary>, |
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.
Ahhh, I see. I misunderstood what compatibility meant in this context, and I apologize for that. I think we do want to keep compatibility around in this case.
Also, this was my terrible oversight when I first put in target_platforms
, I wish I'd have added this BuildPlatformsSummary
struct at the time. I humbly apologize for the extra work you have to do here.
As far as handling this goes, I can think of three general directions.
-
Write out the old
target_platforms
field, and add a new field (saytargets
) which has the full context. Deprecatetarget_platforms
and ask users to use the new field if it's present. (This may want to be anOption<Vec<BuildPlatformsSummary>>
. (This is similar totarget_platform
below.)Hopefully, this adds enough indirection that will be the last time we'd need to do that.
-
Retain compatibility with the old fields in https://docs.rs/target-spec/3.1.0/src/target_spec/summaries.rs.html#33 by manually duplicating them, and add the
sysroot
as another field next to it.-
One way to do this would be to use
serde(flatten)
-- but that requires internal buffering, and in general, serde has numerous issues with internal buffering. -
Another way would be to manually duplicate the fields. But this is a challenge for two reasons. One is that the struct is
#[non_exhaustive]
https://docs.rs/target-spec/3.1.0/src/target_spec/summaries.rs.html#32, and two is that new semantically-important fields could be added to target-spec in the future. (I'm the maintainer of target-spec as well, so I can make changes to it if they make sense.)The former we could probably add some kind of builder for, but the latter is uncomfortably easy to miss details for.
We could have some kind of convoluted
PlatformSummaryBuilder
intarget-spec
that produces an error if not all fields were present, I guess. But I'm not convinced of the value of all that extra work.
-
-
Add another vector next to
target_platforms
called (say)target_platforms_extra
, and promise that it's the same length astarget_platforms
and corresponds 1:1 to it (i.e. users canzip
the two vectors).
I think between all of these options I like 1 the most. It is a little bit of extra work, but sets us up best for the future. (At some point in the future, we'll probably remove both target_platform
and target_platforms
with the appropriate warnings.)
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.
Adopt approach 1, but name the field as target_platforms_v2
to make it explicit that target_platforms
is deprecated. WDYT?
945b6bc
to
ccf511a
Compare
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.
We probably can only merge this PR late this week, as I don't have much extra time working on this. The plan for the next step is:
- Create another commit that creates a builder for
BuildPlatforms
andRustCli
BuildPlatformsBuilder
will make the ctor ofBuildPlatforms
better, so that we can create from- only target(useful for test and backward comaptible with the old version of
RustBuildMeta
); - target and host libdir without target libdir; and
- target, host libdir and any number of the target libdir
- only target(useful for test and backward comaptible with the old version of
RustCli
to streamline the call torustc
as we now probably will call it multiple times.
- Use
rustc --print target-libdir
instead ofsysroot
. - Integrate the new types with
BaseApp::new
. However I currently don't plan to actually support multiple targets here, as this is outside the scope of this PR.
I really, really appreciate all the work you've done here. Thank you for this kindness. Totally understand if you don't have more time, there's just a fractal of complexity here. Please feel free to do as much as you can, and if you don't have time before this weekend, I'll probably pick it up on Saturday or Sunday and finish it up. |
nextest-runner/src/platform.rs
Outdated
pub host_libdir: Option<Utf8PathBuf>, | ||
|
||
/// The target platform, if specified. | ||
pub target: Option<BuildPlatformTarget>, |
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.
@sunshowers This design makes the builder complicate, e.g.:
let mut builder = BuildPlatformBuilder::default();
let mut target_builder = builder.set_target(TargetTriple::x86_64_unknown_linux_gnu());
target_builder.set_libdir(Cursor::new("/fake/target/libdir"));
target_builder.add();
let build_platform = builder
.build()
.expect("should build with target successfully");
The alternative design is a flat struct
pub struct BuildPlatform {
pub host: Platform,
pub host_libdir: Option<Utf8PathBuf>,
pub target_libdir: Option<Utf8PathBuf>,
pub target_triple: Option<TargetTriple>,
}
and the previous build code can be rewritten as
let mut builder = BuildPlatformBuilder::default();
builder
.set_target_triple(TargetTriple::x86_64_unknown_linux_gnu())
.set_target_libdir(Cursor::new("/fake/target/libdir"));
let build_platform = builder
.build()
.expect("should build with target successfully");
Which way do you think is better?
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.
Well -- the flat struct, as your proposed it, allows for the invalid state where target_libdir
is Some(_)
but target_triple
is None
. So I'd strongly prefer the BuildPlatformTarget
pattern you have.
I'm not quite sure the builder pattern is pulling its weight though. Can the setters just live directly on the BuildPlatforms
and BuildPlatformTarget
structs?
nextest-runner/src/target_runner.rs
Outdated
@@ -27,11 +27,11 @@ impl TargetRunner { | |||
/// or via a `CARGO_TARGET_{TRIPLE}_RUNNER` environment variable | |||
pub fn new( | |||
configs: &CargoConfigs, | |||
build_platforms: &BuildPlatforms, |
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.
@sunshowers I rename BuildPlatforms
to BuildPlatform
as now we decided to not include an array of targets in BuildPlatform
. WDYT?
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.
Ah, I've always imagined the plural in BuildPlatforms
to consist of "host + target". So I think I'd prefer to keep it that way.
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.
Done. Revert the name change.
There seems to be still something wrong with the path setting per the CI result as of now. I will try to reproduce the issue locally and fix. |
Actually the CI "Test with latest nextest release" step fails because the CI upgrades to the latest rustup, and when using the latest nextest release, it suffers from the exact same issue this PR tries to fix. Will try to add the env suggested in #1493 (comment) to pass the CI. Once the latest nextest release includes this PR, we come up with another PR to revert the env change. However, with the env change, this PR can't be tested in the CI, at least the integration test almost won't catch anything in this change, we have to delay until the next PR to revert the env change to check if this PR has any issue. But we pass the "Test with locally built nextest" step in https://github.com/nextest-rs/nextest/actions/runs/9136713176/job/25125843092 without the env change, and this should give us some confidence. |
24b0f99
to
6628491
Compare
... to WA nextest-rs#1493 for the "Test with latest nextest release" step on Windows temporarily.
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.
Looks generally great, just a few more comments. Could you let me know within the next day or so whether you'll have time to get this finished up? If not then I can address them myself and land this.
Thanks again for all your work.
@@ -4,7 +4,7 @@ | |||
use crate::{ | |||
cargo_config::{TargetDefinitionLocation, TargetTriple, TargetTripleSource}, | |||
config::{CustomTestGroup, TestGroup}, | |||
platform::BuildPlatforms, | |||
platform::{BuildPlatform as NextestBuildPlatform, BuildPlatformTarget}, |
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.
Any reason for the NextestBuildPlatform
alias?
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.
No, because I used to change the name to BuildPlatform
and it collides with the name of gnuppy::graph::cargo::BuildPlatform
.
Now that we decide to change the name back to BuildPlatforms
, no need to alias the name to avoid the collision.
nextest-runner/src/target_runner.rs
Outdated
@@ -27,11 +27,11 @@ impl TargetRunner { | |||
/// or via a `CARGO_TARGET_{TRIPLE}_RUNNER` environment variable | |||
pub fn new( | |||
configs: &CargoConfigs, | |||
build_platforms: &BuildPlatforms, |
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.
Ah, I've always imagined the plural in BuildPlatforms
to consist of "host + target". So I think I'd prefer to keep it that way.
nextest-runner/src/platform.rs
Outdated
/// | ||
/// Used to set the dynamic linker search path when running the test executables. If we fail to | ||
/// parse the input, the libdir won't be set. | ||
pub fn set_host_libdir(&mut self, reader: impl io::BufRead) { |
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.
I'd rather this just take a Utf8PathBuf
, seems a bit too implementation-dependent to take the stdout of rustc here.
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.
Changed to set_host_libdir_from_rustc_output
for setting from the output. If we just want to set it, just use mutate the struct. WDYT?
nextest-runner/src/platform.rs
Outdated
pub host_libdir: Option<Utf8PathBuf>, | ||
|
||
/// The target platform, if specified. | ||
pub target: Option<BuildPlatformTarget>, |
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.
Well -- the flat struct, as your proposed it, allows for the invalid state where target_libdir
is Some(_)
but target_triple
is None
. So I'd strongly prefer the BuildPlatformTarget
pattern you have.
I'm not quite sure the builder pattern is pulling its weight though. Can the setters just live directly on the BuildPlatforms
and BuildPlatformTarget
structs?
a18f428
to
e2ca0b0
Compare
I do have time to address any further comments in the next week as I don't expect any big changes ahead. |
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.
Okay, just a couple more changes to go and then we can get this out there 🥳
nextest-metadata/src/test_list.rs
Outdated
/// The libdir for the host platform. | ||
/// | ||
/// Empty if failed to discover. | ||
#[serde(default)] | ||
pub host_libdir: Option<Utf8PathBuf>, |
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.
Hmm, I'm not quite sure this is right (for no fault of your own).
Currently, it looks like we were serializing either the target platform if --target
is specified, or the host platform if not. I think that's wrong (and it's my fault I'm pretty sure :) ), and that this libdir stuff forces the issue.
So, in general, there are:
- exactly 1 host platform with its libdir
- Some N >= 0 target platforms with its libdir
Storing N host libdirs doesn't seem right. I think what we should do here is:
// host and target platforms are the same for now, but it's
// quite possible we'll start storing target-specific data at some point
pub struct HostPlatformSummary {
pub platform: PlatformSummary,
pub libdir: Option<Utf8PathBuf>,
}
pub struct TargetPlatformSummary {
pub platform: PlatformSummary,
pub libdir: Option<Utf8PathBuf>,
}
pub struct BuildPlatformsSummary {
pub host: HostPlatformSummary,
pub targets: Vec<TargetPlatformSummary>,
}
// and in RustBuildMetaSummary:
pub struct RustBuildMetaSummary {
// ...
#[serde(default)]
platforms: Option<BuildPlatformsSummary>,
// ...
}
I think this solves all the problems, and also is independent justification to remove the "v2" stuff -- we're now clearly storing the host and target platforms separately, rather than smooshing them together.
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.
also is independent justification to remove the "v2" stuff -- we're now clearly storing the host and target platforms separately, rather than smooshing them together.
IIUC, this new platforms
field still makes both target_platform
and target_platforms
deprecated. Is that correct?
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.
Does this implicitly imply that BuildPlatforms::host
should respect the new HostPlatformSummary::platform
?
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.
In addition, what should be the interface of from_summary
be like? from_summary(summary: BuildPlatformsSummary) -> Result<BuildPlatforms>
or from_summary(summary: BuildPlatformsSummary) -> Result<Vec<BuildPlatforms>>
? In the former case of from_summary(summary: BuildPlatformsSummary) -> Result<BuildPlatforms>
, should we change BuildPlatforms::target
from Option<BuildPlatformsTarget>
to Vec<BuildPlatformsTarget>
?
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.
IIUC, this new platforms field still makes both target_platform and target_platforms deprecated. Is that correct?
Yeah.
Does this implicitly imply that
BuildPlatforms::host
should respect the newHostPlatformSummary::platform
?
Yep, while performing deserialization.
In addition, what should be the interface of
from_summary
be like?from_summary(summary: BuildPlatformsSummary) -> Result<BuildPlatforms>
orfrom_summary(summary: BuildPlatformsSummary) -> Result<Vec<BuildPlatforms>>
?
The former.
In the former case of
from_summary(summary: BuildPlatformsSummary) -> Result<BuildPlatforms>
, should we changeBuildPlatforms::target
fromOption<BuildPlatformsTarget>
toVec<BuildPlatformsTarget>
?
Just error out if there's more than one.
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.
Just error out if there's more than one.
Which error should I return? RustBuildMetaParseError::PlatformDeserializeError
or RustBuildMetaParseError::UnknownHostPlatform
or should I create another enum variant? In case of using existing enum variant, how do I generate the source target_spec::Error
or should I change the variant to be another enum which includes a MultipleTargets
variant?
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.
Another variant on RustBuildMetaParseError is fine.
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.
Done.
- Introduce new types
HostPlatformSummary
andTargetPlatformSummary
- Deserialize
BuildPlatforms::host
fromHostPlatformSummary::platform
- Introduce a new
RustBuildMetaParseError
variant, which is returned if the argument offrom_summary(summary: BuildPlatformsSummary) -> Result<BuildPlatforms>
has more than one entries in thetargets
field.
nextest-runner/src/platform.rs
Outdated
/// cargo-nextest represents the host triple with `None` during runtime. However the | ||
/// build-metadata might be used on a system with a different host triple. Therefore, the host | ||
/// triple is detected if `target_triple` is `None`. | ||
impl From<BuildPlatforms> for BuildPlatformsSummary { |
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.
Have to be honest, I'm generally hesitant about From
impls like this, only liking them for a Liskov-like "is-a" substitutions. Could you turn them back into from_summary
/to_summary
as before? It's not a huge deal but just makes it slightly more explicit.
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.
Changed to ToSummary
and FromSummary
trait, while still leave the to_summary_str
and from_summary_str
in the impl
block. Using traits allows me to use the same method name to_summary
/from_summary
for both the old PlatformSummary
type and the new BuildPlatformsSummary
type.
WDYT? Let me know if you feel strong that we shouldn't introduce new traits.
* Add a `BuildPlatformsTarget` to store the target triple. We will store target libdir in this struct in a following commit. * Change `BuildPlatforms::new` to be called without any arguments, which make it easer to create `BuildPlatforms` when there is no target, especially for testing. * Create a serialized form of `BuildPlatforms`: `BuildPlatformsSummary` * Change `discover_build_platforms` to `discover_target_triple` which only discovers the `TargetTriple`
... which stream lines the call to the `rustc` binary. `RustcCli` will be used to decide the host and target libdir in a following commit.
... so that we can run cargo-nextest with proc-macro projects on Windows. This commit also adds integration tests that run cargo-nextest with a proc-macro project.
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.
Thanks for all your work. I'll land this and fix up the last couple of things.
Appreciate you both for getting this through! |
... so that we can run cargo-nextest with proc-macro projects on Windows to fix #1493.
This commit also adds integration tests for running cargo-nextest for proc-macro projects.