Skip to content

Commit 3e88901

Browse files
committed
cpubits: add cfg(cpubits = "...") override
Adds support for setting a `cfg` to override the automatic target-based detection in the `cpubits!` macro and explicitly specify what bit size should be used.
1 parent b0e2a8f commit 3e88901

File tree

3 files changed

+119
-25
lines changed

3 files changed

+119
-25
lines changed

.github/workflows/cpubits.yml

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,27 +21,38 @@ jobs:
2121
strategy:
2222
matrix:
2323
include:
24-
# 32-bit Linux
24+
# `aarch64` Linux
25+
- target: aarch64-unknown-linux-gnu
26+
rust: 1.85.0 # MSRV
27+
runner: ubuntu-24.04-arm
28+
- target: aarch64-unknown-linux-gnu
29+
rust: stable
30+
runner: ubuntu-24.04-arm
31+
32+
# `aarch64` macOS
33+
- target: aarch64-apple-darwin
34+
rust: 1.85.0 # MSRV
35+
runner: macos-latest
36+
- target: aarch64-apple-darwin
37+
rust: stable
38+
runner: macos-latest
39+
40+
# `x86` Linux (32-bit)
2541
- target: i686-unknown-linux-gnu
26-
platform: ubuntu-latest
42+
runner: ubuntu-latest
2743
rust: 1.85.0 # MSRV
2844
deps: sudo apt update && sudo apt install gcc-multilib
2945

30-
# 64-bit Linux
46+
# `x86_64` Linux
3147
- target: x86_64-unknown-linux-gnu
32-
platform: ubuntu-latest
48+
runner: ubuntu-latest
3349
rust: 1.85.0 # MSRV
3450

35-
# 64-bit Windows
51+
# `x86_64` Windows
3652
- target: x86_64-pc-windows-msvc
37-
platform: windows-latest
53+
runner: windows-latest
3854
rust: 1.85.0 # MSRV
39-
40-
# 64-bit macOS
41-
- target: x86_64-apple-darwin
42-
platform: macos-latest
43-
rust: 1.85.0 # MSRV
44-
runs-on: ${{ matrix.platform }}
55+
runs-on: ${{ matrix.runner != '' && matrix.runner || 'ubuntu-latest' }}
4556
steps:
4657
- uses: actions/checkout@v6
4758
- uses: RustCrypto/actions/cargo-cache@master
@@ -87,3 +98,16 @@ jobs:
8798
toolchain: ${{ matrix.rust }}
8899
targets: wasm32-wasip1
89100
- run: cargo test --target wasm32-wasip1
101+
102+
# Test `cpubits="32"` on a 64-bit target
103+
test-override-32-on-64:
104+
env:
105+
RUSTFLAGS: '-Dwarnings --cfg cpubits="32"'
106+
runs-on: ubuntu-latest
107+
steps:
108+
- uses: actions/checkout@v6
109+
- uses: RustCrypto/actions/cargo-cache@master
110+
- uses: dtolnay/rust-toolchain@master
111+
with:
112+
toolchain: stable
113+
- run: cargo test

