Skip to content

Obtain the Cargo compiler configuration for use in subcommands without building the package #8923

Closed
@volks73

Description

@volks73

Describe the problem you are trying to solve

I would like to obtain the Rust compiler (rustc) configuration, i.e. the output from the cargo rustc -- --print cfg, within cargo subcommands. The output from the cargo rustc -- --print cfg command will be different from the rustc --print cfg command because Cargo will pass additional options based on Cargo environment variables and configuration files. For example, the RUSTFLAGS environment variable is "managed" by Cargo and not recognized by rustc. So, the following could occur:

PS C:\> $env:RUSTFLAGS="-C target-feature=+crt-static";
PS C:\> cargo rustc -- --print cfg
  Compiling <PACKAGE> vX.X.X (<PACKAGE_PATH>)
debug_assertions
target_arch="x86_64"
target_endian="little"
target_env="msvc"
target_family="windows"
target_feature="crt-static"
target_feature="fxsr"
target_feature="sse"
target_feature="sse2"
target_os="windows"
target_pointer_width="64"
target_vendor="pc"
windows
  Finished dev [unoptimized + debuginfo] target(s) in 0.10s
PS C:\> rustc --print cfg
debug_assertions
target_arch="x86_64"
target_endian="little"
target_env="msvc"
target_family="windows"
target_feature="fxsr"
target_feature="sse"
target_feature="sse2"
target_os="windows"
target_pointer_width="64"
target_vendor="pc"
windows

Note the existence of the target_feature="crt-static" in the output from the cargo rustc -- --print cfg command versus the output from the rustc --print cfg command, where the target_feature="crt-static line is missing.

There are also a couple of other issues with the above example. One, the cargo rustc -- --print cfg actually builds the package. It does not skip building the package, whereas the rustc --print cfg command simply prints the configuration and does not compile. Ideally, the cargo rustc -- --print cfg command would also not compile the entire package. Second, the format is human-readable, but it would also be nice to have more machine/subcommand readable format, such as JSON that also omits the "Compiling...." and "Finished..." lines. Third, the cargo rustc -- --print cfg command only works if a single Cargo target is defined for the package; otherwise, an error message appears indicating that passing arguments to the compiler requires a specific Cargo target, e.g. --lib or --bin <NAME>.

Much of this came about from developing the cargo-rustc-cfg crate for use in the cargo-wix subcommand, where we ultimately want to know if a user's project is statically linking the Windows C Runtime (CRT), provide information to WiX templates for conditional builds of Windows installers, and working on supporting cross-compilation, mostly between x86_64, i686, MSVC, and GNU rustc targets on Windows; hence, the Windows-centric examples.

I recognize this is closely related to the discussion around --build-plan flag, the cargo-metadata crate, and the --unit-graph flag. It is possible that I have missed some field or output in these that would yield similar information to the cargo rustc -- --print cfg command, but in my review the metadata output appears to be too high level and does not contain compiler configuration information and the --unit-graph output only has the platform field, which is the target triple (Side note, this will be useful for the cargo-wix subcommand once it is stabilized but won't get us everything we would like to have). I understand there is some hesitation to expose too much Cargo build internals and the multi-targets feature could be a complication.

Describe the solution you'd like

I currently see multiple solutions:

  1. Add a --cfg flag to the cargo rustc subcommand, so that the following would be possible:

    PS C:\> cargo rustc --cfg
    debug_assertions
    target_arch="x86_64"
    target_endian="little"
    target_env="msvc"
    target_family="windows"
    target_feature="fxsr"
    target_feature="sse"
    target_feature="sse2"
    target_os="windows"
    target_pointer_width="64"
    target_vendor="pc"
    windows

    This would not build the project but any compiler arguments from Cargo-related environment variables and/or configuration files (.cargo/config.toml) would be applied. I think having the flag instead of inspecting the <args> Rustc args values for a --print cfg would be easier to implement. I am open to alternative names for the flags as well, i.e. --print-cfg, --config, --print-config, etc. However, I do know that Cargo looks for the --target option in the <args> Rustc args and warns about targets being defined in two places, so some inspection already exists.

  2. If 1 is implemented, then possibly add an option to change the format of the output, i.e. --cfg-format=JSON or --cfg-json. I would actually be fine with defaulting the output to JSON and not having key-value line-based output format. I think this would require some parsing of the rustc <ADDITIONAL_CARGO_COMPILER_ARGS> --print cfg output from within Cargo as opposed to just "forwarding" the output to stdout. I could easily add the conversion to JSON to the cargo-rustc-cfg crate if "forwarding" is quicker and easier.

  3. Add the compiler configuration to the --unit-graph output. This seems appropriate but I am not sure how this fits in with the larger discussion, desires, and goals of the --unit-graph feature.

  4. Add the compiler configuration to the cargo-metadata output. This does not seem appropriate as the metadata appears to be more about the package configuration than the compiler configuration.

  5. A combination of 1, 2, and 3.

Notes

I am willing to help implement any of these items or new ones, but I wanted to gauge interest and check if I missed something in obtaining the compiler configuration from within a cargo subcommand.

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-feature-requestCategory: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted`

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions