autocfg

Struct AutoCfg

source
pub struct AutoCfg { /* private fields */ }
Expand description

Helper to detect compiler features for cfg output in build scripts.

Implementations§

source§

impl AutoCfg

source

pub fn new() -> Result<Self, Error>

Creates a new AutoCfg instance.

§Common errors
  • rustc can’t be executed, from RUSTC or in the PATH.
  • The version output from rustc can’t be parsed.
  • OUT_DIR is not set in the environment, or is not a writable directory.
source

pub fn with_dir<T: Into<PathBuf>>(dir: T) -> Result<Self, Error>

Creates a new AutoCfg instance with the specified output directory.

§Common errors
  • rustc can’t be executed, from RUSTC or in the PATH.
  • The version output from rustc can’t be parsed.
  • dir is not a writable directory.
Examples found in repository?
examples/versions.rs (line 5)
3
4
5
6
7
8
9
fn main() {
    // Normally, cargo will set `OUT_DIR` for build scripts.
    let ac = autocfg::AutoCfg::with_dir("target").unwrap();
    for i in 0..100 {
        ac.emit_rustc_version(1, i);
    }
}
More examples
Hide additional examples
examples/integers.rs (line 5)
3
4
5
6
7
8
9
fn main() {
    // Normally, cargo will set `OUT_DIR` for build scripts.
    let ac = autocfg::AutoCfg::with_dir("target").unwrap();
    for i in 3..8 {
        ac.emit_has_type(&format!("i{}", 1 << i));
    }
}
examples/nightly.rs (line 5)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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");
    }
}
examples/paths.rs (line 5)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
fn main() {
    // Normally, cargo will set `OUT_DIR` for build scripts.
    let ac = autocfg::AutoCfg::with_dir("target").unwrap();

    // since ancient times...
    ac.emit_has_path("std::vec::Vec");
    ac.emit_path_cfg("std::vec::Vec", "has_vec");

    // rustc 1.10.0
    ac.emit_has_path("std::panic::PanicInfo");
    ac.emit_path_cfg("std::panic::PanicInfo", "has_panic_info");

    // rustc 1.20.0
    ac.emit_has_path("std::mem::ManuallyDrop");
    ac.emit_path_cfg("std::mem::ManuallyDrop", "has_manually_drop");

    // rustc 1.25.0
    ac.emit_has_path("std::ptr::NonNull");
    ac.emit_path_cfg("std::ptr::NonNull", "has_non_null");
}
examples/traits.rs (line 5)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
fn main() {
    // Normally, cargo will set `OUT_DIR` for build scripts.
    let ac = autocfg::AutoCfg::with_dir("target").unwrap();

    // since ancient times...
    ac.emit_has_trait("std::ops::Add");
    ac.emit_trait_cfg("std::ops::Add", "has_ops");

    // trait parameters have to be provided
    ac.emit_has_trait("std::borrow::Borrow<str>");
    ac.emit_trait_cfg("std::borrow::Borrow<str>", "has_borrow");

    // rustc 1.8.0
    ac.emit_has_trait("std::ops::AddAssign");
    ac.emit_trait_cfg("std::ops::AddAssign", "has_assign_ops");

    // rustc 1.12.0
    ac.emit_has_trait("std::iter::Sum");
    ac.emit_trait_cfg("std::iter::Sum", "has_sum");

    // rustc 1.28.0
    ac.emit_has_trait("std::alloc::GlobalAlloc");
    ac.emit_trait_cfg("std::alloc::GlobalAlloc", "has_global_alloc");
}
source

pub fn no_std(&self) -> bool

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.

source

pub fn set_no_std(&mut self, no_std: bool)

Sets whether AutoCfg should use #![no_std] in its probes.

See also no_std.

source

pub fn probe_rustc_version(&self, major: usize, minor: usize) -> bool

Tests whether the current rustc reports a version greater than or equal to “major.minor”.

source

pub fn emit_rustc_version(&self, major: usize, minor: usize)

Sets a cfg value of the form rustc_major_minor, like rustc_1_29, if the current rustc is at least that version.

Examples found in repository?
examples/versions.rs (line 7)
3
4
5
6
7
8
9
fn main() {
    // Normally, cargo will set `OUT_DIR` for build scripts.
    let ac = autocfg::AutoCfg::with_dir("target").unwrap();
    for i in 0..100 {
        ac.emit_rustc_version(1, i);
    }
}
source

pub fn probe_raw(&self, code: &str) -> Result<(), Error>

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] 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.

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.

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");
}
Examples found in repository?
examples/nightly.rs (line 15)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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");
    }
}
source

pub fn probe_sysroot_crate(&self, name: &str) -> bool

Tests whether the given sysroot crate can be used.

The test code is subject to change, but currently looks like:

extern crate CRATE as probe;
source

pub fn emit_sysroot_crate(&self, name: &str)

Emits a config value has_CRATE if probe_sysroot_crate returns true.

source

pub fn probe_path(&self, path: &str) -> bool

Tests whether the given path can be used.

The test code is subject to change, but currently looks like:

pub use PATH;
source

pub fn emit_has_path(&self, path: &str)

Emits a config value has_PATH if probe_path returns true.

Any non-identifier characters in the path will be replaced with _ in the generated config value.

Examples found in repository?
examples/paths.rs (line 8)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
fn main() {
    // Normally, cargo will set `OUT_DIR` for build scripts.
    let ac = autocfg::AutoCfg::with_dir("target").unwrap();

    // since ancient times...
    ac.emit_has_path("std::vec::Vec");
    ac.emit_path_cfg("std::vec::Vec", "has_vec");

    // rustc 1.10.0
    ac.emit_has_path("std::panic::PanicInfo");
    ac.emit_path_cfg("std::panic::PanicInfo", "has_panic_info");

    // rustc 1.20.0
    ac.emit_has_path("std::mem::ManuallyDrop");
    ac.emit_path_cfg("std::mem::ManuallyDrop", "has_manually_drop");

    // rustc 1.25.0
    ac.emit_has_path("std::ptr::NonNull");
    ac.emit_path_cfg("std::ptr::NonNull", "has_non_null");
}
source

pub fn emit_path_cfg(&self, path: &str, cfg: &str)

Emits the given cfg value if probe_path returns true.

Examples found in repository?
examples/paths.rs (line 9)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
fn main() {
    // Normally, cargo will set `OUT_DIR` for build scripts.
    let ac = autocfg::AutoCfg::with_dir("target").unwrap();

    // since ancient times...
    ac.emit_has_path("std::vec::Vec");
    ac.emit_path_cfg("std::vec::Vec", "has_vec");

    // rustc 1.10.0
    ac.emit_has_path("std::panic::PanicInfo");
    ac.emit_path_cfg("std::panic::PanicInfo", "has_panic_info");

    // rustc 1.20.0
    ac.emit_has_path("std::mem::ManuallyDrop");
    ac.emit_path_cfg("std::mem::ManuallyDrop", "has_manually_drop");

    // rustc 1.25.0
    ac.emit_has_path("std::ptr::NonNull");
    ac.emit_path_cfg("std::ptr::NonNull", "has_non_null");
}
source

pub fn probe_trait(&self, name: &str) -> bool

Tests whether the given trait can be used.

The test code is subject to change, but currently looks like:

pub trait Probe: TRAIT + Sized {}
source

pub fn emit_has_trait(&self, name: &str)

Emits a config value has_TRAIT if probe_trait returns true.

Any non-identifier characters in the trait name will be replaced with _ in the generated config value.

Examples found in repository?
examples/traits.rs (line 8)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
fn main() {
    // Normally, cargo will set `OUT_DIR` for build scripts.
    let ac = autocfg::AutoCfg::with_dir("target").unwrap();

    // since ancient times...
    ac.emit_has_trait("std::ops::Add");
    ac.emit_trait_cfg("std::ops::Add", "has_ops");

    // trait parameters have to be provided
    ac.emit_has_trait("std::borrow::Borrow<str>");
    ac.emit_trait_cfg("std::borrow::Borrow<str>", "has_borrow");

    // rustc 1.8.0
    ac.emit_has_trait("std::ops::AddAssign");
    ac.emit_trait_cfg("std::ops::AddAssign", "has_assign_ops");

    // rustc 1.12.0
    ac.emit_has_trait("std::iter::Sum");
    ac.emit_trait_cfg("std::iter::Sum", "has_sum");

    // rustc 1.28.0
    ac.emit_has_trait("std::alloc::GlobalAlloc");
    ac.emit_trait_cfg("std::alloc::GlobalAlloc", "has_global_alloc");
}
source

pub fn emit_trait_cfg(&self, name: &str, cfg: &str)

Emits the given cfg value if probe_trait returns true.

Examples found in repository?
examples/traits.rs (line 9)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
fn main() {
    // Normally, cargo will set `OUT_DIR` for build scripts.
    let ac = autocfg::AutoCfg::with_dir("target").unwrap();

    // since ancient times...
    ac.emit_has_trait("std::ops::Add");
    ac.emit_trait_cfg("std::ops::Add", "has_ops");

    // trait parameters have to be provided
    ac.emit_has_trait("std::borrow::Borrow<str>");
    ac.emit_trait_cfg("std::borrow::Borrow<str>", "has_borrow");

    // rustc 1.8.0
    ac.emit_has_trait("std::ops::AddAssign");
    ac.emit_trait_cfg("std::ops::AddAssign", "has_assign_ops");

    // rustc 1.12.0
    ac.emit_has_trait("std::iter::Sum");
    ac.emit_trait_cfg("std::iter::Sum", "has_sum");

    // rustc 1.28.0
    ac.emit_has_trait("std::alloc::GlobalAlloc");
    ac.emit_trait_cfg("std::alloc::GlobalAlloc", "has_global_alloc");
}
source

pub fn probe_type(&self, name: &str) -> bool

Tests whether the given type can be used.

The test code is subject to change, but currently looks like:

pub type Probe = TYPE;
source

pub fn emit_has_type(&self, name: &str)

Emits a config value has_TYPE if probe_type returns true.

Any non-identifier characters in the type name will be replaced with _ in the generated config value.

Examples found in repository?
examples/integers.rs (line 7)
3
4
5
6
7
8
9
fn main() {
    // Normally, cargo will set `OUT_DIR` for build scripts.
    let ac = autocfg::AutoCfg::with_dir("target").unwrap();
    for i in 3..8 {
        ac.emit_has_type(&format!("i{}", 1 << i));
    }
}
source

pub fn emit_type_cfg(&self, name: &str, cfg: &str)

Emits the given cfg value if probe_type returns true.

source

pub fn probe_expression(&self, expr: &str) -> bool

Tests whether the given expression can be used.

The test code is subject to change, but currently looks like:

pub fn probe() { let _ = EXPR; }
source

pub fn emit_expression_cfg(&self, expr: &str, cfg: &str)

Emits the given cfg value if probe_expression returns true.

source

pub fn probe_constant(&self, expr: &str) -> bool

Tests whether the given constant expression can be used.

The test code is subject to change, but currently looks like:

pub const PROBE: () = ((), EXPR).0;
source

pub fn emit_constant_cfg(&self, expr: &str, cfg: &str)

Emits the given cfg value if probe_constant returns true.

Trait Implementations§

source§

impl Clone for AutoCfg

source§

fn clone(&self) -> AutoCfg

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for AutoCfg

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> ToOwned for T
where T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.