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

Include executable in JSON output. #5517

Closed
wants to merge 1 commit into from
Closed

Include executable in JSON output. #5517

wants to merge 1 commit into from

Conversation

patriksvensson
Copy link
Contributor

Closes #5426

@rust-highfive
Copy link

r? @matklad

(rust_highfive has picked a reviewer for you, use r? to override)

@@ -393,6 +393,22 @@ fn link_targets<'a, 'cfg>(
.collect();
let json_messages = bcx.build_config.json_messages();

// Find the executable for the current target (if any).
let mut executable : Option<PathBuf> = Option::None;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Wanted to move this inside the job below but ran into problems with Unit. Any suggestions of how to resolve these problems are appreciated. Not sure if there are any side effects with the current approach.

Copy link
Member

Choose a reason for hiding this comment

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

No, this is exactly how it should look like, and it's kinda cool that Rust detects this at compile time. The Work thing which we create below is a long-lived closure, and works are executed concurrently. If in that closure we close over Context, than bad things would happen, because several works would try to access Context simultaneously from different threads, and context is not ready for that.

So Rust enforces that we compute all relevant data before hand, and store just simple stuff like Strings inside the Work.

Copy link
Member

Choose a reason for hiding this comment

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

Also, you can use let mut executable: Option<PathBuf> = None;, no need to qualify None. However, I hope when bindist is extracted as a separate function, this could be simplified to let executable = if produces_executable(unit) { bindist(unit) } else { None }.

Copy link
Contributor Author

@patriksvensson patriksvensson May 11, 2018

Choose a reason for hiding this comment

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

@matklad Awesome explanation. Thanks!

@@ -4213,6 +4217,7 @@ fn message_format_json_forward_stderr() {
"overflow_checks": false,
"test":false
},
"executable": "{...}",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not verifying the executable here since that's not what's being tested here. Is that OK?

Copy link
Member

Choose a reason for hiding this comment

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

Yep, that's ok!

@patriksvensson
Copy link
Contributor Author

@matklad Any idea why tests are failing on Linux and MacOS?

Expected part:
"[..]foo[EXE]"
Actual part:
"/home/travis/build/rust-lang/cargo/target/cit/t168/foo/target/debug/foo"

@ehuss
Copy link
Contributor

ehuss commented May 11, 2018

@patriksvensson The [..] match is not greedy, so it is only matching up to the first foo. Something like "[..]foo[/]target[/]debug[/]foo[EXE]" should work.

Some(ref link_dst) => link_dst,
None => &output.path,
};
if unit.target.is_bin() || unit.target.is_bin_example() {
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 the logic here needs to be adjusted slightly. In Cargo, there are several flavors of excutables:

  1. binaries and examples, where the user writes fn main() themselves
  2. tests and becnhmars, where fn main() is synthesized by the compiler
  3. build scripts

I think we definitely should specify "executable" for 1 and 2, and maybe for 3 as well.

The test setup for it would look like this:

λ exa -GT
.
├── benches
│  └── benchmark.rs
├── Cargo.toml
├── src
│  ├── lib.rs
│  └── main.rs
└── tests
   └── integration_test.rs

Then, executing cargo test --no-run should show executables for integration_test and for lib.rs (when testing, libary is compiled as an executable which launches unit-tests).

Executing cargo bench --no-run should show exetable for benchmark.

Copy link
Contributor Author

@patriksvensson patriksvensson May 27, 2018

Choose a reason for hiding this comment

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

@matklad I'm having some problems with the tests here. It seems like that the JSON lines emitted by cargo test isn't emitted in a deterministic order. Am I missing something here or might this be a bug?

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 this is ok: for example, Cargo could compile tests and becnhmarks in parallel, so either can be ready first. You could add with_json_unordered method to the testing infra to avoid the problem. It also should be possible to modify the test such that there's only one executable per compilation. For example, you can run cargo build --lib, cargo build --bin separately.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@matklad Ah, didn't know about the with_json_unordered approach 👍 I'm going with separate assert passes like you suggest since that one sounds cleaner somehow. Thanks!

let bindst = match output.hardlink {
Some(ref link_dst) => link_dst,
None => &output.path,
};
Copy link
Member

Choose a reason for hiding this comment

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

This logic is duplicated when we populate Compilation::binaries. Let's extract a helper function fn exetutable_dest(unit: &Unit)?

Copy link
Member

Choose a reason for hiding this comment

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

It might need access to cx as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@matklad Do you mean the let bindst logic?

Copy link
Member

Choose a reason for hiding this comment

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

Yep! The "is this unit executable" logic needs to be different.

@@ -439,6 +455,7 @@ fn link_targets<'a, 'cfg>(
profile: art_profile,
features,
filenames: destinations,
executable: executable,
Copy link
Member

Choose a reason for hiding this comment

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

Could be just executable: if field name and var name are the same, you don't have to write foo: foo.

@matklad
Copy link
Member

matklad commented May 11, 2018

@patriksvensson the actual implementation looks great to me, though I think we need to tweak a logic of what is considered an executable. Basically, we need to make sure that tests and benches also have not-None executable in the corresponding artifact.

@patriksvensson
Copy link
Contributor Author

@matklad I noticed that for tests (regular one, not integration tests), there is nothing in the metadata about the target that seem to hint about it producing an executable (except the filename when running on Windows).

{
    "executable": null,
    "features": [],
    "filenames": [
        "D:\\Source\\github\\patriksvensson\\cargo\\target\\cit\\t0\\foo\\target\\debug\\foo-3398de0ad2d6876f.exe"
    ],
    "fresh": false,
    "package_id": "foo 0.0.1 (path+file:///D:/Source/github/patriksvensson/cargo/target/cit/t0/foo)",
    "profile": {
        "debug_assertions": true,
        "debuginfo": 2,
        "opt_level": "0",
        "overflow_checks": true,
        "test": true
    },
    "reason": "compiler-artifact",
    "target": {
        "crate_types": [
            "lib"
        ],
        "kind": [
            "lib"
        ],
        "name": "foo",
        "src_path": "D:\\Source\\github\\patriksvensson\\cargo\\target\\cit\\t0\\foo\\src\\lib.rs"
    }
}

Any ideas about how to detect this?

@matklad
Copy link
Member

matklad commented May 12, 2018

@patriksvensson

I believe this logic handles this:

if unit.mode.is_any_test() && !unit.mode.is_check() {

@patriksvensson
Copy link
Contributor Author

patriksvensson commented May 30, 2018

@matklad Any idea why I get a error: Could not compile 'foo'. error on Linux? Seems to work fine on Windows.

@alexcrichton
Copy link
Member

ping @patriksvensson, were you able to track down the CI failures?

@patriksvensson
Copy link
Contributor Author

@alexchrichton No, I wasn't. Currently on vacation with family but planning to take another look at it in about 3 days.

@alexcrichton
Copy link
Member

Sure thing, no worries!

@bors
Copy link
Contributor

bors commented Jul 5, 2018

☔ The latest upstream changes (presumably #5651) made this pull request unmergeable. Please resolve the merge conflicts.

@alexcrichton
Copy link
Member

@patriksvensson looks like some tests may still be failing?

@patriksvensson
Copy link
Contributor Author

@alexchrichton Yes, I had some spare time so I rebased my PR against master. Will take a look at the failing tests as soon as I have some spare time again.

@alexcrichton
Copy link
Member

Ok, no worries!

@bors
Copy link
Contributor

bors commented Jul 13, 2018

☔ The latest upstream changes (presumably #5711) made this pull request unmergeable. Please resolve the merge conflicts.

@alexcrichton
Copy link
Member

Ok I'm gonna close this for now, but feel free to update and I can always reopen!

bors added a commit that referenced this pull request Dec 3, 2018
Include executable in JSON output.

Fixes #5426
Rebase of @patriksvensson's #5517
CC @matklad

I didn't really get into the issue or the code, I just interatively rebased Patrik's branch and then massaged and cleaned up the code until the tests passed.  So please double check it for code correctness, test case correctness and test case coverage.

Particularly the branch changed an if condition according to [this suggestion](#5517 (comment)) by Aleksey.  I rolled that back because at one point it helped fix a series of tests.  But let me know if that should be included here.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants