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

Can't set debug-assertions via -Z config-profile #7253

Closed
alexcrichton opened this issue Aug 15, 2019 · 9 comments · Fixed by #7748
Closed

Can't set debug-assertions via -Z config-profile #7253

alexcrichton opened this issue Aug 15, 2019 · 9 comments · Fixed by #7748
Labels
A-config-profile Area: `[profile]` in cargo config files A-configuration Area: cargo config files and env vars A-environment-variables Area: environment variables

Comments

@alexcrichton
Copy link
Member

Currently I get:

$ cargo new foo
$ cd foo
$ CARGO_PROFILE_DEV_DEBUG_ASSERTIONS=false cargo +nightly build
error: failed to parse manifest at `/home/alex/code/wut/foo/Cargo.toml`

Caused by:
  missing config key `profile.dev.debug`

cc @ehuss

@alexcrichton
Copy link
Member Author

Something to do with this check I believe, gonna try to page serde back in...

@ehuss
Copy link
Contributor

ehuss commented Aug 16, 2019

Oh, that's a tricky one. It looks like it is confused on "debug" vs "debug-assertions". I'll take a look at a fix, it may need to scan for longest keys first. There's a bit of ambiguity there.

@ehuss
Copy link
Contributor

ehuss commented Aug 16, 2019

Yikes, it's much more difficult than I expected. At the point where it deserializes an Option, it doesn't know what the inner type may be. It may be a map (or struct) with additional key parts, or it may be a basic type with no additional key parts. There's no way to inspect what the type may be.

I'm not sure how to deal with that. There could be a custom deserialize implementation for Option<T> where T is a map or struct, and then it could behave differently, somehow. But it's a little mind-bending.

Another option is to not allow _ in key names. That is, it would be DEBUGASSERTIONS instead of DEBUG_ASSERTIONS. Sounds familiar to the problem where map keys with underscores don't work (like serde_json) from #5552.

Or we could rethink how config env vars work altogether.

@alexcrichton
Copy link
Member Author

I actually think that disallowing _ in key names if it works isn't a bad idea. I don't think we can quite get away with that today because lots of places have things like CARGO_TARGET_X86_64_... and we wouldn't want to break those. I could imagine though also accepting "squished" versions like CARGO_TARGET_X8664..., but do you think that'd be enough to fix this?

