Description
Currently, ui_test
doesn't support crates that appear as both build-dependencies and core dependencies. That's a bummer as it blocks rust-lang/rust-clippy#14883 which is on the critical path to resolving rust-lang/rust#78717.
So, I wonder what could be done here. First I tried to understand what happens.
The problem
To determine the rlib files that should be added to the tests, ui_test builds the test dependency crate with --message-format=json
. Then it scours the JSON we get from that for the files we care about.
The problem is that sometimes we get this:
{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#[email protected]","manifest_path":"/home/r/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quote-1.0.40/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"quote","src_path":"/home/r/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quote-1.0.40/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","proc-macro"],"filenames":["/home/r/src/rust/clippy/target/debug/deps/libquote-d5accd6216ede55c.rlib","/home/r/src/rust/clippy/target/debug/deps/libquote-d5accd6216ede55c.rmeta"],"executable":null,"fresh":false}
{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#[email protected]","manifest_path":"/home/r/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quote-1.0.40/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"quote","src_path":"/home/r/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quote-1.0.40/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","proc-macro"],"filenames":["/home/r/src/rust/clippy/target/debug/deps/libquote-b6ba71c8e941b673.rlib","/home/r/src/rust/clippy/target/debug/deps/libquote-b6ba71c8e941b673.rmeta"],"executable":null,"fresh":false}
This is basically the same line twice, just with two different hashes in the filename.
This happens because cargo built quote
twice: once as a dependency of a proc macro, and once as a dependency of the crate itself. These days those two dependencies don't get unified any more to avoid features leaking between "host dependencies" and "target dependencies". But ui_test has no way of knowing which of these two to use, so we give up.
Is that right? There's something here I don't understand, which is the situation where a crate only appears as a host dependency. ui_test wouldn't know this and then it would make that available to the test. Doesn't that cause problems? In particular if we are cross-building where host dependencies will have been built for the wrong target?
The pipe dream solution
Cargo probably knows why it built this crate. If it could communicate that to us in the JSON, this would be trivial. "Just" tell us whether this crate was built "for the host" or "for the target". Or is there some reason that cargo doesn't have this information by the time the JSON is emitted? Cc @ehuss @weihanglo
The hacky solution?
If, instead of cargo build
, we run cargo build --target x86_64-unknown-linux-gnu
, we get slightly different output:
{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#[email protected]","manifest_path":"/home/r/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quote-1.0.40/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"quote","src_path":"/home/r/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quote-1.0.40/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","proc-macro"],"filenames":["/home/r/src/rust/clippy/target/x86_64-unknown-linux-gnu/debug/deps/libquote-d21625b54f8de8ce.rlib","/home/r/src/rust/clippy/target/x86_64-unknown-linux-gnu/debug/deps/libquote-d21625b54f8de8ce.rmeta"],"executable":null,"fresh":false}
{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#[email protected]","manifest_path":"/home/r/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quote-1.0.40/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"quote","src_path":"/home/r/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quote-1.0.40/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","proc-macro"],"filenames":["/home/r/src/rust/clippy/target/debug/deps/libquote-7d753679308ff16a.rlib","/home/r/src/rust/clippy/target/debug/deps/libquote-7d753679308ff16a.rmeta"],"executable":null,"fresh":false}
Note the two different filenames:
/home/r/src/rust/clippy/target/x86_64-unknown-linux-gnu/debug/deps/libquote-d21625b54f8de8ce.rlib
/home/r/src/rust/clippy/target/debug/deps/libquote-7d753679308ff16a.rlib
Looking at these, it is clear that the first one is the "target dependency" and the second is the "host dependency".
So maybe ui_test could use that to resolve the ambiguity? I don't know what the best algorithm here is; the easiest one is "call pop()
three times and then compare the filename()
with the target name; if they match, it's the target dependency". @oli-obk do you think that could work?