Skip to content

Commit 042a303

Browse files
celinvalkarkhaz
andauthored
Add "kani" configuration key to enable conditional compilation in build scripts (rust-lang#2297)
We now pass `--cfg=kani` to build scripts, which allow users to use constructs such as `if cfg!(kani)` to conditionally compile their build scripts. The build script may have logic that is not redundant to Kani, or even unsupported. Users can now change how their build works based on conditional compilation. Co-authored-by: Kareem Khazem <[email protected]>
1 parent eefd724 commit 042a303

File tree

10 files changed

+119
-8
lines changed

10 files changed

+119
-8
lines changed

kani-driver/src/call_cargo.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::args::VerificationArgs;
55
use crate::call_single_file::to_rustc_arg;
66
use crate::project::Artifact;
77
use crate::session::KaniSession;
8-
use crate::util;
8+
use crate::{session, util};
99
use anyhow::{bail, Context, Result};
1010
use cargo_metadata::diagnostic::{Diagnostic, DiagnosticLevel};
1111
use cargo_metadata::{Message, Metadata, MetadataCommand, Package, Target};
@@ -79,8 +79,7 @@ impl KaniSession {
7979
cargo_args.push(format!("--features={}", features.join(",")).into());
8080
}
8181

82-
cargo_args.push("--target".into());
83-
cargo_args.push(build_target.into());
82+
cargo_args.append(&mut cargo_config_args());
8483

8584
cargo_args.push("--target-dir".into());
8685
cargo_args.push(target_dir.into());
@@ -111,7 +110,8 @@ impl KaniSession {
111110
for package in packages {
112111
for verification_target in package_targets(&self.args, package) {
113112
let mut cmd = Command::new("cargo");
114-
cmd.args(&cargo_args)
113+
cmd.arg(session::toolchain_shorthand())
114+
.args(&cargo_args)
115115
.args(vec!["-p", &package.name])
116116
.args(&verification_target.to_args())
117117
.args(&pkg_args)
@@ -252,6 +252,19 @@ impl KaniSession {
252252
}
253253
}
254254

255+
pub fn cargo_config_args() -> Vec<OsString> {
256+
[
257+
"--target",
258+
env!("TARGET"),
259+
// Propagate `--cfg=kani` to build scripts.
260+
"-Zhost-config",
261+
"-Ztarget-applies-to-host",
262+
"--config=host.rustflags=[\"--cfg=kani\"]",
263+
]
264+
.map(OsString::from)
265+
.to_vec()
266+
}
267+
255268
/// Print the compiler message following the coloring schema.
256269
fn print_msg(diagnostic: &Diagnostic, use_rendered: bool) -> Result<()> {
257270
if use_rendered {

kani-driver/src/concrete_playback/playback.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
66
use crate::args::common::Verbosity;
77
use crate::args::playback_args::{CargoPlaybackArgs, KaniPlaybackArgs, MessageFormat};
8+
use crate::call_cargo::cargo_config_args;
89
use crate::call_single_file::base_rustc_flags;
910
use crate::session::{lib_playback_folder, InstallType};
1011
use crate::{session, util};
@@ -113,8 +114,7 @@ fn cargo_test(install: &InstallType, args: CargoPlaybackArgs) -> Result<()> {
113114
}
114115

115116
cargo_args.append(&mut args.cargo.to_cargo_args());
116-
cargo_args.push("--target".into());
117-
cargo_args.push(env!("TARGET").into());
117+
cargo_args.append(&mut cargo_config_args());
118118

119119
// These have to be the last arguments to cargo test.
120120
if !args.playback.test_args.is_empty() {
@@ -124,7 +124,8 @@ fn cargo_test(install: &InstallType, args: CargoPlaybackArgs) -> Result<()> {
124124

125125
// Arguments that will only be passed to the target package.
126126
let mut cmd = Command::new("cargo");
127-
cmd.args(&cargo_args)
127+
cmd.arg(session::toolchain_shorthand())
128+
.args(&cargo_args)
128129
.env("RUSTC", &install.kani_compiler()?)
129130
// Use CARGO_ENCODED_RUSTFLAGS instead of RUSTFLAGS is preferred. See
130131
// https://doc.rust-lang.org/cargo/reference/environment-variables.html

kani-driver/src/session.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,14 @@ pub fn base_folder() -> Result<PathBuf> {
291291
.to_path_buf())
292292
}
293293

294+
/// Return the shorthand for the toolchain used by this Kani version.
295+
///
296+
/// This shorthand can be used to select the exact toolchain version that matches the one used to
297+
/// build the current Kani version.
298+
pub fn toolchain_shorthand() -> String {
299+
format!("+{}", env!("RUSTUP_TOOLCHAIN"))
300+
}
301+
294302
impl InstallType {
295303
pub fn new() -> Result<Self> {
296304
// Case 1: We've checked out the development repo and we're built under `target/kani`

tests/cargo-ui/verbose-cmds/expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
CARGO_ENCODED_RUSTFLAGS=
2-
cargo rustc
2+
cargo +nightly
33
Running: `goto-cc
44
Running: `goto-instrument
55
Checking harness dummy_harness...
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Copyright Kani Contributors
2+
# SPDX-License-Identifier: Apache-2.0 OR MIT
3+
[package]
4+
name = "build-rs-conditional"
5+
version = "0.1.0"
6+
edition = "2021"
7+
8+
[dependencies]
9+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
//! Verify that build scripts can check if they are running under `kani`.
4+
5+
fn main() {
6+
if cfg!(kani) {
7+
println!("cargo:rustc-env=RUNNING_KANI=Yes");
8+
} else {
9+
println!("cargo:rustc-env=RUNNING_KANI=No");
10+
}
11+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/usr/bin/env bash
2+
# Copyright Kani Contributors
3+
# SPDX-License-Identifier: Apache-2.0 OR MIT
4+
5+
set +e
6+
7+
TMP_DIR="/tmp/build-rs"
8+
9+
rm -rf ${TMP_DIR}
10+
cp -r . ${TMP_DIR}
11+
pushd ${TMP_DIR} > /dev/null
12+
13+
14+
echo "[TEST] Run verification..."
15+
cargo kani --concrete-playback=inplace -Z concrete-playback
16+
17+
echo "[TEST] Run playback..."
18+
cargo kani playback -Z concrete-playback --lib -- check_kani
19+
20+
echo "[TEST] Run test..."
21+
cargo test --lib
22+
23+
# Cleanup
24+
popd > /dev/null
25+
rm -r ${TMP_DIR}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Copyright Kani Contributors
2+
# SPDX-License-Identifier: Apache-2.0 OR MIT
3+
script: build_rs.sh
4+
expected: expected
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[TEST] Run verification...
2+
Checking harness verify::check_kani...
3+
Complete - 1 successfully verified harnesses, 0 failures, 1 total
4+
5+
[TEST] Run playback...
6+
running 1 test\
7+
test verify::kani_concrete_playback_check_kani_\
8+
\
9+
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out
10+
11+
[TEST] Run test...
12+
running 1 test\
13+
test test::check_not_kani ... ok\
14+
\
15+
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
16+
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
//! This tests ensures that build scripts are able to conditionally check if they are running under
4+
//! Kani (in both verification and playback mode).
5+
6+
#[cfg(kani)]
7+
mod verify {
8+
/// Running `cargo kani` should verify that "RUNNING_KANI" is equals to "Yes"
9+
#[kani::proof]
10+
fn check_kani() {
11+
assert_eq!(env!("RUNNING_KANI"), "Yes");
12+
// Add a dummy cover so playback generates a test that should succeed.
13+
kani::cover!(kani::any());
14+
}
15+
}
16+
17+
#[cfg(test)]
18+
mod test {
19+
/// Running `cargo test` should check that "RUNNING_KANI" is "No".
20+
#[test]
21+
fn check_not_kani() {
22+
assert_eq!(env!("RUNNING_KANI"), "No");
23+
}
24+
}

0 commit comments

Comments
 (0)