Skip to content

Commit 2b2c5f8

Browse files
authored
Move all rustc arguments to kani-driver (#2174)
Move all rustc arguments to kani-driver 1. It's good to have one source of truth. 2. This is needed for us to properly support caching compiler artifacts
1 parent ce5c061 commit 2b2c5f8

File tree

9 files changed

+85
-209
lines changed

9 files changed

+85
-209
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,8 @@ dependencies = [
523523
"rustc-demangle",
524524
"serde",
525525
"serde_json",
526+
"strum",
527+
"strum_macros",
526528
"toml",
527529
"tracing",
528530
"tracing-subscriber",

kani-compiler/src/main.rs

Lines changed: 1 addition & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -47,48 +47,9 @@ use rustc_hir::definitions::DefPathHash;
4747
use rustc_interface::Config;
4848
use rustc_session::config::ErrorOutputType;
4949
use session::json_panic_hook;
50+
use std::env;
5051
use std::ffi::OsStr;
51-
use std::path::PathBuf;
5252
use std::rc::Rc;
53-
use std::{env, fs};
54-
55-
/// This function generates all rustc configurations required by our goto-c codegen.
56-
fn rustc_gotoc_flags(lib_path: &str) -> Vec<String> {
57-
// The option below provides a mechanism by which definitions in the
58-
// standard library can be overriden. See
59-
// https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/.E2.9C.94.20Globally.20override.20an.20std.20macro/near/268873354
60-
// for more details.
61-
let kani_std_rlib = PathBuf::from(lib_path).join("libstd.rlib");
62-
let kani_std_wrapper = format!("noprelude:std={}", kani_std_rlib.to_str().unwrap());
63-
let args = vec![
64-
"-C",
65-
"overflow-checks=on",
66-
"-C",
67-
"panic=abort",
68-
"-Z",
69-
"unstable-options",
70-
"-Z",
71-
"panic_abort_tests=yes",
72-
"-Z",
73-
"trim-diagnostic-paths=no",
74-
"-Z",
75-
"human_readable_cgu_names",
76-
"-Z",
77-
"always-encode-mir",
78-
"--cfg=kani",
79-
"-Z",
80-
"crate-attr=feature(register_tool)",
81-
"-Z",
82-
"crate-attr=register_tool(kanitool)",
83-
"-L",
84-
lib_path,
85-
"--extern",
86-
"kani",
87-
"--extern",
88-
kani_std_wrapper.as_str(),
89-
];
90-
args.iter().map(|s| s.to_string()).collect()
91-
}
9253

9354
/// Main function. Configure arguments and run the compiler.
9455
fn main() -> Result<(), &'static str> {
@@ -152,35 +113,9 @@ impl Callbacks for KaniCallbacks {
152113
}
153114
}
154115

155-
/// The Kani root folder has all binaries inside bin/ and libraries inside lib/.
156-
/// This folder can also be used as a rustc sysroot.
157-
fn kani_root() -> PathBuf {
158-
match env::current_exe() {
159-
Ok(exe_path) => {
160-
let mut path = fs::canonicalize(&exe_path).unwrap_or(exe_path);
161-
// Current folder (bin/)
162-
path.pop();
163-
// Top folder
164-
path.pop();
165-
path
166-
}
167-
Err(e) => panic!("Failed to get current exe path: {e}"),
168-
}
169-
}
170-
171116
/// Generate the arguments to pass to rustc_driver.
172117
fn generate_rustc_args(args: &ArgMatches) -> Vec<String> {
173118
let mut rustc_args = vec![String::from("rustc")];
174-
if args.get_flag(parser::GOTO_C) {
175-
let mut default_path = kani_root();
176-
default_path.push("lib");
177-
let gotoc_args = rustc_gotoc_flags(
178-
args.get_one::<String>(parser::KANI_LIB)
179-
.unwrap_or(&default_path.to_str().unwrap().to_string()),
180-
);
181-
rustc_args.extend_from_slice(&gotoc_args);
182-
}
183-
184119
if args.get_flag(parser::RUSTC_VERSION) {
185120
rustc_args.push(String::from("--version"))
186121
}
@@ -192,9 +127,6 @@ fn generate_rustc_args(args: &ArgMatches) -> Vec<String> {
192127
if let Some(extra_flags) = args.get_raw(parser::RUSTC_OPTIONS) {
193128
extra_flags.for_each(|arg| rustc_args.push(convert_arg(arg)));
194129
}
195-
let sysroot = sysroot_path(args);
196-
rustc_args.push(String::from("--sysroot"));
197-
rustc_args.push(convert_arg(sysroot.as_os_str()));
198130
tracing::debug!(?rustc_args, "Compile");
199131
rustc_args
200132
}
@@ -205,72 +137,6 @@ fn convert_arg(arg: &OsStr) -> String {
205137
arg.to_str().expect(format!("[Error] Cannot parse argument \"{arg:?}\".").as_str()).to_string()
206138
}
207139

208-
/// Get the sysroot, for our specific version of Rust nightly.
209-
///
210-
/// Rust normally finds its sysroot by looking at where itself (the `rustc`
211-
/// executable) is located. This will fail for us because we're `kani-compiler`
212-
/// and not located under the rust sysroot.
213-
///
214-
/// We do know the actual name of the toolchain we need, however.
215-
/// We look for our toolchain in the usual place for rustup.
216-
///
217-
/// We previously used to pass `--sysroot` in `KANIFLAGS` from `kani-driver`,
218-
/// but this failed to have effect when building a `build.rs` file.
219-
/// This wasn't used anywhere but passing down here, so we've just migrated
220-
/// the code to find the sysroot path directly into this function.
221-
///
222-
/// This function will soon be removed.
223-
#[deprecated]
224-
fn toolchain_sysroot_path() -> PathBuf {
225-
// If we're installed normally, we'll find `$KANI/toolchain` as a symlink to our desired toolchain
226-
{
227-
let kani_root = kani_root();
228-
let toolchain_path = kani_root.join("toolchain");
229-
if toolchain_path.exists() {
230-
return toolchain_path;
231-
}
232-
}
233-
234-
// rustup sets some environment variables during build, but this is not clearly documented.
235-
// https://github.com/rust-lang/rustup/blob/master/src/toolchain.rs (search for RUSTUP_HOME)
236-
// We're using RUSTUP_TOOLCHAIN here, which is going to be set by our `rust-toolchain.toml` file.
237-
// This is a *compile-time* constant, not a dynamic lookup at runtime, so this is reliable.
238-
let toolchain = env!("RUSTUP_TOOLCHAIN");
239-
240-
// We use the home crate to do a *runtime* determination of where rustup toolchains live
241-
let rustup = home::rustup_home().expect("Couldn't find RUSTUP_HOME");
242-
let path = rustup.join("toolchains").join(toolchain);
243-
244-
if !path.exists() {
245-
panic!("Couldn't find Kani Rust toolchain {toolchain}. Tried: {}", path.display());
246-
}
247-
path
248-
}
249-
250-
/// Get the sysroot relative to the binary location.
251-
///
252-
/// Kani uses a custom sysroot. The `std` library and dependencies are compiled in debug mode and
253-
/// include the entire MIR definitions needed by Kani.
254-
///
255-
/// We do provide a `--sysroot` option that users may want to use instead.
256-
#[allow(deprecated)]
257-
fn sysroot_path(args: &ArgMatches) -> PathBuf {
258-
let sysroot_arg = args.get_one::<String>(parser::SYSROOT);
259-
let path = if let Some(s) = sysroot_arg {
260-
PathBuf::from(s)
261-
} else if !args.get_flag(parser::GOTO_C) {
262-
toolchain_sysroot_path()
263-
} else {
264-
kani_root()
265-
};
266-
267-
if !path.exists() {
268-
panic!("Couldn't find Kani Rust toolchain {:?}.", path.display());
269-
}
270-
tracing::debug!(?path, ?sysroot_arg, "Sysroot path.");
271-
path
272-
}
273-
274140
/// Find the stub mapping for the given harness.
275141
///
276142
/// This function is necessary because Kani currently allows a harness to be

kani-driver/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ rustc-demangle = "0.1.21"
3232
pathdiff = "0.2.1"
3333
rayon = "1.5.3"
3434
comfy-table = "6.0.0"
35+
strum = {version = "0.24.0"}
36+
strum_macros = {version = "0.24.0"}
3537
tracing = {version = "0.1", features = ["max_level_trace", "release_max_level_debug"]}
3638
tracing-subscriber = {version = "0.3.8", features = ["env-filter", "json", "fmt"]}
3739
tracing-tree = "0.2.2"

kani-driver/src/call_cargo.rs

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
// SPDX-License-Identifier: Apache-2.0 OR MIT
33

44
use crate::args::KaniArgs;
5-
use crate::session::{KaniSession, ReachabilityMode};
5+
use crate::session::KaniSession;
66
use anyhow::{bail, Context, Result};
77
use cargo_metadata::diagnostic::{Diagnostic, DiagnosticLevel};
88
use cargo_metadata::{Message, Metadata, MetadataCommand, Package};
9-
use std::ffi::OsString;
9+
use std::ffi::{OsStr, OsString};
1010
use std::fs;
1111
use std::io::BufReader;
1212
use std::path::{Path, PathBuf};
@@ -58,8 +58,9 @@ impl KaniSession {
5858
fs::remove_dir_all(&target_dir)?;
5959
}
6060

61-
let mut kani_args = self.kani_specific_flags();
62-
let rustc_args = self.kani_rustc_flags();
61+
let kani_args = self.kani_compiler_flags();
62+
let mut rustc_args = self.kani_rustc_flags();
63+
rustc_args.push("--kani-flags".into());
6364

6465
let mut cargo_args: Vec<OsString> = vec!["rustc".into()];
6566
if let Some(path) = &self.args.cargo.manifest_path {
@@ -99,21 +100,8 @@ impl KaniSession {
99100
}
100101

101102
// Arguments that will only be passed to the target package.
102-
let mut pkg_args: Vec<OsString> = vec![];
103-
match self.reachability_mode() {
104-
ReachabilityMode::ProofHarnesses => {
105-
pkg_args.extend(["--".into(), "--reachability=harnesses".into()]);
106-
}
107-
ReachabilityMode::AllPubFns => {
108-
pkg_args.extend(["--".into(), "--reachability=pub_fns".into()]);
109-
}
110-
ReachabilityMode::Tests => {
111-
pkg_args.extend(["--".into(), "--reachability=tests".into()]);
112-
}
113-
}
114-
115-
// Only joing them at the end. All kani flags must come first.
116-
kani_args.extend_from_slice(&rustc_args);
103+
let mut pkg_args: Vec<String> = vec![];
104+
pkg_args.extend(["--".to_string(), format!("--reachability={}", self.reachability_mode())]);
117105

118106
let mut found_target = false;
119107
let packages = packages_to_verify(&self.args, &metadata);
@@ -125,8 +113,10 @@ impl KaniSession {
125113
.args(&target.to_args())
126114
.args(&pkg_args)
127115
.env("RUSTC", &self.kani_compiler)
128-
.env("RUSTFLAGS", "--kani-flags")
129-
.env("KANIFLAGS", &crate::util::join_osstring(&kani_args, " "))
116+
.env("KANIFLAGS", kani_args.join(" "))
117+
// Use CARGO_ENCODED_RUSTFLAGS instead of RUSTFLAGS is preferred. See
118+
// https://doc.rust-lang.org/cargo/reference/environment-variables.html
119+
.env("CARGO_ENCODED_RUSTFLAGS", rustc_args.join(OsStr::new("\x1f")))
130120
.env("CARGO_TERM_PROGRESS_WHEN", "never");
131121

132122
self.run_cargo(cmd)?;

kani-driver/src/call_single_file.rs

Lines changed: 48 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::ffi::OsString;
66
use std::path::Path;
77
use std::process::Command;
88

9-
use crate::session::{KaniSession, ReachabilityMode};
9+
use crate::session::{base_folder, lib_folder, KaniSession};
1010

1111
impl KaniSession {
1212
/// Used by `kani` and not `cargo-kani` to process a single Rust file into a `.symtab.json`
@@ -17,15 +17,8 @@ impl KaniSession {
1717
crate_name: &String,
1818
outdir: &Path,
1919
) -> Result<()> {
20-
let mut kani_args = self.kani_specific_flags();
21-
kani_args.push(
22-
match self.reachability_mode() {
23-
ReachabilityMode::ProofHarnesses => "--reachability=harnesses",
24-
ReachabilityMode::AllPubFns => "--reachability=pub_fns",
25-
ReachabilityMode::Tests => "--reachability=tests",
26-
}
27-
.into(),
28-
);
20+
let mut kani_args = self.kani_compiler_flags();
21+
kani_args.push(format!("--reachability={}", self.reachability_mode()));
2922

3023
let mut rustc_args = self.kani_rustc_flags();
3124
rustc_args.push(file.into());
@@ -65,10 +58,9 @@ impl KaniSession {
6558
Ok(())
6659
}
6760

68-
/// These arguments are arguments passed to kani-compiler that are `kani` specific.
69-
/// These are also used by call_cargo to pass as the env var KANIFLAGS.
70-
pub fn kani_specific_flags(&self) -> Vec<OsString> {
71-
let mut flags = vec![OsString::from("--goto-c")];
61+
/// These arguments are arguments passed to kani-compiler that are `kani` compiler specific.
62+
pub fn kani_compiler_flags(&self) -> Vec<String> {
63+
let mut flags = vec![];
7264

7365
if self.args.debug {
7466
flags.push("--log-level=debug".into());
@@ -93,19 +85,57 @@ impl KaniSession {
9385
flags.push("--enable-stubbing".into());
9486
}
9587
if let Some(harness) = &self.args.harness {
96-
flags.push(format!("--harness={harness}").into());
88+
flags.push(format!("--harness={harness}"));
9789
}
9890

91+
// This argument will select the Kani flavour of the compiler. It will be removed before
92+
// rustc driver is invoked.
93+
flags.push("--goto-c".into());
94+
9995
#[cfg(feature = "unsound_experiments")]
10096
flags.extend(self.args.unsound_experiments.process_args());
10197

10298
flags
10399
}
104100

105-
/// These arguments are arguments passed to kani-compiler that are `rustc` specific.
106-
/// These are also used by call_cargo to pass as the env var KANIFLAGS.
101+
/// This function generates all rustc configurations required by our goto-c codegen.
107102
pub fn kani_rustc_flags(&self) -> Vec<OsString> {
108-
let mut flags = Vec::<OsString>::new();
103+
let lib_path = lib_folder().unwrap();
104+
let kani_std_rlib = lib_path.join("libstd.rlib");
105+
let kani_std_wrapper = format!("noprelude:std={}", kani_std_rlib.to_str().unwrap());
106+
let sysroot = base_folder().unwrap();
107+
let args = vec![
108+
"-C",
109+
"overflow-checks=on",
110+
"-C",
111+
"panic=abort",
112+
"-C",
113+
"symbol-mangling-version=v0",
114+
"-Z",
115+
"unstable-options",
116+
"-Z",
117+
"panic_abort_tests=yes",
118+
"-Z",
119+
"trim-diagnostic-paths=no",
120+
"-Z",
121+
"human_readable_cgu_names",
122+
"-Z",
123+
"always-encode-mir",
124+
"--cfg=kani",
125+
"-Z",
126+
"crate-attr=feature(register_tool)",
127+
"-Z",
128+
"crate-attr=register_tool(kanitool)",
129+
"--sysroot",
130+
sysroot.to_str().unwrap(),
131+
"-L",
132+
lib_path.to_str().unwrap(),
133+
"--extern",
134+
"kani",
135+
"--extern",
136+
kani_std_wrapper.as_str(),
137+
];
138+
let mut flags: Vec<_> = args.iter().map(OsString::from).collect();
109139
if self.args.use_abs {
110140
flags.push("-Z".into());
111141
flags.push("force-unstable-if-unmarked=yes".into()); // ??
@@ -124,9 +154,6 @@ impl KaniSession {
124154
}
125155
}
126156

127-
flags.push("-C".into());
128-
flags.push("symbol-mangling-version=v0".into());
129-
130157
// e.g. compiletest will set 'compile-flags' here and we should pass those down to rustc
131158
// and we fail in `tests/kani/Match/match_bool.rs`
132159
if let Ok(str) = std::env::var("RUSTFLAGS") {

0 commit comments

Comments
 (0)