From e0e0f18f54fb60f9c42a01c6571edcdab4542db6 Mon Sep 17 00:00:00 2001 From: Techcable Date: Mon, 9 Sep 2024 22:15:25 -0700 Subject: [PATCH 1/6] Automatically emit `rustc-check-cfg` directives for AutoCfg This avoids the `unexpected_cfgs` lint for any of the configs emitted by AutoCfg methods. This lint is new in Rust 1.80: This adds a `emit_possibility` method to mirror the `emit` method. Calling `emit` manually does not call `emit_possibility`. Fixes issue #64 --- src/lib.rs | 48 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index d117b9d..b4ad8d1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -100,6 +100,10 @@ pub struct AutoCfg { /// This looks like: `cargo:rustc-cfg=CFG` /// /// Cargo will use this in arguments to rustc, like `--cfg CFG`. +/// +/// This does not automatically call [`emit_possibility`] +/// so the compiler my generate an [`unexpected_cfgs` warning][check-cfg-flags]. +/// However, all the builtin emit methods on [`AutoCfg`] call [`emit_possibility`] automatically. pub fn emit(cfg: &str) { println!("cargo:rustc-cfg={}", cfg); } @@ -125,6 +129,25 @@ pub fn rerun_env(var: &str) { println!("cargo:rerun-if-env-changed={}", var); } +/// Indicates to rustc that a config flag should not generate an [`unexpected_cfgs` warning][check-cfg-flags] +/// +/// This looks like `cargo:cargo:rustc-check-cfg=cfg(VAR)` +/// +/// As of rust 1.80, the compiler does [automatic checking of cfgs at compile time][check-cfg-flags]. +/// All custom configuration flags must be known to rustc, or they will generate a warning. +/// This is done automatically when calling the builtin emit methods on [`AutoCfg`], +/// but not when calling [`autocfg::emit`](crate::emit) directly. +/// +/// Versions before rust 1.80 will simply ignore this directive. +/// +/// This function indicates to the compiler that the config flag never has a value. +/// If this is not desired, see [the blog post][check-cfg]. +/// +/// [check-cfg-flags]: https://blog.rust-lang.org/2024/05/06/check-cfg.html +pub fn emit_possibility(cfg: &str) { + println!("cargo:rustc-check-cfg=cfg({})", cfg); +} + /// Creates a new `AutoCfg` instance. /// /// # Panics @@ -230,8 +253,10 @@ impl AutoCfg { /// Sets a `cfg` value of the form `rustc_major_minor`, like `rustc_1_29`, /// if the current `rustc` is at least that version. pub fn emit_rustc_version(&self, major: usize, minor: usize) { + let cfg_flag = format!("rustc_{}_{}", major, minor); + emit_possibility(&cfg_flag); if self.probe_rustc_version(major, minor) { - emit(&format!("rustc_{}_{}", major, minor)); + emit(&cfg_flag); } } @@ -345,8 +370,10 @@ impl AutoCfg { /// Emits a config value `has_CRATE` if `probe_sysroot_crate` returns true. pub fn emit_sysroot_crate(&self, name: &str) { + let cfg_flag = format!("has_{}", mangle(name)); + emit_possibility(&cfg_flag); if self.probe_sysroot_crate(name) { - emit(&format!("has_{}", mangle(name))); + emit(&cfg_flag); } } @@ -366,13 +393,16 @@ impl AutoCfg { /// Any non-identifier characters in the `path` will be replaced with /// `_` in the generated config value. pub fn emit_has_path(&self, path: &str) { + let cfg_flag = format!("has_{}", mangle(path)); + emit_possibility(&cfg_flag); if self.probe_path(path) { - emit(&format!("has_{}", mangle(path))); + emit(&cfg_flag); } } /// Emits the given `cfg` value if `probe_path` returns true. pub fn emit_path_cfg(&self, path: &str, cfg: &str) { + emit_possibility(cfg); if self.probe_path(path) { emit(cfg); } @@ -394,13 +424,16 @@ impl AutoCfg { /// Any non-identifier characters in the trait `name` will be replaced with /// `_` in the generated config value. pub fn emit_has_trait(&self, name: &str) { + let cfg_flag = format!("has_{}", mangle(name)); + emit_possibility(&cfg_flag); if self.probe_trait(name) { - emit(&format!("has_{}", mangle(name))); + emit(&cfg_flag); } } /// Emits the given `cfg` value if `probe_trait` returns true. pub fn emit_trait_cfg(&self, name: &str, cfg: &str) { + emit_possibility(cfg); if self.probe_trait(name) { emit(cfg); } @@ -422,13 +455,16 @@ impl AutoCfg { /// Any non-identifier characters in the type `name` will be replaced with /// `_` in the generated config value. pub fn emit_has_type(&self, name: &str) { + let cfg_flag = format!("has_{}", mangle(name)); + emit_possibility(&cfg_flag); if self.probe_type(name) { - emit(&format!("has_{}", mangle(name))); + emit(&cfg_flag); } } /// Emits the given `cfg` value if `probe_type` returns true. pub fn emit_type_cfg(&self, name: &str, cfg: &str) { + emit_possibility(cfg); if self.probe_type(name) { emit(cfg); } @@ -447,6 +483,7 @@ impl AutoCfg { /// Emits the given `cfg` value if `probe_expression` returns true. pub fn emit_expression_cfg(&self, expr: &str, cfg: &str) { + emit_possibility(cfg); if self.probe_expression(expr) { emit(cfg); } @@ -465,6 +502,7 @@ impl AutoCfg { /// Emits the given `cfg` value if `probe_constant` returns true. pub fn emit_constant_cfg(&self, expr: &str, cfg: &str) { + emit_possibility(cfg); if self.probe_constant(expr) { emit(cfg); } From 546f7c6c1c0e25b2dca136675934348118f603d2 Mon Sep 17 00:00:00 2001 From: Techcable Date: Thu, 19 Sep 2024 11:11:46 -0700 Subject: [PATCH 2/6] Fix minor doc issues Misisng link and incorrect `cargo:cargo:...` prefix --- src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index b4ad8d1..882dba4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -104,6 +104,8 @@ pub struct AutoCfg { /// This does not automatically call [`emit_possibility`] /// so the compiler my generate an [`unexpected_cfgs` warning][check-cfg-flags]. /// However, all the builtin emit methods on [`AutoCfg`] call [`emit_possibility`] automatically. +/// +/// [check-cfg-flags]: https://blog.rust-lang.org/2024/05/06/check-cfg.html pub fn emit(cfg: &str) { println!("cargo:rustc-cfg={}", cfg); } @@ -131,7 +133,7 @@ pub fn rerun_env(var: &str) { /// Indicates to rustc that a config flag should not generate an [`unexpected_cfgs` warning][check-cfg-flags] /// -/// This looks like `cargo:cargo:rustc-check-cfg=cfg(VAR)` +/// This looks like `cargo:rustc-check-cfg=cfg(VAR)` /// /// As of rust 1.80, the compiler does [automatic checking of cfgs at compile time][check-cfg-flags]. /// All custom configuration flags must be known to rustc, or they will generate a warning. From 0b4a7617ad0e6ccf271dac7ab920a731195fab32 Mon Sep 17 00:00:00 2001 From: Techcable Date: Thu, 19 Sep 2024 11:18:53 -0700 Subject: [PATCH 3/6] Have emit_has methods delegate wherever possible Per request of @cuviper in PR #70 --- src/lib.rs | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 882dba4..fc3c59b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -395,11 +395,7 @@ impl AutoCfg { /// Any non-identifier characters in the `path` will be replaced with /// `_` in the generated config value. pub fn emit_has_path(&self, path: &str) { - let cfg_flag = format!("has_{}", mangle(path)); - emit_possibility(&cfg_flag); - if self.probe_path(path) { - emit(&cfg_flag); - } + self.emit_path_cfg(path, &format!("has_{}", mangle(path))); } /// Emits the given `cfg` value if `probe_path` returns true. @@ -426,11 +422,7 @@ impl AutoCfg { /// Any non-identifier characters in the trait `name` will be replaced with /// `_` in the generated config value. pub fn emit_has_trait(&self, name: &str) { - let cfg_flag = format!("has_{}", mangle(name)); - emit_possibility(&cfg_flag); - if self.probe_trait(name) { - emit(&cfg_flag); - } + self.emit_trait_cfg(name, &format!("has_{}", mangle(name))); } /// Emits the given `cfg` value if `probe_trait` returns true. @@ -457,11 +449,7 @@ impl AutoCfg { /// Any non-identifier characters in the type `name` will be replaced with /// `_` in the generated config value. pub fn emit_has_type(&self, name: &str) { - let cfg_flag = format!("has_{}", mangle(name)); - emit_possibility(&cfg_flag); - if self.probe_type(name) { - emit(&cfg_flag); - } + self.emit_type_cfg(name, &format!("has_{}", mangle(name))); } /// Emits the given `cfg` value if `probe_type` returns true. From ac78be804dbcf9e616d69a93c0ba918adc6a003a Mon Sep 17 00:00:00 2001 From: Techcable Date: Thu, 19 Sep 2024 11:58:57 -0700 Subject: [PATCH 4/6] Add ci test crate for check-cfg --- .github/workflows/ci.yaml | 3 +++ ci/verify-check-cfg/.gitignore | 3 +++ ci/verify-check-cfg/Cargo.toml | 12 +++++++++ ci/verify-check-cfg/build.rs | 43 +++++++++++++++++++++++++++++++++ ci/verify-check-cfg/src/main.rs | 42 ++++++++++++++++++++++++++++++++ 5 files changed, 103 insertions(+) create mode 100644 ci/verify-check-cfg/.gitignore create mode 100644 ci/verify-check-cfg/Cargo.toml create mode 100644 ci/verify-check-cfg/build.rs create mode 100644 ci/verify-check-cfg/src/main.rs diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 147e669..c38bd54 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -14,6 +14,7 @@ jobs: matrix: rust: [1.0.0, 1.5.0, 1.10.0, 1.15.0, 1.20.0, 1.25.0, 1.30.0, 1.35.0, 1.40.0, 1.45.0, 1.50.0, 1.55.0, 1.60.0, 1.65.0, 1.70.0, 1.75.0, + 1.80.0, # first version with rustc-check-cfg stable, beta, nightly] steps: - uses: actions/checkout@v4 @@ -22,6 +23,8 @@ jobs: toolchain: ${{ matrix.rust }} - run: cargo build --verbose - run: cargo test --verbose + - run: cargo run + working-directory: ./ci/verify-check-cfg # try probing a target that doesn't have std at all no_std: diff --git a/ci/verify-check-cfg/.gitignore b/ci/verify-check-cfg/.gitignore new file mode 100644 index 0000000..4683d3e --- /dev/null +++ b/ci/verify-check-cfg/.gitignore @@ -0,0 +1,3 @@ +# Rust +/target +/Cargo.lock diff --git a/ci/verify-check-cfg/Cargo.toml b/ci/verify-check-cfg/Cargo.toml new file mode 100644 index 0000000..7602ccd --- /dev/null +++ b/ci/verify-check-cfg/Cargo.toml @@ -0,0 +1,12 @@ +[package] +# NOTE: Cannot be in workspace because of rustc 1.0 support +name = "autocfg-verify-check-cfg" +description = "A dummy crate to verify autocfg is emitting check-cfg directives" +version = "0.1.0" +edition = "2021" +# only for testing +publish = false + +[build-dependencies] +autocfg = { path = "../.." } + diff --git a/ci/verify-check-cfg/build.rs b/ci/verify-check-cfg/build.rs new file mode 100644 index 0000000..9df82c0 --- /dev/null +++ b/ci/verify-check-cfg/build.rs @@ -0,0 +1,43 @@ +pub fn main() { + let cfg = autocfg::AutoCfg::new().unwrap(); + + // + // tests + // + + // always true + cfg.emit_rustc_version(1, 0); + // should always be false + cfg.emit_rustc_version(7, u32::MAX as usize); + + // always true + cfg.emit_has_path("std::vec::Vec"); + cfg.emit_path_cfg("std::vec::Vec", "has_path_std_vec"); + // always false + cfg.emit_has_path("dummy::DummyPath"); + cfg.emit_path_cfg("dummy::DummyPath", "has_path_dummy"); + + // always true + cfg.emit_has_trait("std::ops::Add"); + cfg.emit_trait_cfg("std::ops::Add", "has_trait_add"); + // always false + cfg.emit_has_trait("dummy::DummyTrait"); + cfg.emit_trait_cfg("dummy::DummyTrait", "has_trait_dummy"); + + // always true + cfg.emit_has_type("i32"); + cfg.emit_type_cfg("i32", "has_type_i32"); + // always false + cfg.emit_has_type("i7billion"); + cfg.emit_type_cfg("i7billion", "has_type_i7billion"); + + // always true + cfg.emit_expression_cfg("3 + 7", "has_working_addition"); + // always false + cfg.emit_expression_cfg("3 ^^^^^ 12", "has_working_5xor"); + + // always true + cfg.emit_constant_cfg("7", "has_const_7"); + // false - Opening file should never be `const` + cfg.emit_constant_cfg("std::fs::File::open(\"foo.txt\")", "has_const_file_open"); +} diff --git a/ci/verify-check-cfg/src/main.rs b/ci/verify-check-cfg/src/main.rs new file mode 100644 index 0000000..9df9f40 --- /dev/null +++ b/ci/verify-check-cfg/src/main.rs @@ -0,0 +1,42 @@ +#![deny(unexpected_cfgs)] + +macro_rules! test_cfgs { + ($($cfg:ident,)*) => {$({ + let cfg_desc = format!("cfg!({})", stringify!($cfg)); + if cfg!($cfg) { + println!("Enabled: {}", cfg_desc); + } else { + println!("Disabled: {}", cfg_desc); + } + })*}; + +} + +pub fn main() { + test_cfgs!( + // emit_rustc_version + rustc_1_0, + rustc_7_4294967295, + // emit_has_path, emit_path_cfg + has_std__vec__Vec, + has_path_std_vec, + has_dummy__DummyPath, + has_path_dummy, + // emit_has_trait, emit_trait_cfg + has_std__ops__Add, + has_trait_add, + has_dummy__DummyTrait, + has_trait_dummy, + // emit_has_type, has_type_i32 + has_i32, + has_type_i32, + has_i7billion, + has_type_i7billion, + // emit_expression_cfg + has_working_addition, + has_working_5xor, + // emit_constant_cfg + has_const_7, + has_const_file_open, + ); +} From a8703c163f5aa66819f515356530420955374386 Mon Sep 17 00:00:00 2001 From: Techcable Date: Thu, 19 Sep 2024 22:01:41 -0700 Subject: [PATCH 5/6] Attempt rust 1.0 compat for ci/verify-check-cfg I can't use rust 1.0 on my computer (M1 Mac), so I am relying on CI to check this. --- ci/verify-check-cfg/Cargo.toml | 2 +- ci/verify-check-cfg/build.rs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ci/verify-check-cfg/Cargo.toml b/ci/verify-check-cfg/Cargo.toml index 7602ccd..2da55fa 100644 --- a/ci/verify-check-cfg/Cargo.toml +++ b/ci/verify-check-cfg/Cargo.toml @@ -3,7 +3,7 @@ name = "autocfg-verify-check-cfg" description = "A dummy crate to verify autocfg is emitting check-cfg directives" version = "0.1.0" -edition = "2021" +edition = "2015" # only for testing publish = false diff --git a/ci/verify-check-cfg/build.rs b/ci/verify-check-cfg/build.rs index 9df82c0..76098b7 100644 --- a/ci/verify-check-cfg/build.rs +++ b/ci/verify-check-cfg/build.rs @@ -1,3 +1,5 @@ +extern crate autocfg; + pub fn main() { let cfg = autocfg::AutoCfg::new().unwrap(); @@ -8,7 +10,7 @@ pub fn main() { // always true cfg.emit_rustc_version(1, 0); // should always be false - cfg.emit_rustc_version(7, u32::MAX as usize); + cfg.emit_rustc_version(7, std::u32::MAX as usize); // always true cfg.emit_has_path("std::vec::Vec"); From 52a995b6723ae015fbed7312d56803492f01e10a Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 26 Sep 2024 17:45:37 -0700 Subject: [PATCH 6/6] Apply suggestions from code review --- ci/verify-check-cfg/Cargo.toml | 2 ++ ci/verify-check-cfg/src/main.rs | 1 + 2 files changed, 3 insertions(+) diff --git a/ci/verify-check-cfg/Cargo.toml b/ci/verify-check-cfg/Cargo.toml index 2da55fa..23817a4 100644 --- a/ci/verify-check-cfg/Cargo.toml +++ b/ci/verify-check-cfg/Cargo.toml @@ -7,6 +7,8 @@ edition = "2015" # only for testing publish = false +build = "build.rs" + [build-dependencies] autocfg = { path = "../.." } diff --git a/ci/verify-check-cfg/src/main.rs b/ci/verify-check-cfg/src/main.rs index 9df9f40..1b459b8 100644 --- a/ci/verify-check-cfg/src/main.rs +++ b/ci/verify-check-cfg/src/main.rs @@ -1,3 +1,4 @@ +#![allow(unknown_lints)] #![deny(unexpected_cfgs)] macro_rules! test_cfgs {