cpubits/Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,6 @@ target CPU, which in some cases may differ from its address size a.k.a.
1515
`target_pointer_width`. Implemented as `macro_rules!`
1616
"""
1717

18-
[lints]
19-
workspace = true
18+
[lints.rust.unexpected_cfgs]
19+
level = "warn"
20+
check-cfg = ['cfg(cpubits, values("16", "32", "64"))']

cpubits/src/lib.rs

Lines changed: 80 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg",
55
html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg"
66
)]
7-
#![allow(clippy::doc_markdown)]
7+
#![warn(clippy::pedantic)]
88

99
//! # Supported bit sizes
1010
//!
@@ -18,6 +18,48 @@
1818
//! ```text
1919
//! expected values for `target_pointer_width` are: `16`, `32`, and `64`
2020
//! ```
21+
//!
22+
//! # Overriding the selection result via `cfg`
23+
//!
24+
//! This crate supports overriding its detection heuristics via an explicit `cfg` setting:
25+
//!
26+
//! - `cpubits = "16"`: force 16-bit
27+
//! - `cpubits = "32"`: force 32-bit
28+
//! - `cpubits = "64"`: force 64-bit
29+
//!
30+
//! This can be useful for testing different backends, and also in the event you would like to
31+
//! override the default detection result (in which case we would appreciate it if you opened an
32+
//! issue and let us know why).
33+
//!
34+
//! You can set `cfg` via the `RUSTFLAGS` environment variable:
35+
//!
36+
//! ```console
37+
//! $ RUSTFLAGS='--cfg cpubits="64"' cargo build --release
38+
//! ```
39+
//!
40+
//! Or you can persistently configure it for your project in `.cargo/config.toml`:
41+
//!
42+
//! ```toml
43+
//! # In .cargo/config.toml
44+
//! [build]
45+
//! rustflags = ['--cfg', 'cpubits="64"']
46+
//! ```
47+
//!
48+
//! ## Lint configuration for `cfg(cpubits)`
49+
//!
50+
//! If you are using the `cpubits!` macro you will notice the following warning being emitted:
51+
//!
52+
//! ```text
53+
//! warning: unexpected `cfg` condition name: `cpubits`
54+
//! ```
55+
//!
56+
//! You will need to add the following configuration to your `Cargo.toml` to silence the warning:
57+
//!
58+
//! ```toml
59+
//! [lints.rust.unexpected_cfgs]
60+
//! level = "warn"
61+
//! check-cfg = ['cfg(cpubits, values("16", "32", "64"))']
62+
//! ```
2163
2264
// End of toplevel rustdoc, beginning of macro documentation. We put the detailed docs on the macro
2365
// itself so we can re-export it, and people can easily get to these docs from the re-exported
@@ -47,6 +89,11 @@
4789
/// }
4890
/// ```
4991
///
92+
/// NOTE: rustc will complain: "warning: unexpected `cfg` condition name: `cpubits`"
93+
///
94+
/// See the [lint configuration for `cfg(cpubits)`](./index.html#lint-configuration-for-cfgcpubits)
95+
/// documentation for how to silence the warning.
96+
///
5097
/// ## Grouping multiple bit sizes
5198
///
5299
/// If you would like to group together 16-bit and 32-bit platforms, you can do so as follows:
@@ -100,8 +147,8 @@
100147
/// certain targets from 32-bit to 64-bit ones.
101148
///
102149
/// This 64-bit promotion occurs if `any` of the following `cfg`s are true:
103-
/// - ARMv7: `all(target_arch = "arm", target_feature = "v7")`
104-
/// - WASM: `target_arch = "wasm32"`
150+
/// - `armv7`: `all(target_arch = "arm", target_feature = "v7")`
151+
/// - `wasm32`: `target_arch = "wasm32"`
105152
#[macro_export]
106153
macro_rules! cpubits {
107154
// Only run the given block if we have selected a 16-bit word size, i.e. the code will be
@@ -204,22 +251,35 @@ macro_rules! cpubits {
204251
) => {
205252
$crate::cfg_if! {
206253
@__items () ;
254+
// The following are effectively `if`/`else` clauses in a Lispy syntax, where each
255+
// 2-tuple is `( ( predicate ) ( body ) )`. The first clause with a matching predicate
256+
// is taken and the rest are ignored just like `if`/`else`.
257+
//
258+
// We first match on each of the explicit overrides, and if none of them are configured
259+
// apply our heuristic logic which allows certain targets to be overridden to use
260+
// 64-bit backends, as configured in the `enable_64_bit` predicate above.
261+
(
262+
( cpubits = "16" )
263+
( $( $tokens16 )* )
264+
),
265+
(
266+
( cpubits = "32" )
267+
( $( $tokens32 )* )
268+
),
269+
(
270+
( cpubits = "64" )
271+
( $( $tokens64 )* )
272+
),
207273
(
208274
( target_pointer_width = "16" )
209275
( $( $tokens16 )* )
210276
),
211277
(
212-
(all(
213-
target_pointer_width = "32",
214-
not($( $enable_64_bit )+)
215-
))
278+
( all(target_pointer_width = "32", not($( $enable_64_bit )+)) )
216279
( $( $tokens32 )* )
217280
),
218281
(
219-
(any(
220-
target_pointer_width = "64",
221-
$( $enable_64_bit )+
222-
))
282+
( any(target_pointer_width = "64", $( $enable_64_bit )+) )
223283
( $( $tokens64 )* )
224284
),
225285
(
@@ -317,6 +377,7 @@ mod tests {
317377
use super::CPUBITS;
318378

319379
/// Return the expected number of bits for the target.
380+
#[cfg(not(any(cpubits = "16", cpubits = "32", cpubits = "64")))]
320381
fn expected_bits() -> u32 {
321382
// Duplicated 64-bit override predicates need to go here
322383
if cfg!(any(
@@ -331,6 +392,7 @@ mod tests {
331392
}
332393
}
333394

395+
#[cfg(not(any(cpubits = "16", cpubits = "32", cpubits = "64")))]
334396
#[test]
335397
fn cpubits_works() {
336398
assert_eq!(CPUBITS, expected_bits());
@@ -351,6 +413,7 @@ mod tests {
351413
}
352414

353415
/// Test for the `16 | 32` syntax.
416+
#[cfg(not(any(cpubits = "16", cpubits = "32", cpubits = "64")))]
354417
#[test]
355418
fn cpubits_16_or_32_vs_64() {
356419
const BITS: u32 = {
@@ -366,4 +429,10 @@ mod tests {
366429
bits => unreachable!("#{bits}-bits should be one of: 16, 32, 64"),
367430
}
368431
}
432+
433+
#[cfg(cpubits = "32")]
434+
#[test]
435+
fn cpubits_32_bit_override() {
436+
assert_eq!(CPUBITS, 32);
437+
}
369438
}

0 commit comments

Comments
 (0)