Apart from that though I agree we may need to rethink env vars :(

@ehuss
Copy link
Contributor

ehuss commented Aug 19, 2019

I could imagine though also accepting "squished" versions

The "target" table works a little differently since it is queried by key (it knows ahead of time what target to look for). I'm not sure, but I think profiles is the only config thing with a map that hits this problem.

I'm going to leave this here so I don't lose it. One test currently fails, and the other fails if these lines are removed.

#[cargo_test]
fn tricky_env_config() {
    // Some issues with underscores in env vars.
    #[derive(Deserialize)]
    struct WithOptMap {
        m: Option<collections::BTreeMap<String, u32>>,
    }
    let config = new_config(&[
        ("CARGO_WITHOPTMAP_M_bitflags", "1"),
    ]);
    let s: WithOptMap = config.get("withoptmap").unwrap();
    assert_eq!(s.m.expect("option").get("bitflags"), Some(&1));

    #[derive(Deserialize)]
    struct Ambig {
        debug: Option<u32>,
        debug_assertions: Option<bool>,
    }
    let config = new_config(&[
        ("CARGO_AMBIG_DEBUG_ASSERTIONS", "true"),
    ]);
    let s: Ambig = config.get("ambig").unwrap();
    assert_eq!(s.debug_assertions, Some(true));
    assert_eq!(s.debug, None);
}

@alexcrichton
Copy link
Member Author

Yeah I've always sort of regretted that we have these weird paths of configuration in Cargo which aren't entirely consistent so some stuff (like target configuration) works well but others based on table accesses (like profiles) don't work so well.

It may be possible with serde-fu to handle these errors and basically deterministically swallow them specifically for optional fields if the env key ended up not being found. That being said I don't personally posess the serde-fu to finagle that.

A perhaps drastic alternative is to say this is "wontfix" and start splitting environment variables on periods instead of underscores (well, both for compat, but you get the idea). That way we could do the equivalent of cargo.profile.dev.debug-assertions=1 as an environment variable, which although it's pretty difficult to set that from the shell (I think you need to use env) it may be good enough for tooling purposes like rustbuild or other build systems which invoke Cargo.

@ehuss
Copy link
Contributor

ehuss commented Aug 19, 2019

It may be possible with serde-fu to handle these errors

I initially thought of trying that, but the Visitor takes the deserializer by value and the visitor can't be cloned or anything.

This issue seems to provide something similar to what we're trying to achieve. When I have more time and energy, I'll try to take another stab to see if there is serde magic that'll work.

splitting environment variables on periods

I'm also tempted by it, but it can be very awkward to use in most shells.

@ehuss ehuss added A-configuration Area: cargo config files and env vars A-environment-variables Area: environment variables A-config-profile Area: `[profile]` in cargo config files labels Sep 21, 2019
@ehuss
Copy link
Contributor

ehuss commented Sep 26, 2019

Another option is to do what mdbook does and use double underscores to represent a dot to avoid confusion with dashes: https://rust-lang-nursery.github.io/mdBook/format/config.html#environment-variables

So it would be something like CARGO__PROFILE__DEV__DEBUG_ASSERTIONS. Not very pretty, but an option.

bors added a commit that referenced this issue Oct 9, 2019
Migrate towards exclusively using serde for `Config`

This series of commits was spawned off a thought I had while reading #7253 (comment), although it ended up not really touching on that at all. I was a little unsettled about how unstructured the config accesses are throughout Cargo and we had sort of two systems (one serde which is nice, one which is more manual) for reading config values.

This PR converts everything to run through serde for deserializing values, except for `get_list` which is funky. There's only one usage of that with the `paths` key though and we can probably fix this soon-ish.

In any case, the highlights of this PR are:

* This PR is surprisingly large. I did a lot of movement in `config.rs` to try to make the file smaller and more understandable.
* The `Value` type which retains information about where it was deserialized from is very special, and has special treatment with serde's data model. That's what allows us to use that and serde at the same time.
* The `ConfigRelativePath` and `ConfigKey` structures have been revamped internally, but morally serve the same purposes as before.
* Cargo now has structured `struct` access for a bunch of its configuration (`net`, `http`, `build`, etc). I would ideally like to move toward a world where this is the *only* way to read configuration, or at least everything conventionally runs through those paths.
* Functionally, this PR should have no difference other than tweaks to error messages here and there, and perhaps more strict validation on commands where we validate more configuration on each run than we previously did.
* This isn't a 100% transition for Cargo yet, but I figured it would be a good idea to post this and get some feedback first.
* In the long run I want to remove `get_env`, `get_cv`, and `get_*_priv` from `Config` as internal details. I'd like to move this all to `de.rs` and have it walk down the tree of configuration as we deserialize a value. For now though these all remain in place and that refactoring is left to a future PR.
@alexcrichton
Copy link
Member Author

This has been sitting in my inbox for awhile and I've meant to respond to it, sorry about that!

I don't really have a great opinion on what to do here at this point, but double-underscores seems like sort of the least bad option for now and isn't that unreasonable really.

bors added a commit that referenced this issue Dec 19, 2019
Config enhancements.

This is a collection of changes to config handling. I intended to split this into separate PRs, but they all built on one another so I decided to do it as one. However, I can still split this up if desired.

High level overview:

- Refactorings, mainly to remove `pub` from `Config::get_table` and use serde API instead.
- Add `--config` CLI option.
- Add config `include` to include other files.

This makes some progress on #5416.
Closes #6699.

This makes a minor user-visible change in regards to `StringList` types. If an array is specified in a config as a list, and also as an env var, they will now be merged. Previously the environment variable overrode the file value. But if it is a string, then it won't join (env var takes precedence). I can probably change this, but I'm not sure if the old behavior is desired, or if it should merge all the time?

**Future plans**
This lays the groundwork for some more changes:
- Work on #7253 (`debug-assertions` and `debug` fails in environment vars). I have some ideas to try.
- Consider removing use of `get_list` for `paths`, and use a `Vec<ConfigRelativePath>`. This will require some non-trivial changes to how `ConfigSeqAccess` works. This is one of the last parts that does not use the serde API.
- Possibly change `[source]` to load config values in a lazy fashion. This will unlock the ability to use environment variables with source definitions (like CARGO_SOURCE_CRATES_IO_REPLACE_WITH).
- Possibly change `[profile]` to load config profiles in a lazy fashion. This will make it easier to use environment variables with profiles, particularly with arbitrarily named profiles.
- Possibly remove the case-sensitive environment variables in `-Zadvanced-env`. I think they are just too awkward, and prone to problems. Instead, drive people towards using `--config` instead of env vars.
- Add support for TOML tables in env vars (like `CARGO_PROFILES={my-profile={opt-level=1}})`). I started implementing it, but then looking at the use cases, it didn't seem as useful as I initially thought. However, it's still an option to try.

**Refactoring overview**

- `[source]` table now uses the serde API.
- `[target]` table now uses the serde API. This is complicated since the 'cfg()' entries are different from the triple entries. The 'cfg()' tables are loaded separately, and are accessed from `Config::target_cfgs`. Otherwise, it just uses `config.get` of the specific target.TRIPLE.
    - Moved the target config stuff into `config/target.rs`.
- Various changes to make this work:
    - Added `PathAndArgs` type which replaces `config.get_path_and_args`.
    - Changed `ConfigKey` to track the key parts as a list (instead of a string). This fixes an issue where quoted keys weren't handled properly (like `[foo.'a.b'.bar]`). This also seems to make a little more sense (it was joining parts into a string only to immediately call `split` on it). Changed various APIs to take a `ConfigKey` object instead of a string to avoid that splitting behavior.
    - `ValueDeserializer` now pre-computes the `Definition` so that it can provide a better error message when a value fails to deserialize.

Overall, there shouldn't be significant user-visible changes. Some error messages have changed and warnings have been added for some ignored keys. `-Zadvanced-env` now works for source and target tables, though I'm not really happy with that feature.
@bors bors closed this as completed in f7c5b1f Jan 6, 2020
alexcrichton added a commit to alexcrichton/rust that referenced this issue Jun 15, 2020
This commit moves the compiler-builtins-specific build logic from
`src/bootstrap/bin/rustc.rs` into the workspace `Cargo.toml`'s
`[profile]` configuration. Now that rust-lang/cargo#7253 is fixed we can
ensure that Cargo knows about debug assertions settings, and it can also
be configured to specifically disable debug assertions unconditionally
for compiler-builtins. This should improve rebuild logic when
debug-assertions settings change and also improve build-std integration
where Cargo externally now has an avenue to learn how to build
compiler-builtins as well.
Manishearth added a commit to Manishearth/rust that referenced this issue Jun 26, 2020
…g-assertions, r=Mark-Simulacrum

rustbuild: Move compiler-builtins build logic to manifest

This commit moves the compiler-builtins-specific build logic from
`src/bootstrap/bin/rustc.rs` into the workspace `Cargo.toml`'s
`[profile]` configuration. Now that rust-lang/cargo#7253 is fixed we can
ensure that Cargo knows about debug assertions settings, and it can also
be configured to specifically disable debug assertions unconditionally
for compiler-builtins. This should improve rebuild logic when
debug-assertions settings change and also improve build-std integration
where Cargo externally now has an avenue to learn how to build
compiler-builtins as well.
alexcrichton added a commit to alexcrichton/rust that referenced this issue Jun 29, 2020
This commit moves the compiler-builtins-specific build logic from
`src/bootstrap/bin/rustc.rs` into the workspace `Cargo.toml`'s
`[profile]` configuration. Now that rust-lang/cargo#7253 is fixed we can
ensure that Cargo knows about debug assertions settings, and it can also
be configured to specifically disable debug assertions unconditionally
for compiler-builtins. This should improve rebuild logic when
debug-assertions settings change and also improve build-std integration
where Cargo externally now has an avenue to learn how to build
compiler-builtins as well.
Manishearth added a commit to Manishearth/rust that referenced this issue Jun 29, 2020
…g-assertions, r=Mark-Simulacrum

rustbuild: Move compiler-builtins build logic to manifest

This commit moves the compiler-builtins-specific build logic from
`src/bootstrap/bin/rustc.rs` into the workspace `Cargo.toml`'s
`[profile]` configuration. Now that rust-lang/cargo#7253 is fixed we can
ensure that Cargo knows about debug assertions settings, and it can also
be configured to specifically disable debug assertions unconditionally
for compiler-builtins. This should improve rebuild logic when
debug-assertions settings change and also improve build-std integration
where Cargo externally now has an avenue to learn how to build
compiler-builtins as well.
bors added a commit to rust-lang-ci/rust that referenced this issue Jun 29, 2020
…assertions, r=Mark-Simulacrum

rustbuild: Move compiler-builtins build logic to manifest

This commit moves the compiler-builtins-specific build logic from
`src/bootstrap/bin/rustc.rs` into the workspace `Cargo.toml`'s
`[profile]` configuration. Now that rust-lang/cargo#7253 is fixed we can
ensure that Cargo knows about debug assertions settings, and it can also
be configured to specifically disable debug assertions unconditionally
for compiler-builtins. This should improve rebuild logic when
debug-assertions settings change and also improve build-std integration
where Cargo externally now has an avenue to learn how to build
compiler-builtins as well.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-config-profile Area: `[profile]` in cargo config files A-configuration Area: cargo config files and env vars A-environment-variables Area: environment variables
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants