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

Overhaul how cargo treats profiles #1441

Merged
merged 24 commits into from
Mar 24, 2015
Merged

Conversation

alexcrichton
Copy link
Member

This commit is a complete overhaul of how Cargo handles compilation profiles
internally. The external interface of Cargo is not affected by this change.

Previously each Target had a Profile embedded within it. Conceptually a Target
is an entry in the manifest (a binary, benchmark, etc) and a Profile controlled
various flags (e.g. --test, -C opt-level, etc). Each Package then contained many
profiles for each possible compilation mode. For example a Package would have
one target for testing a library, benchmarking a library, documenting a library,
etc. When it came to building these targets, Cargo would filter out the targets
listed to determine what needed to be built.

This filtering was largely done based off an "environment" represented as a
string. Each mode of compilation got a separate environment string like "test"
or "bench". Altogether, however, this approach had a number of drawbacks:

  • Examples in release mode do not currently work. This is due to how examples
    are classified and how release mode is handled (e.g. the "release" environment
    where examples are meant to be built in the "test" environment).
  • It is not trivial to implement cargo test --release today.
  • It is not trivial to implement cargo build --bin foo where only the binary
    foo is built. The same is true for examples.
  • It is not trivial to add selective building of a number of
    binaries/examples/etc.
  • Filtering the list of targets to build has some pretty hokey logic that
    involves pseudo-environments like "doc-all" vs "doc". This logic is duplicated
    in a few places and in general is quite brittle.
  • The TOML parser greatly affects compilation due to the time at which profiles
    are generated, which seems somewhat backwards.
  • Profiles must be overridden, but only partially, at compile time becuase only
    the top-level package's profile is applied.

In general, this system just needed an overhaul. This commit made a single
change of separating Profile from Target and then basically hit make until
all the tests passed again. The other large architectural changes are:

  • Environment strings are now entirely gone.
  • Filters are implemented in a much more robust fashion.
  • Release mode is now handled much more gracefully.
  • The unit of compilation in the backend is no longer (package, target) but
    rather (package, target, profile). This change had to be propagated many
    location in the cargo_rustc module.
  • The backend does not filter targets to build at all. All filtering now
    happens entirely in the frontend.

I'll test issues after this change lands, but the motivation behind this is to
open the door to quickly fixing a number of outstanding issues against Cargo.
This change itself is not intended to close many bugs.

This commit is a complete overhaul of how Cargo handles compilation profiles
internally. The external interface of Cargo is not affected by this change.

Previously each Target had a Profile embedded within it. Conceptually a Target
is an entry in the manifest (a binary, benchmark, etc) and a Profile controlled
various flags (e.g. --test, -C opt-level, etc). Each Package then contained many
profiles for each possible compilation mode. For example a Package would have
one target for testing a library, benchmarking a library, documenting a library,
etc. When it came to building these targets, Cargo would filter out the targets
listed to determine what needed to be built.

This filtering was largely done based off an "environment" represented as a
string. Each mode of compilation got a separate environment string like `"test"`
or `"bench"`. Altogether, however, this approach had a number of drawbacks:

* Examples in release mode do not currently work. This is due to how examples
  are classified and how release mode is handled (e.g. the "release" environment
  where examples are meant to be built in the "test" environment).
* It is not trivial to implement `cargo test --release` today.
* It is not trivial to implement `cargo build --bin foo` where *only* the binary
  `foo` is built. The same is true for examples.
* It is not trivial to add selective building of a number of
  binaries/examples/etc.
* Filtering the list of targets to build has some pretty hokey logic that
  involves pseudo-environments like "doc-all" vs "doc". This logic is duplicated
  in a few places and in general is quite brittle.
* The TOML parser greatly affects compilation due to the time at which profiles
  are generated, which seems somewhat backwards.
* Profiles must be overridden, but only partially, at compile time becuase only
  the top-level package's profile is applied.

In general, this system just needed an overhaul. This commit made a single
change of separating `Profile` from `Target` and then basically hit `make` until
all the tests passed again. The other large architectural changes are:

* Environment strings are now entirely gone.
* Filters are implemented in a much more robust fashion.
* Release mode is now handled much more gracefully.
* The unit of compilation in the backend is no longer (package, target) but
  rather (package, target, profile). This change had to be propagated many
  location in the `cargo_rustc` module.
* The backend does not filter targets to build *at all*. All filtering now
  happens entirely in the frontend.

I'll test issues after this change lands, but the motivation behind this is to
open the door to quickly fixing a number of outstanding issues against Cargo.
This change itself is not intended to close many bugs.
This adds a new `--bin` flag to `cargo test` to specifically say that a binary
should be tested. Additionally the dependencies are tweaked such that binaries
to not depend on themselves being available.
If a profile's `test` flag is set to true, then it will always generate a unit
test so the `is_test` check is redundant.
The flag now only applies to integration tests, not all targets with the
specified name.
Libraries are no longer built if they aren't doctested, so something else needed
to be present to trigger the library being built.
If no filter is supplied, then only consider binaries as candidates, not
examples as well.
This is required for `cargo run` to work
Binaries are no longer always built when examples are built, so update the test
accordingly.
The dependency is just there to get them to compile, not to actually induce
recompiles.
Both tweak how deep documentation is compiled as well as fixing up the
dependencies for a documented target.
@rust-highfive
Copy link

r? @huonw

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

@alexcrichton
Copy link
Member Author

This is me finally following up to #1325

@alexcrichton
Copy link
Member Author

cc @wycats

@alexcrichton
Copy link
Member Author

This will also unblock some work related to rust-lang/rust#23533 I've got pending.

@@ -50,20 +50,31 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
let root = try!(find_root_manifest_for_cwd(options.flag_manifest_path));
config.shell().set_verbose(options.flag_verbose);

let mut benches = Vec::new();
Copy link
Contributor

Choose a reason for hiding this comment

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

this vector looks unnecessary - seems you could use options.flag_bench.as_slice()

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm currently trying to keep Cargo on stable Rust as much as possible, and unfortunately these methods are currently unstable. I had not considered this though, and it's a good idea! I may try to facilitate the stability of as_slice now...

@alexcrichton
Copy link
Member Author

I can also squash any number of commits as desired or break up the first commit if necessary. I started by lumping as much as possible into one commit but eventually started making one fix per mistake, so the first commit is somewhat biasedly large!

@brson
Copy link
Contributor

brson commented Mar 23, 2015

@bors r+

@bors
Copy link
Contributor

bors commented Mar 23, 2015

📌 Commit 3ce79da has been approved by brson

@bors
Copy link
Contributor

bors commented Mar 23, 2015

⌛ Testing commit 3ce79da with merge 0428b88...

@bors
Copy link
Contributor

bors commented Mar 23, 2015

💔 Test failed - cargo-win-32

@alexcrichton
Copy link
Member Author

@bors: r=brson acd1304

@bors
Copy link
Contributor

bors commented Mar 23, 2015

⌛ Testing commit acd1304 with merge 060c59f...

@bors
Copy link
Contributor

bors commented Mar 24, 2015

💔 Test failed - cargo-win-32

@alexcrichton
Copy link
Member Author

@bors: r=bson 0c28783

@bors
Copy link
Contributor

bors commented Mar 24, 2015

⌛ Testing commit 0c28783 with merge c6b9324...

bors added a commit that referenced this pull request Mar 24, 2015
This commit is a complete overhaul of how Cargo handles compilation profiles
internally. The external interface of Cargo is not affected by this change.

Previously each Target had a Profile embedded within it. Conceptually a Target
is an entry in the manifest (a binary, benchmark, etc) and a Profile controlled
various flags (e.g. --test, -C opt-level, etc). Each Package then contained many
profiles for each possible compilation mode. For example a Package would have
one target for testing a library, benchmarking a library, documenting a library,
etc. When it came to building these targets, Cargo would filter out the targets
listed to determine what needed to be built.

This filtering was largely done based off an "environment" represented as a
string. Each mode of compilation got a separate environment string like `"test"`
or `"bench"`. Altogether, however, this approach had a number of drawbacks:

* Examples in release mode do not currently work. This is due to how examples
  are classified and how release mode is handled (e.g. the "release" environment
  where examples are meant to be built in the "test" environment).
* It is not trivial to implement `cargo test --release` today.
* It is not trivial to implement `cargo build --bin foo` where *only* the binary
  `foo` is built. The same is true for examples.
* It is not trivial to add selective building of a number of
  binaries/examples/etc.
* Filtering the list of targets to build has some pretty hokey logic that
  involves pseudo-environments like "doc-all" vs "doc". This logic is duplicated
  in a few places and in general is quite brittle.
* The TOML parser greatly affects compilation due to the time at which profiles
  are generated, which seems somewhat backwards.
* Profiles must be overridden, but only partially, at compile time becuase only
  the top-level package's profile is applied.

In general, this system just needed an overhaul. This commit made a single
change of separating `Profile` from `Target` and then basically hit `make` until
all the tests passed again. The other large architectural changes are:

* Environment strings are now entirely gone.
* Filters are implemented in a much more robust fashion.
* Release mode is now handled much more gracefully.
* The unit of compilation in the backend is no longer (package, target) but
  rather (package, target, profile). This change had to be propagated many
  location in the `cargo_rustc` module.
* The backend does not filter targets to build *at all*. All filtering now
  happens entirely in the frontend.

I'll test issues after this change lands, but the motivation behind this is to
open the door to quickly fixing a number of outstanding issues against Cargo.
This change itself is not intended to close many bugs.
@bors
Copy link
Contributor

bors commented Mar 24, 2015

☀️ Test successful - cargo-linux-32, cargo-linux-64, cargo-mac-32, cargo-mac-64, cargo-win-32, cargo-win-64

@bors bors merged commit 0c28783 into rust-lang:master Mar 24, 2015
@bors
Copy link
Contributor

bors commented Mar 24, 2015

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

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