merge master into master

autocfg 升级到1.4.0

Created-by: dragonswordy
Commit-by: ljy9810
Merged-by: openharmony_ci
Description: ### 一、内容说明(相关的Issue)
https://gitcode.com/openharmony/third_party_rust_memoffset/issues/1

### 二、建议测试周期和提测地址  
  建议测试完成时间:xxxx.xx.xx  
  投产上线时间:xxxx.xx.xx  
  提测地址:CI环境/压测环境  
  测试账号:  

### 三、变更内容
  * 3.1 关联PR列表

  * 3.2 数据库和部署说明  
    1. 常规更新 
    2. 重启unicorn
    3. 重启sidekiq
    4. 迁移任务:是否有迁移任务,没有写 "无"
    5. rake脚本:`bundle exec xxx RAILS_ENV = production`;没有写 "无"

  * 3.4 其他技术优化内容(做了什么,变更了什么)
    - 重构了 xxxx 代码
    - xxxx 算法优化


  * 3.5 废弃通知(什么字段、方法弃用?)



  * 3.6  后向不兼容变更(是否有无法向后兼容的变更?)


  
### 四、研发自测点(自测哪些?冒烟用例全部自测?)
  自测测试结论:


### 五、测试关注点(需要提醒QA重点关注的、可能会忽略的地方)
  检查点:

| 需求名称 | 是否影响xx公共模块 | 是否需要xx功能 | 需求升级是否依赖其他子产品 |
|------|------------|----------|---------------|
| xxx  | 否          | 需要       | 不需要           |
|      |            |          |               |

  接口测试:

  性能测试:

  并发测试:

  其他:



See merge request: openharmony/third_party_rust_autocfg!3
This commit is contained in:
openharmony_ci
2025-09-01 20:25:29 +08:00
23 changed files with 740 additions and 345 deletions
+35 -56
View File
@@ -1,9 +1,9 @@
name: CI
on:
pull_request:
push:
branches:
- staging
- trying
- master
jobs:
@@ -13,85 +13,64 @@ jobs:
strategy:
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, stable, beta, nightly]
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:
- name: Checkout
uses: actions/checkout@v2
- name: Install
uses: actions-rs/toolchain@v1
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.rust }}
profile: minimal
override: true
- name: Build
uses: actions-rs/cargo@v1
with:
command: build
args: --verbose
- name: Test
uses: actions-rs/cargo@v1
with:
command: test
args: --verbose
- 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:
name: No Std
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Install
uses: actions-rs/toolchain@v1
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
target: thumbv6m-none-eabi
profile: minimal
override: true
- name: Test
- run: cargo test --verbose --lib
env:
TARGET: thumbv6m-none-eabi
uses: actions-rs/cargo@v1
with:
command: test
args: --verbose --lib
# we don't even need an installed target for version checks
missing_target:
name: Missing Target
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Install
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
override: true
- name: Test
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- run: cargo test --verbose --lib -- version
env:
TARGET: thumbv6m-none-eabi
uses: actions-rs/cargo@v1
with:
command: test
args: --verbose --lib -- version
fmt:
name: Format
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install
uses: actions-rs/toolchain@v1
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@1.77.0
with:
profile: minimal
toolchain: 1.58.1
override: true
components: rustfmt
- name: Check formatting
uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check
- run: cargo fmt --all --check
# One job that "summarizes" the success state of this pipeline. This can then be added to branch
# protection, rather than having to add each job separately.
success:
name: Success
runs-on: ubuntu-latest
needs: [test, no_std, missing_target, fmt]
# Github branch protection is exceedingly silly and treats "jobs skipped because a dependency
# failed" as success. So we have to do some contortions to ensure the job fails if any of its
# dependencies fails.
if: always() # make sure this is never "skipped"
steps:
# Manually check the status of all dependencies. `if: failure()` does not work.
- name: check if any dependency failed
run: jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}'
-35
View File
@@ -1,35 +0,0 @@
name: master
on:
push:
branches:
- master
schedule:
- cron: '0 0 * * 0' # 00:00 Sunday
jobs:
test:
name: Test
runs-on: ubuntu-latest
strategy:
matrix:
rust: [1.0.0, stable]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install
uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.rust }}
profile: minimal
override: true
- name: Build
uses: actions-rs/cargo@v1
with:
command: build
args: --verbose
- name: Test
uses: actions-rs/cargo@v1
with:
command: test
args: --verbose
-50
View File
@@ -1,50 +0,0 @@
name: PR
on:
pull_request:
jobs:
test:
name: Test
runs-on: ubuntu-latest
strategy:
matrix:
rust: [1.0.0, stable]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install
uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.rust }}
profile: minimal
override: true
- name: Build
uses: actions-rs/cargo@v1
with:
command: build
args: --verbose
- name: Test
uses: actions-rs/cargo@v1
with:
command: test
args: --verbose
fmt:
name: Format
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: 1.58.1
override: true
components: rustfmt
- name: Check formatting
uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check
+4 -2
View File
@@ -1,13 +1,15 @@
[package]
name = "autocfg"
version = "1.1.0"
version = "1.4.0"
authors = ["Josh Stone <cuviper@gmail.com>"]
license = "Apache-2.0 OR MIT"
repository = "https://github.com/cuviper/autocfg"
documentation = "https://docs.rs/autocfg/"
description = "Automatic cfg for Rust compiler features"
readme = "README.md"
keywords = ["rustc", "build", "autoconf"]
categories = ["development-tools::build-utils"]
exclude = ["/.github/**", "/bors.toml"]
exclude = ["/.github/**"]
rust-version = "1.0"
[dependencies]
+1 -1
View File
@@ -3,7 +3,7 @@
"Name": "autocfg",
"License": "Apache License V2.0, MIT",
"License File": "LICENSE-APACHE, LICENSE-MIT",
"Version Number": "1.1.0",
"Version Number": "1.4.0",
"Owner": "fangting12@huawei.com",
"Upstream URL": "https://github.com/cuviper/autocfg",
"Description": "A library that generates Rust code based on compile-time configuration options."
+19 -2
View File
@@ -43,6 +43,23 @@ should only be used when the compiler supports it.
## Release Notes
- 1.4.0 (2024-09-26)
- Add `emit_possibility` for Rust 1.80's [checked cfgs], and call that
automatically for methods that conditionally `emit`, by @Techcable.
[checked cfgs]: https://blog.rust-lang.org/2024/05/06/check-cfg.html
- 1.3.0 (2024-05-03)
- Add `probe_raw` for direct control of the code that will be test-compiled.
- Use wrappers when querying the `rustc` version information too.
- 1.2.0 (2024-03-25)
- Add `no_std` and `set_no_std` to control the use of `#![no_std]` in probes.
- Use `RUSTC_WRAPPER` and `RUSTC_WORKSPACE_WRAPPER` when they are set.
- 1.1.0 (2022-02-07)
- Use `CARGO_ENCODED_RUSTFLAGS` when it is set.
@@ -88,8 +105,8 @@ treated as a major breaking change for semver purposes.
This project is licensed under either of
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
http://www.apache.org/licenses/LICENSE-2.0)
https://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or
http://opensource.org/licenses/MIT)
https://opensource.org/licenses/MIT)
at your option.
-20
View File
@@ -1,20 +0,0 @@
status = [
"Test (1.0.0)",
"Test (1.5.0)",
"Test (1.10.0)",
"Test (1.15.0)",
"Test (1.20.0)",
"Test (1.25.0)",
"Test (1.30.0)",
"Test (1.35.0)",
"Test (1.40.0)",
"Test (1.45.0)",
"Test (1.50.0)",
"Test (1.55.0)",
"Test (stable)",
"Test (beta)",
"Test (nightly)",
"No Std",
"Missing Target",
"Format",
]
+3
View File
@@ -0,0 +1,3 @@
# Rust
/target
/Cargo.lock
+14
View File
@@ -0,0 +1,14 @@
[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 = "2015"
# only for testing
publish = false
build = "build.rs"
[build-dependencies]
autocfg = { path = "../.." }
+45
View File
@@ -0,0 +1,45 @@
extern crate autocfg;
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, std::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");
}
+43
View File
@@ -0,0 +1,43 @@
#![allow(unknown_lints)]
#![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,
);
}
+18
View File
@@ -0,0 +1,18 @@
extern crate autocfg;
fn main() {
// Normally, cargo will set `OUT_DIR` for build scripts.
let ac = autocfg::AutoCfg::with_dir("target").unwrap();
// When this feature was stabilized, it also renamed the method to
// `chunk_by`, so it's important to *use* the feature in your probe.
let code = r#"
#![feature(slice_group_by)]
pub fn probe(slice: &[i32]) -> impl Iterator<Item = &[i32]> {
slice.group_by(|a, b| a == b)
}
"#;
if ac.probe_raw(code).is_ok() {
autocfg::emit("has_slice_group_by");
}
}
+13 -1
View File
@@ -2,6 +2,7 @@ use std::error;
use std::fmt;
use std::io;
use std::num;
use std::process;
use std::str;
/// A common error type for the `autocfg` crate.
@@ -20,7 +21,7 @@ impl error::Error for Error {
ErrorKind::Io(ref e) => Some(e),
ErrorKind::Num(ref e) => Some(e),
ErrorKind::Utf8(ref e) => Some(e),
ErrorKind::Other(_) => None,
ErrorKind::Process(_) | ErrorKind::Other(_) => None,
}
}
}
@@ -31,6 +32,10 @@ impl fmt::Display for Error {
ErrorKind::Io(ref e) => e.fmt(f),
ErrorKind::Num(ref e) => e.fmt(f),
ErrorKind::Utf8(ref e) => e.fmt(f),
ErrorKind::Process(ref status) => {
// Same message as the newer `ExitStatusError`
write!(f, "process exited unsuccessfully: {}", status)
}
ErrorKind::Other(s) => s.fmt(f),
}
}
@@ -40,10 +45,17 @@ impl fmt::Display for Error {
enum ErrorKind {
Io(io::Error),
Num(num::ParseIntError),
Process(process::ExitStatus),
Utf8(str::Utf8Error),
Other(&'static str),
}
pub fn from_exit(status: process::ExitStatus) -> Error {
Error {
kind: ErrorKind::Process(status),
}
}
pub fn from_io(e: io::Error) -> Error {
Error {
kind: ErrorKind::Io(e),
+183 -46
View File
@@ -20,7 +20,8 @@
//!
//! fn main() {
//! # // Normally, cargo will set `OUT_DIR` for build scripts.
//! # std::env::set_var("OUT_DIR", "target");
//! # let exe = std::env::current_exe().unwrap();
//! # std::env::set_var("OUT_DIR", exe.parent().unwrap());
//! let ac = autocfg::new();
//! ac.emit_has_type("i128");
//!
@@ -61,10 +62,11 @@ macro_rules! try {
use std::env;
use std::ffi::OsString;
use std::fmt::Arguments;
use std::fs;
use std::io::{stderr, Write};
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use std::process::Stdio;
#[allow(deprecated)]
use std::sync::atomic::ATOMIC_USIZE_INIT;
use std::sync::atomic::{AtomicUsize, Ordering};
@@ -72,6 +74,9 @@ use std::sync::atomic::{AtomicUsize, Ordering};
mod error;
pub use error::Error;
mod rustc;
use rustc::Rustc;
mod version;
use version::Version;
@@ -82,11 +87,12 @@ mod tests;
#[derive(Clone, Debug)]
pub struct AutoCfg {
out_dir: PathBuf,
rustc: PathBuf,
rustc: Rustc,
rustc_version: Version,
target: Option<OsString>,
no_std: bool,
rustflags: Vec<String>,
uuid: u64,
}
/// Writes a config flag for rustc on standard out.
@@ -94,6 +100,12 @@ 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.
///
/// [check-cfg-flags]: https://blog.rust-lang.org/2024/05/06/check-cfg.html
pub fn emit(cfg: &str) {
println!("cargo:rustc-cfg={}", cfg);
}
@@ -119,7 +131,26 @@ pub fn rerun_env(var: &str) {
println!("cargo:rerun-if-env-changed={}", var);
}
/// Create a new `AutoCfg` instance.
/// Indicates to rustc that a config flag should not generate an [`unexpected_cfgs` warning][check-cfg-flags]
///
/// 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.
/// 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
///
@@ -129,7 +160,7 @@ pub fn new() -> AutoCfg {
}
impl AutoCfg {
/// Create a new `AutoCfg` instance.
/// Creates a new `AutoCfg` instance.
///
/// # Common errors
///
@@ -144,7 +175,7 @@ impl AutoCfg {
}
}
/// Create a new `AutoCfg` instance with the specified output directory.
/// Creates a new `AutoCfg` instance with the specified output directory.
///
/// # Common errors
///
@@ -153,9 +184,8 @@ impl AutoCfg {
/// - `dir` is not a writable directory.
///
pub fn with_dir<T: Into<PathBuf>>(dir: T) -> Result<Self, Error> {
let rustc = env::var_os("RUSTC").unwrap_or_else(|| "rustc".into());
let rustc: PathBuf = rustc.into();
let rustc_version = try!(Version::from_rustc(&rustc));
let rustc = Rustc::new();
let rustc_version = try!(rustc.version());
let target = env::var_os("TARGET");
@@ -173,14 +203,15 @@ impl AutoCfg {
rustc_version: rustc_version,
target: target,
no_std: false,
uuid: new_uuid(),
};
// Sanity check with and without `std`.
if !ac.probe("").unwrap_or(false) {
ac.no_std = true;
if !ac.probe("").unwrap_or(false) {
if !ac.probe_raw("").is_ok() {
if ac.probe_raw("#![no_std]").is_ok() {
ac.no_std = true;
} else {
// Neither worked, so assume nothing...
ac.no_std = false;
let warning = b"warning: autocfg could not probe for `std`\n";
stderr().write_all(warning).ok();
}
@@ -188,7 +219,34 @@ impl AutoCfg {
Ok(ac)
}
/// Test whether the current `rustc` reports a version greater than
/// Returns whether `AutoCfg` is using `#![no_std]` in its probes.
///
/// This is automatically detected during construction -- if an empty probe
/// fails while one with `#![no_std]` succeeds, then the attribute will be
/// used for all further probes. This is usually only necessary when the
/// `TARGET` lacks `std` altogether. If neither succeeds, `no_std` is not
/// set, but that `AutoCfg` will probably only work for version checks.
///
/// This attribute changes the implicit [prelude] from `std` to `core`,
/// which may affect the paths you need to use in other probes. It also
/// restricts some types that otherwise get additional methods in `std`,
/// like floating-point trigonometry and slice sorting.
///
/// See also [`set_no_std`](#method.set_no_std).
///
/// [prelude]: https://doc.rust-lang.org/reference/names/preludes.html#the-no_std-attribute
pub fn no_std(&self) -> bool {
self.no_std
}
/// Sets whether `AutoCfg` should use `#![no_std]` in its probes.
///
/// See also [`no_std`](#method.no_std).
pub fn set_no_std(&mut self, no_std: bool) {
self.no_std = no_std;
}
/// Tests whether the current `rustc` reports a version greater than
/// or equal to "`major`.`minor`".
pub fn probe_rustc_version(&self, major: usize, minor: usize) -> bool {
self.rustc_version >= Version::new(major, minor, 0)
@@ -197,20 +255,27 @@ 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);
}
}
fn probe<T: AsRef<[u8]>>(&self, code: T) -> Result<bool, Error> {
/// Returns a new (hopefully unique) crate name for probes.
fn new_crate_name(&self) -> String {
#[allow(deprecated)]
static ID: AtomicUsize = ATOMIC_USIZE_INIT;
let id = ID.fetch_add(1, Ordering::Relaxed);
let mut command = Command::new(&self.rustc);
format!("autocfg_{:016x}_{}", self.uuid, id)
}
fn probe_fmt<'a>(&self, source: Arguments<'a>) -> Result<(), Error> {
let mut command = self.rustc.command();
command
.arg("--crate-name")
.arg(format!("probe{}", id))
.arg(self.new_crate_name())
.arg("--crate-type=lib")
.arg("--out-dir")
.arg(&self.out_dir)
@@ -226,14 +291,71 @@ impl AutoCfg {
let mut child = try!(command.spawn().map_err(error::from_io));
let mut stdin = child.stdin.take().expect("rustc stdin");
if self.no_std {
try!(stdin.write_all(b"#![no_std]\n").map_err(error::from_io));
}
try!(stdin.write_all(code.as_ref()).map_err(error::from_io));
try!(stdin.write_fmt(source).map_err(error::from_io));
drop(stdin);
let status = try!(child.wait().map_err(error::from_io));
Ok(status.success())
match child.wait() {
Ok(status) if status.success() => Ok(()),
Ok(status) => Err(error::from_exit(status)),
Err(error) => Err(error::from_io(error)),
}
}
fn probe<'a>(&self, code: Arguments<'a>) -> bool {
let result = if self.no_std {
self.probe_fmt(format_args!("#![no_std]\n{}", code))
} else {
self.probe_fmt(code)
};
result.is_ok()
}
/// Tests whether the given code can be compiled as a Rust library.
///
/// This will only return `Ok` if the compiler ran and exited successfully,
/// per `ExitStatus::success()`.
/// The code is passed to the compiler exactly as-is, notably not even
/// adding the [`#![no_std]`][Self::no_std] attribute like other probes.
///
/// Raw probes are useful for testing functionality that's not yet covered
/// by the rest of the `AutoCfg` API. For example, the following attribute
/// **must** be used at the crate level, so it wouldn't work within the code
/// templates used by other `probe_*` methods.
///
/// ```
/// # extern crate autocfg;
/// # // Normally, cargo will set `OUT_DIR` for build scripts.
/// # let exe = std::env::current_exe().unwrap();
/// # std::env::set_var("OUT_DIR", exe.parent().unwrap());
/// let ac = autocfg::new();
/// assert!(ac.probe_raw("#![no_builtins]").is_ok());
/// ```
///
/// Rust nightly features could be tested as well -- ideally including a
/// code sample to ensure the unstable feature still works as expected.
/// For example, `slice::group_by` was renamed to `chunk_by` when it was
/// stabilized, even though the feature name was unchanged, so testing the
/// `#![feature(..)]` alone wouldn't reveal that. For larger snippets,
/// [`include_str!`] may be useful to load them from separate files.
///
/// ```
/// # extern crate autocfg;
/// # // Normally, cargo will set `OUT_DIR` for build scripts.
/// # let exe = std::env::current_exe().unwrap();
/// # std::env::set_var("OUT_DIR", exe.parent().unwrap());
/// let ac = autocfg::new();
/// let code = r#"
/// #![feature(slice_group_by)]
/// pub fn probe(slice: &[i32]) -> impl Iterator<Item = &[i32]> {
/// slice.group_by(|a, b| a == b)
/// }
/// "#;
/// if ac.probe_raw(code).is_ok() {
/// autocfg::emit("has_slice_group_by");
/// }
/// ```
pub fn probe_raw(&self, code: &str) -> Result<(), Error> {
self.probe_fmt(format_args!("{}", code))
}
/// Tests whether the given sysroot crate can be used.
@@ -244,14 +366,16 @@ impl AutoCfg {
/// extern crate CRATE as probe;
/// ```
pub fn probe_sysroot_crate(&self, name: &str) -> bool {
self.probe(format!("extern crate {} as probe;", name)) // `as _` wasn't stabilized until Rust 1.33
.unwrap_or(false)
// Note: `as _` wasn't stabilized until Rust 1.33
self.probe(format_args!("extern crate {} as probe;", name))
}
/// 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);
}
}
@@ -263,7 +387,7 @@ impl AutoCfg {
/// pub use PATH;
/// ```
pub fn probe_path(&self, path: &str) -> bool {
self.probe(format!("pub use {};", path)).unwrap_or(false)
self.probe(format_args!("pub use {};", path))
}
/// Emits a config value `has_PATH` if `probe_path` returns true.
@@ -271,13 +395,12 @@ 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) {
if self.probe_path(path) {
emit(&format!("has_{}", mangle(path)));
}
self.emit_path_cfg(path, &format!("has_{}", mangle(path)));
}
/// 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);
}
@@ -291,8 +414,7 @@ impl AutoCfg {
/// pub trait Probe: TRAIT + Sized {}
/// ```
pub fn probe_trait(&self, name: &str) -> bool {
self.probe(format!("pub trait Probe: {} + Sized {{}}", name))
.unwrap_or(false)
self.probe(format_args!("pub trait Probe: {} + Sized {{}}", name))
}
/// Emits a config value `has_TRAIT` if `probe_trait` returns true.
@@ -300,13 +422,12 @@ 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) {
if self.probe_trait(name) {
emit(&format!("has_{}", mangle(name)));
}
self.emit_trait_cfg(name, &format!("has_{}", mangle(name)));
}
/// 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);
}
@@ -320,8 +441,7 @@ impl AutoCfg {
/// pub type Probe = TYPE;
/// ```
pub fn probe_type(&self, name: &str) -> bool {
self.probe(format!("pub type Probe = {};", name))
.unwrap_or(false)
self.probe(format_args!("pub type Probe = {};", name))
}
/// Emits a config value `has_TYPE` if `probe_type` returns true.
@@ -329,13 +449,12 @@ 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) {
if self.probe_type(name) {
emit(&format!("has_{}", mangle(name)));
}
self.emit_type_cfg(name, &format!("has_{}", mangle(name)));
}
/// 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);
}
@@ -349,12 +468,12 @@ impl AutoCfg {
/// pub fn probe() { let _ = EXPR; }
/// ```
pub fn probe_expression(&self, expr: &str) -> bool {
self.probe(format!("pub fn probe() {{ let _ = {}; }}", expr))
.unwrap_or(false)
self.probe(format_args!("pub fn probe() {{ let _ = {}; }}", expr))
}
/// 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);
}
@@ -368,12 +487,12 @@ impl AutoCfg {
/// pub const PROBE: () = ((), EXPR).0;
/// ```
pub fn probe_constant(&self, expr: &str) -> bool {
self.probe(format!("pub const PROBE: () = ((), {}).0;", expr))
.unwrap_or(false)
self.probe(format_args!("pub const PROBE: () = ((), {}).0;", expr))
}
/// 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);
}
@@ -405,7 +524,7 @@ fn dir_contains_target(
cargo_target_dir
.to_str()
.map(|cargo_target_dir| dir.contains(&cargo_target_dir))
.map(|cargo_target_dir| dir.contains(cargo_target_dir))
})
})
.unwrap_or(false)
@@ -451,3 +570,21 @@ fn rustflags(target: &Option<OsString>, dir: &Path) -> Vec<String> {
Vec::new()
}
/// Generates a numeric ID to use in probe crate names.
///
/// This attempts to be random, within the constraints of Rust 1.0 and no dependencies.
fn new_uuid() -> u64 {
const FNV_OFFSET_BASIS: u64 = 0xcbf2_9ce4_8422_2325;
const FNV_PRIME: u64 = 0x100_0000_01b3;
// This set should have an actual random hasher.
let set: std::collections::HashSet<u64> = (0..256).collect();
// Feed the `HashSet`-shuffled order into FNV-1a.
let mut hash: u64 = FNV_OFFSET_BASIS;
for x in set {
hash = (hash ^ x).wrapping_mul(FNV_PRIME);
}
hash
}
+89
View File
@@ -0,0 +1,89 @@
use std::env;
use std::ffi::OsString;
use std::path::PathBuf;
use std::process::Command;
use super::error::Error;
use super::version::Version;
#[derive(Clone, Debug)]
pub struct Rustc {
rustc: PathBuf,
rustc_wrapper: Option<PathBuf>,
rustc_workspace_wrapper: Option<PathBuf>,
}
impl Rustc {
pub fn new() -> Self {
Rustc {
rustc: env::var_os("RUSTC")
.unwrap_or_else(|| "rustc".into())
.into(),
rustc_wrapper: get_rustc_wrapper(false),
rustc_workspace_wrapper: get_rustc_wrapper(true),
}
}
/// Build the command with possible wrappers.
pub fn command(&self) -> Command {
let mut rustc = self
.rustc_wrapper
.iter()
.chain(self.rustc_workspace_wrapper.iter())
.chain(Some(&self.rustc));
let mut command = Command::new(rustc.next().unwrap());
for arg in rustc {
command.arg(arg);
}
command
}
/// Try to get the `rustc` version.
pub fn version(&self) -> Result<Version, Error> {
// Some wrappers like clippy-driver don't pass through version commands,
// so we try to fall back to combinations without each wrapper.
macro_rules! try_version {
($command:expr) => {
if let Ok(value) = Version::from_command($command) {
return Ok(value);
}
};
}
let rustc = &self.rustc;
if let Some(ref rw) = self.rustc_wrapper {
if let Some(ref rww) = self.rustc_workspace_wrapper {
try_version!(Command::new(rw).args(&[rww, rustc]));
}
try_version!(Command::new(rw).arg(rustc));
}
if let Some(ref rww) = self.rustc_workspace_wrapper {
try_version!(Command::new(rww).arg(rustc));
}
Version::from_command(&mut Command::new(rustc))
}
}
fn get_rustc_wrapper(workspace: bool) -> Option<PathBuf> {
// We didn't really know whether the workspace wrapper is applicable until Cargo started
// deliberately setting or unsetting it in rust-lang/cargo#9601. We'll use the encoded
// rustflags as a proxy for that change for now, but we could instead check version 1.55.
if workspace && env::var_os("CARGO_ENCODED_RUSTFLAGS").is_none() {
return None;
}
let name = if workspace {
"RUSTC_WORKSPACE_WRAPPER"
} else {
"RUSTC_WRAPPER"
};
if let Some(wrapper) = env::var_os(name) {
// NB: `OsStr` didn't get `len` or `is_empty` until 1.9.
if wrapper != OsString::new() {
return Some(wrapper.into());
}
}
None
}
-120
View File
@@ -1,36 +1,5 @@
use super::AutoCfg;
use std::env;
use std::path::Path;
impl AutoCfg {
fn core_std(&self, path: &str) -> String {
let krate = if self.no_std { "core" } else { "std" };
format!("{}::{}", krate, path)
}
fn assert_std(&self, probe_result: bool) {
assert_eq!(!self.no_std, probe_result);
}
fn assert_min(&self, major: usize, minor: usize, probe_result: bool) {
assert_eq!(self.probe_rustc_version(major, minor), probe_result);
}
fn for_test() -> Result<Self, super::error::Error> {
match env::var_os("TESTS_TARGET_DIR") {
Some(d) => Self::with_dir(d),
None => Self::with_dir("target"),
}
}
}
#[test]
fn autocfg_version() {
let ac = AutoCfg::for_test().unwrap();
println!("version: {:?}", ac.rustc_version);
assert!(ac.probe_rustc_version(1, 0));
}
#[test]
fn version_cmp() {
use super::version::Version;
@@ -44,95 +13,6 @@ fn version_cmp() {
assert!(Version::new(2, 0, 0) > v123);
}
#[test]
fn probe_add() {
let ac = AutoCfg::for_test().unwrap();
let add = ac.core_std("ops::Add");
let add_rhs = add.clone() + "<i32>";
let add_rhs_output = add.clone() + "<i32, Output = i32>";
let dyn_add_rhs_output = "dyn ".to_string() + &*add_rhs_output;
assert!(ac.probe_path(&add));
assert!(ac.probe_trait(&add));
assert!(ac.probe_trait(&add_rhs));
assert!(ac.probe_trait(&add_rhs_output));
ac.assert_min(1, 27, ac.probe_type(&dyn_add_rhs_output));
}
#[test]
fn probe_as_ref() {
let ac = AutoCfg::for_test().unwrap();
let as_ref = ac.core_std("convert::AsRef");
let as_ref_str = as_ref.clone() + "<str>";
let dyn_as_ref_str = "dyn ".to_string() + &*as_ref_str;
assert!(ac.probe_path(&as_ref));
assert!(ac.probe_trait(&as_ref_str));
assert!(ac.probe_type(&as_ref_str));
ac.assert_min(1, 27, ac.probe_type(&dyn_as_ref_str));
}
#[test]
fn probe_i128() {
let ac = AutoCfg::for_test().unwrap();
let i128_path = ac.core_std("i128");
ac.assert_min(1, 26, ac.probe_path(&i128_path));
ac.assert_min(1, 26, ac.probe_type("i128"));
}
#[test]
fn probe_sum() {
let ac = AutoCfg::for_test().unwrap();
let sum = ac.core_std("iter::Sum");
let sum_i32 = sum.clone() + "<i32>";
let dyn_sum_i32 = "dyn ".to_string() + &*sum_i32;
ac.assert_min(1, 12, ac.probe_path(&sum));
ac.assert_min(1, 12, ac.probe_trait(&sum));
ac.assert_min(1, 12, ac.probe_trait(&sum_i32));
ac.assert_min(1, 12, ac.probe_type(&sum_i32));
ac.assert_min(1, 27, ac.probe_type(&dyn_sum_i32));
}
#[test]
fn probe_std() {
let ac = AutoCfg::for_test().unwrap();
ac.assert_std(ac.probe_sysroot_crate("std"));
}
#[test]
fn probe_alloc() {
let ac = AutoCfg::for_test().unwrap();
ac.assert_min(1, 36, ac.probe_sysroot_crate("alloc"));
}
#[test]
fn probe_bad_sysroot_crate() {
let ac = AutoCfg::for_test().unwrap();
assert!(!ac.probe_sysroot_crate("doesnt_exist"));
}
#[test]
fn probe_no_std() {
let ac = AutoCfg::for_test().unwrap();
assert!(ac.probe_type("i32"));
assert!(ac.probe_type("[i32]"));
ac.assert_std(ac.probe_type("Vec<i32>"));
}
#[test]
fn probe_expression() {
let ac = AutoCfg::for_test().unwrap();
assert!(ac.probe_expression(r#""test".trim_left()"#));
ac.assert_min(1, 30, ac.probe_expression(r#""test".trim_start()"#));
ac.assert_std(ac.probe_expression("[1, 2, 3].to_vec()"));
}
#[test]
fn probe_constant() {
let ac = AutoCfg::for_test().unwrap();
assert!(ac.probe_constant("1 + 2 + 3"));
ac.assert_min(1, 33, ac.probe_constant("{ let x = 1 + 2 + 3; x * x }"));
ac.assert_min(1, 39, ac.probe_constant(r#""test".len()"#));
}
#[test]
fn dir_does_not_contain_target() {
assert!(!super::dir_contains_target(
+11 -6
View File
@@ -1,4 +1,3 @@
use std::path::Path;
use std::process::Command;
use std::str;
@@ -22,9 +21,9 @@ impl Version {
}
}
pub fn from_rustc(rustc: &Path) -> Result<Self, Error> {
pub fn from_command(command: &mut Command) -> Result<Self, Error> {
// Get rustc's verbose version
let output = try!(Command::new(rustc)
let output = try!(command
.args(&["--version", "--verbose"])
.output()
.map_err(error::from_io));
@@ -47,9 +46,15 @@ impl Version {
// Split the version into semver components.
let mut iter = version.splitn(3, '.');
let major = try!(iter.next().ok_or(error::from_str("missing major version")));
let minor = try!(iter.next().ok_or(error::from_str("missing minor version")));
let patch = try!(iter.next().ok_or(error::from_str("missing patch version")));
let major = try!(iter
.next()
.ok_or_else(|| error::from_str("missing major version")));
let minor = try!(iter
.next()
.ok_or_else(|| error::from_str("missing minor version")));
let patch = try!(iter
.next()
.ok_or_else(|| error::from_str("missing patch version")));
Ok(Version::new(
try!(major.parse().map_err(error::from_num)),
+28
View File
@@ -0,0 +1,28 @@
extern crate autocfg;
use std::env;
mod support;
/// Tests that we can control the use of `#![no_std]`.
#[test]
fn no_std() {
// Clear the CI `TARGET`, if any, so we're just dealing with the
// host target which always has `std` available.
env::remove_var("TARGET");
// Use the same path as this test binary.
let out = support::out_dir();
let mut ac = autocfg::AutoCfg::with_dir(out.as_ref()).unwrap();
assert!(!ac.no_std());
assert!(ac.probe_path("std::mem"));
// `#![no_std]` was stabilized in Rust 1.6
if ac.probe_rustc_version(1, 6) {
ac.set_no_std(true);
assert!(ac.no_std());
assert!(!ac.probe_path("std::mem"));
assert!(ac.probe_path("core::mem"));
}
}
+7 -6
View File
@@ -2,18 +2,19 @@ extern crate autocfg;
use std::env;
mod support;
/// Tests that autocfg uses the RUSTFLAGS or CARGO_ENCODED_RUSTFLAGS
/// environment variables when running rustc.
#[test]
fn test_with_sysroot() {
// Use the same path as this test binary.
let dir = env::current_exe().unwrap().parent().unwrap().to_path_buf();
env::set_var("OUT_DIR", &format!("{}", dir.display()));
let dir = support::exe_dir();
let out = support::out_dir();
// If we have encoded rustflags, they take precedence, even if empty.
env::set_var("CARGO_ENCODED_RUSTFLAGS", "");
env::set_var("RUSTFLAGS", &format!("-L {}", dir.display()));
let ac = autocfg::AutoCfg::new().unwrap();
let ac = autocfg::AutoCfg::with_dir(out.as_ref()).unwrap();
assert!(ac.probe_sysroot_crate("std"));
assert!(!ac.probe_sysroot_crate("autocfg"));
@@ -22,12 +23,12 @@ fn test_with_sysroot() {
"CARGO_ENCODED_RUSTFLAGS",
&format!("-L\x1f{}", dir.display()),
);
let ac = autocfg::AutoCfg::new().unwrap();
let ac = autocfg::AutoCfg::with_dir(out.as_ref()).unwrap();
assert!(ac.probe_sysroot_crate("autocfg"));
// Try the old-style RUSTFLAGS, ensuring HOST != TARGET.
env::remove_var("CARGO_ENCODED_RUSTFLAGS");
env::set_var("HOST", "lol");
let ac = autocfg::AutoCfg::new().unwrap();
let ac = autocfg::AutoCfg::with_dir(out.as_ref()).unwrap();
assert!(ac.probe_sysroot_crate("autocfg"));
}
+21
View File
@@ -0,0 +1,21 @@
use std::borrow::Cow;
use std::env;
use std::path::{Path, PathBuf};
/// The directory containing this test binary.
pub fn exe_dir() -> PathBuf {
let exe = env::current_exe().unwrap();
exe.parent().unwrap().to_path_buf()
}
/// The directory to use for test probes.
pub fn out_dir() -> Cow<'static, Path> {
if let Some(tmpdir) = option_env!("CARGO_TARGET_TMPDIR") {
Cow::Borrowed(tmpdir.as_ref())
} else if let Some(tmpdir) = env::var_os("TESTS_TARGET_DIR") {
Cow::Owned(tmpdir.into())
} else {
// Use the same path as this test binary.
Cow::Owned(exe_dir())
}
}
+138
View File
@@ -0,0 +1,138 @@
extern crate autocfg;
use autocfg::AutoCfg;
mod support;
fn core_std(ac: &AutoCfg, path: &str) -> String {
let krate = if ac.no_std() { "core" } else { "std" };
format!("{}::{}", krate, path)
}
fn assert_std(ac: &AutoCfg, probe_result: bool) {
assert_eq!(!ac.no_std(), probe_result);
}
fn assert_min(ac: &AutoCfg, major: usize, minor: usize, probe_result: bool) {
assert_eq!(ac.probe_rustc_version(major, minor), probe_result);
}
fn autocfg_for_test() -> AutoCfg {
AutoCfg::with_dir(support::out_dir().as_ref()).unwrap()
}
#[test]
fn autocfg_version() {
let ac = autocfg_for_test();
assert!(ac.probe_rustc_version(1, 0));
}
#[test]
fn probe_add() {
let ac = autocfg_for_test();
let add = core_std(&ac, "ops::Add");
let add_rhs = add.clone() + "<i32>";
let add_rhs_output = add.clone() + "<i32, Output = i32>";
let dyn_add_rhs_output = "dyn ".to_string() + &*add_rhs_output;
assert!(ac.probe_path(&add));
assert!(ac.probe_trait(&add));
assert!(ac.probe_trait(&add_rhs));
assert!(ac.probe_trait(&add_rhs_output));
assert_min(&ac, 1, 27, ac.probe_type(&dyn_add_rhs_output));
}
#[test]
fn probe_as_ref() {
let ac = autocfg_for_test();
let as_ref = core_std(&ac, "convert::AsRef");
let as_ref_str = as_ref.clone() + "<str>";
let dyn_as_ref_str = "dyn ".to_string() + &*as_ref_str;
assert!(ac.probe_path(&as_ref));
assert!(ac.probe_trait(&as_ref_str));
assert!(ac.probe_type(&as_ref_str));
assert_min(&ac, 1, 27, ac.probe_type(&dyn_as_ref_str));
}
#[test]
fn probe_i128() {
let ac = autocfg_for_test();
let i128_path = core_std(&ac, "i128");
assert_min(&ac, 1, 26, ac.probe_path(&i128_path));
assert_min(&ac, 1, 26, ac.probe_type("i128"));
}
#[test]
fn probe_sum() {
let ac = autocfg_for_test();
let sum = core_std(&ac, "iter::Sum");
let sum_i32 = sum.clone() + "<i32>";
let dyn_sum_i32 = "dyn ".to_string() + &*sum_i32;
assert_min(&ac, 1, 12, ac.probe_path(&sum));
assert_min(&ac, 1, 12, ac.probe_trait(&sum));
assert_min(&ac, 1, 12, ac.probe_trait(&sum_i32));
assert_min(&ac, 1, 12, ac.probe_type(&sum_i32));
assert_min(&ac, 1, 27, ac.probe_type(&dyn_sum_i32));
}
#[test]
fn probe_std() {
let ac = autocfg_for_test();
assert_std(&ac, ac.probe_sysroot_crate("std"));
}
#[test]
fn probe_alloc() {
let ac = autocfg_for_test();
assert_min(&ac, 1, 36, ac.probe_sysroot_crate("alloc"));
}
#[test]
fn probe_bad_sysroot_crate() {
let ac = autocfg_for_test();
assert!(!ac.probe_sysroot_crate("doesnt_exist"));
}
#[test]
fn probe_no_std() {
let ac = autocfg_for_test();
assert!(ac.probe_type("i32"));
assert!(ac.probe_type("[i32]"));
assert_std(&ac, ac.probe_type("Vec<i32>"));
}
#[test]
fn probe_expression() {
let ac = autocfg_for_test();
assert!(ac.probe_expression(r#""test".trim_left()"#));
assert_min(&ac, 1, 30, ac.probe_expression(r#""test".trim_start()"#));
assert_std(&ac, ac.probe_expression("[1, 2, 3].to_vec()"));
}
#[test]
fn probe_constant() {
let ac = autocfg_for_test();
assert!(ac.probe_constant("1 + 2 + 3"));
assert_min(
&ac,
1,
33,
ac.probe_constant("{ let x = 1 + 2 + 3; x * x }"),
);
assert_min(&ac, 1, 39, ac.probe_constant(r#""test".len()"#));
}
#[test]
fn probe_raw() {
let ac = autocfg_for_test();
let prefix = if ac.no_std() { "#![no_std]\n" } else { "" };
let f = |s| format!("{}{}", prefix, s);
// This attribute **must** be used at the crate level.
assert!(ac.probe_raw(&f("#![no_builtins]")).is_ok());
assert!(ac.probe_raw(&f("#![deny(dead_code)] fn x() {}")).is_err());
assert!(ac.probe_raw(&f("#![allow(dead_code)] fn x() {}")).is_ok());
assert!(ac
.probe_raw(&f("#![deny(dead_code)] pub fn x() {}"))
.is_ok());
}
+12
View File
@@ -0,0 +1,12 @@
#!/bin/bash
for arg in "$@"; do
case "$arg" in
# Add our own version so we can check that the wrapper is used for that.
"--version") echo "release: 12345.6789.0" ;;
# Read all input so the writer doesn't get EPIPE when we exit.
"-") read -d "" PROBE ;;
esac
done
exit 0
+56
View File
@@ -0,0 +1,56 @@
extern crate autocfg;
use std::env;
mod support;
/// Tests that autocfg uses the RUSTC_WRAPPER and/or RUSTC_WORKSPACE_WRAPPER
/// environment variables when running rustc.
#[test]
#[cfg(unix)] // we're using system binaries as wrappers
fn test_wrappers() {
fn set(name: &str, value: Option<bool>) {
match value {
Some(true) => env::set_var(name, "/usr/bin/env"),
Some(false) => env::set_var(name, "/bin/false"),
None => env::remove_var(name),
}
}
let out = support::out_dir();
// This is used as a heuristic to detect rust-lang/cargo#9601.
env::set_var("CARGO_ENCODED_RUSTFLAGS", "");
// No wrapper, a good pass-through wrapper, and a bad wrapper.
let variants = [None, Some(true), Some(false)];
for &workspace in &variants {
for &rustc in &variants {
set("RUSTC_WRAPPER", rustc);
set("RUSTC_WORKSPACE_WRAPPER", workspace);
let ac = autocfg::AutoCfg::with_dir(out.as_ref()).unwrap();
if rustc == Some(false) || workspace == Some(false) {
// Everything should fail with bad wrappers.
assert!(!ac.probe_type("usize"));
} else {
// Try known good and bad types for the wrapped rustc.
assert!(ac.probe_type("usize"));
assert!(!ac.probe_type("mesize"));
}
// Either way, we should have found the inner rustc version.
assert!(ac.probe_rustc_version(1, 0));
}
}
// Finally, make sure that `RUSTC_WRAPPER` is applied outermost
// by using something that doesn't pass through at all.
env::set_var("RUSTC_WRAPPER", "./tests/wrap_ignored");
env::set_var("RUSTC_WORKSPACE_WRAPPER", "/bin/false");
let ac = autocfg::AutoCfg::with_dir(out.as_ref()).unwrap();
assert!(ac.probe_type("mesize")); // anything goes!
// Make sure we also got the version from that wrapper.
assert!(ac.probe_rustc_version(12345, 6789));
}