Skip to content

target.cfg doesn't support features #14306

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

Closed
cyphar opened this issue Jul 26, 2024 · 4 comments
Closed

target.cfg doesn't support features #14306

cyphar opened this issue Jul 26, 2024 · 4 comments
Labels
C-bug Category: bug S-triage Status: This issue is waiting on initial triage.

Comments

@cyphar
Copy link

cyphar commented Jul 26, 2024

Problem

I am working on a library which requires some tests to be run as root. However, only some of the tests actually need root and so I designed the test suite such that the tests that require root are only run when you actually have root. It seems the most rust-like way of doing this (given how restrictive libtest is) is to create a dummy feature _test_as_root and then do:

#[test]
#[cfg_attr(not(feature = "_test_as_root"), ignore)]
fn test_fn() {}

(The alternative is to make the test always pass if it is running as root, but this is less than ideal

Given that sudo cargo doesn't work in general, and is quite painful to get working, it would be ideal if I could just do this in CI:

% cargo test                          # runs as a regular user
% cargo test --features _test_as_root # runs as root

Using the suggestion from #5999 (comment), it seems like setting a runner with target.'cfg(feature = "_test_as_root") would work. However:

% cat .cargo/config
[target.'cfg(feature = "_test_as_root")']
runner = "sudo -E"
% cargo test --features _test_as_root
# the tests that require root fail because the tests don't run as root

If you use target.x86_64-unknown-linux-gnu it works. It seem that the cfg(feature=...) is never matched? Even if you change runner to false or some non-existent command the tests still run as if the setting wasn't there.

The docs states that the format of target.'cfg(...)' matches the conditional compilation spec (which includes reference to cfg(feature = ...) so it seems like this should work.

Steps

Run this script:

#!/bin/bash

set -xEeuo pipefail

cargo init --vcs none --lib example
pushd example

mkdir -p .cargo
cat >.cargo/config.toml <<EOF
[target.'cfg(feature = "_test_as_root")']
runner = "sudo -E"
EOF

cat >>Cargo.toml <<EOF
libc = "*"

[features]
_test_as_root = []
EOF

cat >>src/lib.rs <<EOF
#[test]
#[cfg_attr(not(feature = "_test_as_root"), ignore)]
fn test_only_as_root() {
    assert_eq!(unsafe { libc::geteuid() }, 0, "not running as root");
}
EOF

Then note that:

  • cargo test succeeds and test_only_as_root is ignored.
  • cargo test --features _test_as_root fails because the .cargo/config.toml had no effect.

Possible Solution(s)

Parse [target.'cfg(feature = ...)'] configurations? I don't know if there is some technical restriction that stops feature from being understood by cargo when parsing .cargo/config.toml.

Notes

In my particular case, using #5999 (comment) this issue can be worked around by using environment variables like so:

% cargo test 
% CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER='sudo -E' cargo test --features _test_as_root

But this is fairly ugly and unlike [target.'cfg(feature = "_test_as_root")'] the feature and test runner are now decoupled and so the test will no longer run as root on different targets.

Version

cargo 1.80.0 (376290515 2024-07-16)
release: 1.80.0
commit-hash: 37629051518c3df9ac2c1744589362a02ecafa99
commit-date: 2024-07-16
host: x86_64-unknown-linux-gnu
libgit2: 1.7.2 (sys:0.18.3 vendored)
libcurl: 8.6.0-DEV (sys:0.4.72+curl-8.6.0 vendored ssl:OpenSSL/1.1.1w)
ssl: OpenSSL 1.1.1w  11 Sep 2023
os: openSUSE 20240716.0.0 [64-bit]
@cyphar cyphar added C-bug Category: bug S-triage Status: This issue is waiting on initial triage. labels Jul 26, 2024
@weihanglo
Copy link
Member

Thank you for your detailed reproduction! target.cfg against Cargo features, test, and debug_assertions is not supported. See [target]:

cfg values come from those built-in to the compiler (run rustc --print=cfg to view), values set by build scripts, and extra --cfg flags passed to rustc (such as those defined in RUSTFLAGS). Do not try to match on debug_assertions or Cargo features like feature="foo".

This seems to be a duplicate of #8170. Close in favor of that. Let us know if there is any reason to keep it separately.

@weihanglo weihanglo closed this as not planned Won't fix, can't repro, duplicate, stale Jul 26, 2024
@cyphar
Copy link
Author

cyphar commented Jul 26, 2024

@weihanglo Ah, I missed that part of the docs. Sorry about that.

However, the docs say "values set by build scripts", but adding the following to build.rs and using [target.'cfg(_test_as_root)']:

if cfg!(feature = "_test_as_root") {
    println!("cargo::rustc-cfg=_test_as_root")
}

#8170 mentions that this is because the config is "once per cargo run". In that case, should the line about build scripts be removed from the docs? How else could you use a build script to modify the cfg?

In fact, even something like

[target.'cfg(test)']
runner = "sudo -E"

Doesn't work, which it seems like it should given the description in the docs.

@weihanglo
Copy link
Member

For cfg(test) it is worth mentioning since it is a source of of general confusion. Feel free to open a PR fixing that :)

For cargo::rustc-cfg I don't know why it is mentioned. Perhaps it is a documentation bug?
cc @ehuss if you know some history of this.

@ehuss
Copy link
Contributor

ehuss commented Jul 26, 2024

Looks like a mistake to me.

weihanglo added a commit to weihanglo/cargo that referenced this issue Jul 26, 2024
weihanglo added a commit to weihanglo/cargo that referenced this issue Sep 30, 2024
weihanglo added a commit to weihanglo/cargo that referenced this issue Sep 30, 2024
weihanglo added a commit to weihanglo/cargo that referenced this issue Sep 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: bug S-triage Status: This issue is waiting on initial triage.
Projects
None yet
Development

No branches or pull requests

3 participants