Repository navigation
Conversation
tautschnig
left a comment
There was a problem hiding this comment.
Thank you for your contribution! A couple of comments inline.
Kani's cargo target, sysroot, target allowlist and machine model were all keyed to the host triple, so code that only compiles for another target could not be verified. CBMC's machine model is data in the goto program, so no such host is needed. - kani-compiler: riscv64 (LP64D) machine model, riscv64gc target features, riscv64-unknown-linux-gnu in check_target. - kani-driver: --target <TRIPLE>, gated on -Z unstable-options; rejected with non-host concrete playback and with verify-std. - build-kani: `cargo build-dev --lib-target <TRIPLE>` builds that target's verification libraries into targets/<TRIPLE>/lib, a sysroot of its own; the host's lib/ is unchanged. - tests/script-based-pre/target_riscv64, run by kani-regression.sh. Towards model-checking#2402. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The script test now exercises the --concrete-playback and verify-std rejections alongside the -Z gate, so every new argument conflict has coverage. The missing-library bail has no transcript-stable test: every target check_target accepts is a host triple on some CI runner, so its libraries exist somewhere in the matrix. The docs page's Limitations now carries the __CPROVER_architecture_* overwrite the README discloses.
A PATH wrapper pointing at this machine's build directory, created to run the committed test against the dev-built driver; it never belonged in the branch and the copyright check said so.
check_target matched on the LLVM target alone. riscv64a23-unknown-linux-gnu and riscv64-wrs-vxworks share riscv64gc's LLVM target, but target_config reports riscv64gc's features for all of them, so a23 was accepted and verified with the wrong cfg(target_feature) set. The Apple prefix checks also let iOS, tvOS, visionOS and watchOS through now that --target makes them reachable. Match the OS for both, and the feature string for riscv64. The error now names the target triple as well as its LLVM target, since the LLVM target alone made a rejected a23 read like riscv64gc. Also rewrap an over-long comment in new_machine_model. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The overwrite does not come from linking. When goto-cc links goto binaries the first input's __CPROVER_architecture_* symbols win, and kani_lib.c reaches the link as C source, which goto-cc compiles with the host's configuration. Say so, and say what would keep the model Kani wrote. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- build-dev: --lib-target conflicts with --skip-libs instead of being ignored. - target_riscv64: drop the usize-width assertion, which holds on every host Kani runs on and so does not show the target changed. - docs: name long double as a C width that differs (64-bit on macOS arm64, 128-bit on riscv64), and say where the overwritten model matters. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
I've pushed a small follow-up (450cbc2): --lib-target now conflicts with --skip-libs, the test drops an assertion that held on every host, and the docs name long double as a C width that differs between macOS arm64 and riscv64. The description's test results are refreshed. Could a maintainer approve the workflow runs? They're waiting on first-time contributor approval, so target_riscv64 has only run locally so far. |
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Cross-target linking can retain host machine semantics, and exported metadata reports the wrong target.
Review effort: Balanced
Findings: 1
Open (3)
What changed in this PR
Adds experimental cross-target verification, initially supporting riscv64gc-unknown-linux-gnu.
Changes:
- Adds
--targethandling throughout compilation and coverage. - Builds target-specific verification sysroots and a RISC-V machine model.
- Adds documentation and cross-target regression coverage.
| File | Description |
|---|---|
tools/build-kani/src/sysroot.rs |
Builds target-specific sysroots. |
tools/build-kani/src/parser.rs |
Adds --lib-target. |
tools/build-kani/src/main.rs |
Builds requested target libraries. |
tests/script-based-pre/target_riscv64/target_riscv64.sh |
Exercises cross-target commands. |
tests/script-based-pre/target_riscv64/target_riscv64.expected |
Defines expected output. |
tests/script-based-pre/target_riscv64/sample_crate/src/lib.rs |
Adds RISC-V cargo test crate. |
tests/script-based-pre/target_riscv64/sample_crate/Cargo.toml |
Configures the test crate. |
tests/script-based-pre/target_riscv64/riscv64.rs |
Tests RISC-V target facts. |
tests/script-based-pre/target_riscv64/config.yml |
Configures the script test. |
scripts/kani-regression.sh |
Builds RISC-V libraries in CI. |
kani-driver/src/session.rs |
Resolves target-specific libraries. |
kani-driver/src/coverage/cov_session.rs |
Uses the verification target for coverage. |
kani-driver/src/concrete_playback/playback.rs |
Keeps playback host-targeted. |
kani-driver/src/call_single_file.rs |
Passes targets to single-file compilation. |
kani-driver/src/call_cargo.rs |
Passes targets through Cargo. |
kani-driver/src/args/std_args.rs |
Rejects targeted verify-std. |
kani-driver/src/args/mod.rs |
Defines and validates --target. |
kani-compiler/src/codegen_cprover_gotoc/compiler_interface.rs |
Adds RISC-V features and machine model. |
docs/src/SUMMARY.md |
Links the new documentation. |
docs/src/reference/experimental/target.md |
Documents cross-target verification. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
feliperodri
left a comment
There was a problem hiding this comment.
Thanks for this. Requesting changes for two small gaps; the rest is in good shape.
I built it with cargo build-dev --lib-target riscv64gc-unknown-linux-gnu on x86_64 Linux with CBMC 6.11.0. target_riscv64, fmt, clippy and the driver/build-kani unit tests pass. Beyond the PR's test I tried a crate with a build.rs and a proc-macro dependency (the build script sees riscv64, the proc macro runs on the host), alternating host and riscv64 runs in one target dir, --coverage, autoharness on a single file, and cross-verifying for aarch64-unknown-linux-gnu from x86_64. All of those behaved. I also checked the riscv64 MachineModel against rustc's target spec, CBMC's set_arch_spec_riscv64 and the psABI, and it matches on every field.
What blocks, both inline:
--c-libwith a non-host--targetcompiles the C with the host'scharsignedness, and I have a harness that verifies for riscv64 when it should fail. Rejecting the combination is enough for now.kani autoharness --stdignores--targetand builds for the host. It needs the same rejection asverify-std.
With those two rejections in place (and a line each in target_riscv64), I'd approve. The other inline comments are suggestions.
On the architecture symbols in the linked .out: for Rust-only harnesses I don't think the host values make results wrong for the targets check_target accepts. Rust types reach the goto program with explicit widths and signedness, and kani_lib.c only uses size_t, uint8_t and pointers, which have the same widths on all five targets. Where it matters is C that goto-cc compiles, which is the --c-lib case. So I'm fine with precompiling kani_lib.c as a follow-up, as you proposed. I did confirm Copilot's --export-json point: the metadata says x86_64-unknown-linux-gnu for a riscv64 run, and passing verification_target() through would fix it.
On CI cost: the riscv64 library build adds about 45 s to each regression job on ubuntu-22.04. I'm fine keeping it in kani-regression.sh.
I didn't run anything on a macOS host locally (CI covers target_riscv64 there), and I couldn't do a full autoharness --std run because the std checkout I had doesn't build with this toolchain; I only checked the cargo invocation.
| --output-format=old.", | ||
| )); | ||
| } | ||
| if self.concrete_playback.is_some() |
There was a problem hiding this comment.
Soundness: --c-lib needs the same treatment as --concrete-playback here. link_goto_binary hands the --c-lib files to goto-cc, which compiles them with the host's C configuration, so C code reached from a riscv64 harness gets x86_64's signed char. Moving kani_lib.c after the Rust inputs (the follow-up from the docs thread) fixes the architecture symbols but not this, because the C functions are already typed by the time they are linked.
Reproducer on x86_64 Linux:
// cchar.c
int is_negative(char c) { return c < 0; }// cchar.rs
use std::ffi::c_char;
extern "C" {
fn is_negative(c: c_char) -> i32;
}
#[kani::proof]
fn char_sign() {
let c = 200u8 as c_char;
let r = unsafe { is_negative(c) };
assert!(r == 1, "C saw 200 as a negative char");
}kani cchar.rs --target riscv64gc-unknown-linux-gnu -Z unstable-options -Z c-ffi --c-lib cchar.c reports VERIFICATION:- SUCCESSFUL. On riscv64 char is unsigned, so the assertion fails there. Compiling the C file with goto-cc -funsigned-char -c cchar.c -o cu.o and passing --c-lib cu.o gives the correct FAILED.
Both flags are unstable, so rejecting --c-lib with a non-host --target is enough for this PR. Configuring goto-cc for the target can come with the kani_lib.c follow-up.
There was a problem hiding this comment.
| )); | ||
| } | ||
|
|
||
| if self.verify_opts.target_triple.is_some() { |
There was a problem hiding this comment.
Bug: kani autoharness --std goes through the same cargo_build_std path, which now passes HOST_TARGET, but nothing rejects --target there. With kani autoharness --std <library> --target riscv64gc-unknown-linux-gnu -Z unstable-options -Z autoharness --verbose, the cargo command has --target x86_64-unknown-linux-gnu, so a successful run would be a result for the host's std while the user asked for riscv64. The same check in AutoharnessArgs::validate when self.std is set would cover it, plus a line in the test next to the verify-std one.
There was a problem hiding this comment.
Good catch, fixed in 7153afd. AutoharnessArgs::validate now refuses --target when --std is set, before the std path check, the same way verify-std does. There is a unit test covering both subcommands and a line in target_riscv64.
| /// Return the folder with the pre-compiled rust libraries for verifying `target`. | ||
| /// The host's are in `lib/`. Any other target's are in `targets/<target>/lib/`, which is a | ||
| /// sysroot of its own, built by `cargo build-dev --lib-target <target>`. | ||
| pub fn lib_folder_for(target: &str) -> Result<PathBuf> { |
There was a problem hiding this comment.
Suggestion: the driver accepts any string for --target and only checks whether the library folder exists, so thumbv7em-none-eabihf, x86_64-unknown-linux-musl and typos all get "build them with cargo build-dev --lib-target <triple>". For musl, following that advice fails the whole cargo build-dev with the compiler's Kani requires the target platform to be ... error, deep in the log. --target "" resolves to targets/lib. Checking the triple against the supported list here (and in build-kani for --lib-target) would give one clear error up front. A shared constant, for example in kani_metadata, would keep the driver, build-kani and check_target from drifting apart.
There was a problem hiding this comment.
Done in d67167f. SUPPORTED_TARGETS in kani_metadata is now the single list. The driver checks --target against it right after the unstable gate and lists the supported targets in the error, which covers musl, typos and --target "". build-kani checks --lib-target the same way before it builds anything. build-kani didn't depend on kani_metadata before, so that's a new path dependency for it. The compiler side is in my reply on check_target.
| let bin_folder = &build_bin(&build_parser.args)?; | ||
| if !build_parser.skip_libs { | ||
| build_lib(bin_folder)?; | ||
| for target in &build_parser.lib_targets { |
There was a problem hiding this comment.
Suggestion: a later cargo build-dev without --lib-target leaves targets/<triple>/lib from the previous build in place, and the driver uses it. To check, I added a pub fn to library/kani/src/lib.rs and ran plain cargo build-dev: a harness calling it verified for the host and failed with E0425: cannot find function for riscv64. That's the loud case. A behavior change in library/kani or Kani's std overrides would be verified against the old copy without any error. CI always passes --lib-target, so this only affects local builds, but those are the ones where people iterate on the library. Rebuilding every target already present under targets/, or removing the folder when it isn't requested, would avoid it.
There was a problem hiding this comment.
Nice find. Done in c8a5d29: a plain cargo build-dev now rebuilds every supported target that already has a folder under targets/, as well as any named with --lib-target, and prints a line for each one it picked up. I went with rebuilding over deleting so a riscv64 setup keeps working across plain builds. --skip-libs still skips all of them.
| // `riscv64gc-unknown-linux-gnu`, whose LLVM target drops the `gc`. | ||
| // `riscv64a23-unknown-linux-gnu` and `riscv64-wrs-vxworks` share that LLVM target, so also | ||
| // match the OS and the features that `target_config` hardcodes. | ||
| let is_riscv64_linux_target = session.target.llvm_target == "riscv64-unknown-linux-gnu" |
There was a problem hiding this comment.
Suggestion: now that the allowlist is meant to name exact rustc targets (the error message lists them that way), comparing session.opts.target_triple.tuple() against those five names would say so directly. The exact match on the features string is the part I'd worry about: if a toolchain bump respells it (reorders it, or lists an implied extension), riscv64 starts failing check_target. CI would catch that through the library build, so this isn't blocking.
There was a problem hiding this comment.
Done in 25e3570, using the same SUPPORTED_TARGETS list from kani_metadata. The features compare was there because riscv64gc-unknown-linux-gnu, riscv64a23-unknown-linux-gnu and riscv64-wrs-vxworks share the LLVM target riscv64-unknown-linux-gnu, and the features string was what told riscv64gc apart. The tuple does that by itself. The one thing a tuple match alone would let through is a target JSON named after a supported target, since rustc takes the tuple from the file stem, so JSON targets are refused outright.
| |--------|-------| | ||
| | `x86_64-unknown-linux-gnu` | | | ||
| | `aarch64-unknown-linux-gnu` | | | ||
| | `riscv64gc-unknown-linux-gnu` | LP64D data model | |
There was a problem hiding this comment.
Suggestion: kernels usually build for riscv64gc-unknown-none-elf, which check_target rejects. Verifying such a crate as riscv64gc-unknown-linux-gnu sets target_os = "linux" and makes std available, so code behind cfg(target_os = "none") is compiled out and the linux branch is verified in its place. A sentence here saying the bare-metal target isn't supported, and what changes when the Linux one stands in for it, would tell kernel users what they are and aren't verifying.
There was a problem hiding this comment.
Done in eb6c119. The page now says riscv64gc-unknown-none-elf isn't supported, and that verifying such a crate as riscv64gc-unknown-linux-gnu sets target_os = "linux" and makes std available, so cfg(target_os = "none") code is compiled out and the linux branch is what gets verified.
link_goto_binary passed kani_lib.c to goto-cc as C source. goto-cc compiles it with the host's C configuration, and that configuration replaced the __CPROVER_architecture_* symbols kani-compiler wrote, so a riscv64 run was checked with the host's char signedness and long double width (CBMC printed "Adding CPROVER library (arm64)" on a macOS host). When goto-cc links goto binaries the first input's symbols win. For a cross target, compile kani_lib.c to an object next to the link output and pass it after the Rust inputs. Host runs keep the old command line. --c-lib now conflicts with a cross --target: those sources would also be compiled for the host and replace the model. goto-cc does accept clang's --target=<triple>, but it only sets the architecture (not the OS), and needs a native compiler that understands the flag, which gcc does not. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The target_riscv64 assertions are rustc facts (c_char, cfg), which hold whatever machine model CBMC ends up using. Inspect the binary Kani links for a harness and check that __CPROVER_architecture_arch is riscv64 and char_is_unsigned is 1. Without the previous commit it reads "arm64" and 0 on a macOS arm64 host. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
create_metadata_json wrote env!("TARGET"), the triple Kani was built for,
so a riscv64 run exported metadata.target as the host's triple. Pass the
verification target in, and check the exported value in target_riscv64.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The linked program now keeps the target's __CPROVER_architecture_* symbols. List the --c-lib conflict instead, and say that the OS symbol is still the host's, since Kani's machine model does not record one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The AArch64 model set char_is_unsigned for every OS. That holds on Linux, but char is signed on Apple arm64 (Apple's "Writing ARM64 code for Apple platforms", core::ffi::c_char on aarch64-apple-darwin, and CBMC's own macOS arm64 configuration). Host runs on macOS hid this, because the host-compiled kani_lib.c replaced the symbol at link time. A run with --target aarch64-apple-darwin from another host would not. Make it depend on the OS, as wchar_t_is_unsigned already does, and split the table out of new_machine_model so a unit test can check it without a rustc session. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1eaa2d9 refuses --c-lib with a non-host --target and covers it with a unit test, but nothing checked the message a user actually sees. The C file is the reviewer's reproducer: char is unsigned on riscv64 and signed on x86_64, which is why compiling it for the host would be wrong. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
autoharness --std builds std through the same cargo_build_std path as verify-std, which passes the host triple to cargo because Kani's no_core library exists for the host only. verify-std rejects --target for that reason, but autoharness --std accepted it and quietly verified the host's std. Check it before the std path, so the error names the real problem. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Kernels usually build for riscv64gc-unknown-none-elf, and the obvious workaround of verifying as riscv64gc-unknown-linux-gnu changes what gets verified: target_os becomes "linux" and std is available, so cfg(target_os = "none") code drops out. A kernel user should know that before reading a SUCCESSFUL result. Also list autoharness --std beside verify-std, since it now refuses --target too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The driver accepted any string for --target and only looked for targets/<triple>/lib, so an unsupported triple or a typo got "build them with cargo build-dev --lib-target <triple>". For musl, following that advice failed the whole build with kani-compiler's target error deep in the log, and --target "" resolved to the targets/ folder itself. SUPPORTED_TARGETS in kani_metadata is now the one list. The driver checks --target against it after the unstable gate, and build-kani checks --lib-target before building anything. kani_metadata is the crate the driver and compiler already share; build-kani takes it as a new path dependency, since it had no Kani crate in common with them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
check_target recognised targets by LLVM target, and for riscv64 also compared the spec's features string exactly, because riscv64gc, riscv64a23 and riscv64-wrs-vxworks share an LLVM target. A toolchain bump that respelled that string would have rejected riscv64gc. Compare the session's tuple against SUPPORTED_TARGETS instead. The tuple names the built-in spec, so it separates those targets without the features string. A target JSON file is refused outright, because rustc names it after its file stem and a file called riscv64gc-unknown-linux-gnu.json would otherwise pass with any layout. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A cargo build-dev without --lib-target left targets/<triple>/lib from the last build in place, and the driver used it. A change to library/kani or Kani's std overrides was then verified against the old copy for that target with no error; only a removed or renamed function showed up, as a compile failure. build-dev now rebuilds each supported target that already has a folder, as well as the ones named on the command line. Rebuilding rather than deleting keeps a riscv64 setup working across plain builds, and keeps the driver's "build them with cargo build-dev --lib-target" advice true: naming a target once is enough. --skip-libs still skips all of them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks for the careful review. Both blockers are in, and I took the suggestions in this PR as well rather than leaving them for later:
On I also ran this branch against a real workload, the Kani suite of nife: 222 harnesses across 32 crates. On the host, every verdict and every CBMC formula size (program size, VCCs, properties) was identical to the PR's merge-base. With |
|
@feliperodri, both blockers from your review are fixed and I took the five suggestions as well; each thread has the commit that addresses it. Could you please take another look when you have a moment? CI hasn't run here yet: the workflows from the latest push are waiting on first-time contributor approval. Could a maintainer please approve them so One scope note: "Mark char as signed in the aarch64-apple-darwin machine model" changes an existing host model, not just the new target. If you'd rather review that on its own, I'm happy to split it into a separate PR. |
|
One more small thing: verify-std (ubuntu-22.04) in run 37961948162 timed out after 53 minutes, and the logs have since expired, so I can't tell why. Nothing in this PR touches the std verification path when --target isn't given, so I suspect it was a runner timeout. Could someone rerun that job, along with approving the pending workflows? Thanks. |
|
@feliperodri, a quick summary to make the re-review easy. Each of your threads has a reply naming its fix:
CI is green. I've left the threads open for you to resolve. Is there a release planned that this could make? We're carrying a patched 0.67.0 until it ships. Thanks! |
The merge of main brought the RFC 0015 --export-json shape (model-checking#4941), which reports `target` as the triple Kani was built for and gates the flag behind `-Z export-json`. With --target that triple is the wrong one, and the target_riscv64 script test, which checks that the export records the verification target, no longer ran. Take `target` from `verification_target()`, say so in the RFC's field table, and update the script test for the new key and the new gate. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Merged main, which had moved enough to conflict. One thing to flag: #4941’s new --export-json reports target as Kani’s build triple, which is wrong under --target, so c264c69 takes it from the verification target and updates RFC 0015’s field table to match. Runs without --target report the same value as before. CI is waiting on workflow approval for the fork. Could a maintainer approve the run when you get a chance? |
|
@feliperodri, this has been waiting on your re-review since the 5 October changes request. Both blockers and the five suggestions are in, each thread names its commit, and I merged main again on 26 October, so there are no conflicts. The workflows for the latest push still have not run: they need first-time contributor approval, so |
|
@calef thanks for your patience and for the contribution. Unfortunately, I have several PRs to review for this and other repositories so this one is not yet a priority. It needs a careful review. We are also discussing about the cadence for future releases, but no actual plan for a new release at the moment. |


This PR adds an unstable
--target <TRIPLE>option, so Kani can verify a crate for a target other than the host, and addsriscv64gc-unknown-linux-gnuas a target Kani has a machine model for.Towards #2402. It covers the part of that issue that needs no new machine-model work: 64-bit little-endian targets. The 16-bit and big-endian cases asked for there are left for later (see "Not in this PR").
Why
CBMC does not care which machine it runs on; the machine model is data Kani writes into the goto program. What stops Kani verifying for another target today is that four places are keyed to
env!("TARGET"): the target passed to cargo, the sysrootbuild-kanibuilds,check_target's allowlist, andnew_machine_model. Our use is a kernel with anarch/riscv64tree whose code only compiles for riscv64 (cfg(target_arch),core::arch::riscv64), which we want to prove from x86_64 and Apple Silicon machines, including GitHub-hosted runners. CBMC 6.11'sset_arch_spec_riscv64already exists, so CBMC needs no change.What changes
kani-compiler: ariscv64machine model (RISC-V psABI LP64D: unsignedchar, signed 32-bitwchar_t, 128-bitlong double, matching CBMC'sset_arch_spec_riscv64),riscv64-unknown-linux-gnuincheck_target, and theriscv64gctarget features intarget_config. Withoutdthere, rustc warns on every crate that the LP64D ABI needs it, and says the warning will become an error.kani-driver:--target <TRIPLE>, gated on-Z unstable-options, for bothkaniandcargo kani. It replacesenv!("TARGET")in the cargo invocation,cargo metadata --filter-platform, the coverage paths and the single-filerustccall. When it is not given, nothing changes: the host triple is used exactly as before, and single-file runs do not pass--targettorustcat all.--concrete-playbackwith a non-host--targetis rejected (the test runs on the host), and so isverify-std --target(itsno_corelibrary is host-only).cargo build-dev --lib-target <TRIPLE>(repeatable) also builds the verification libraries for that triple intotarget/kani/targets/<TRIPLE>/lib/, which is a complete sysroot of its own. The host keepslib/exactly as it is, so release bundles andcargo kani setupare unaffected. The driver looks for a non-host target's libraries there, and if they are missing it says which command builds them. The rustup target does not need to be installed, since-Z build-stdbuilds fromrust-src.Testing
tests/script-based-pre/target_riscv64. It runskanion a single file andcargo kanion a crate, both for riscv64. The harnesses sit behind#[cfg(target_arch = "riscv64")], so the test also shows that the host run finds none. They check target facts that differ from an x86_64 host (c_charis unsigned,target_feature = "d"), and there is one failing overflow check, so CBMC has to find something. The crate's harness stubs a function that usesrdcycleinline assembly, which does not compile for any other target. The test also covers the error when-Z unstable-optionsis missing, and the--concrete-playbackandverify-stdrejections. The missing-library error has no transcript-stable test: every targetcheck_targetaccepts has its libraries built somewhere in the CI matrix (riscv64's bykani-regression.sh, below), so the error cannot be triggered there.scripts/kani-regression.shnow builds with--lib-target riscv64gc-unknown-linux-gnuso this test runs in CI. That adds one library build to each of the fiveregressionmatrix jobs; on an Apple Silicon Mac it took about two minutes, under heavy load from other work. I can move it to a single separate job if you would rather keep it off the main regression path. None of the regression workflows have run on this PR yet; they are waiting for approval to run for a first-time contributor.cargo test -p kani-driver -p kani_metadata -p build-kani,./scripts/kani-fmt.sh --check, and the compiletest suitesui(152 passed),cargo-ui(30),cargo-kani(71),expected(478 passed, 16 ignored) andcargo-coverage(2). On 2026-10-03, rebased onmainat1640445da,script-based-prepassed (91, 1 ignored),uipassed (153) andcargo-uipassed (30). Theverify_std_cmdfailure I mentioned earlier did not recur. I have not run thecoveragesuite. I did not run the fullkanisuite or firecracker locally.no_stdkernel crate for riscv64 and verified its harnesses, stubs included.Something I noticed and did not change
When goto-cc links goto binaries, the first input's
__CPROVER_architecture_*symbols win, andlink_goto_binarypasseskani_lib.cas C source, which goto-cc compiles with the host's configuration. So the linked.outcarries the host's architecture (arm64andchar_is_unsigned = 0on Apple Silicon) rather than the model Kani wrote. Precompilingkani_lib.cand linking it after the Rust inputs would fix it; I'd propose that as a follow-up.Not in this PR
goto-cc -m32, plus the 64-bit assumptions @celinval mentioned in How to verify a target different to the host environment? #2086), 16-bitusize, and big-endian targets, all of which Command-line flag to change model target or environment #2402 asks for.cargo kani setup.-Zfeature name. This uses-Z unstable-options, like other experimental options. If you would prefer a named feature, or an RFC first, I'll do that.Disclosure
This change was written by an AI coding agent (Claude Code) working under my direction, for nife, a capability microkernel that uses Kani for its kernel proofs. I'm responsible for it and will follow up on review.
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.