Skip to content

Commit

Permalink
Fix windows CI builds (#1476)
Browse files Browse the repository at this point in the history
* Prevent .pdb files from being generated in windows

* test

* Test another thing

* For tests, find executables for target-specific prusti

* test it

* Try it

* Windows-specific tests

* More

* format

* More reliable finding of executables

* add cfg print for testing

* Try specfiying target in .cargo/config.toml

* Refactor

* Comments and resume normal workflow logic

* Perhaps an even better soln

* Update test.yml

* Put stuff in the right spots

* Revert workflow, update a comment

* test jobs = 1
  • Loading branch information
zgrannan committed Dec 5, 2023
1 parent a5c29c9 commit a59d989
Show file tree
Hide file tree
Showing 11 changed files with 131 additions and 121 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ jobs:
- name: Build with cargo
run: python x.py build --all --jobs 1
- name: Run cargo tests
run: python x.py test --all
run: python x.py test --all --jobs 1
- name: Run a subset of tests with Carbon
run: |
python x.py test pass/no-annotation --all --verbose
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions analysis/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ syn = { version = "1.0", features = [ "full", "parsing" ] }
derive_more = "0.99"
prusti-rustc-interface = { path = "../prusti-rustc-interface" }
tracing = { path = "../tracing" }
prusti-utils = { path = "../prusti-utils" }

[dev-dependencies]
compiletest_rs = "0.10"
Expand Down
1 change: 1 addition & 0 deletions analysis/tests/test_accessibility.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod utils;

use glob::glob;
use prusti_utils::utils::find_compiled_executable;
use std::{
env,
ffi::OsStr,
Expand Down
1 change: 1 addition & 0 deletions analysis/tests/test_analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ mod utils;

/// Source: https://github.com/rust-lang/miri/blob/master/tests/compiletest.rs
use compiletest_rs as compiletest;
use prusti_utils::utils::find_compiled_executable;
use std::{env, path::PathBuf};
use utils::*;

Expand Down
32 changes: 0 additions & 32 deletions analysis/tests/utils.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,3 @@
use std::path::PathBuf;

pub fn find_compiled_executable(name: &str) -> PathBuf {
let target_directory = if cfg!(debug_assertions) {
"debug"
} else {
"release"
};
let executable_name = if cfg!(windows) {
format!("{name}.exe")
} else {
name.to_string()
};
let local_driver_path: PathBuf = ["target", target_directory, executable_name.as_str()]
.iter()
.collect();
if local_driver_path.exists() {
return local_driver_path;
}
let workspace_driver_path: PathBuf =
["..", "target", target_directory, executable_name.as_str()]
.iter()
.collect();
if workspace_driver_path.exists() {
return workspace_driver_path;
}
panic!(
"Could not find the {target_directory:?} {executable_name:?} binary to be used in tests. \
It might be that the project has not been compiled correctly."
);
}

pub fn find_sysroot() -> String {
// Taken from https://github.com/Manishearth/rust-clippy/pull/911.
let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
Expand Down
38 changes: 22 additions & 16 deletions prusti-contracts-build/build.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
use std::{path::PathBuf, process::Command};

use prusti_utils::launch::get_prusti_contracts_build_target_dir;

fn executable_name(name: &str) -> String {
#[cfg(windows)]
let name = format!("{}.exe", name);

#[cfg(not(windows))]
let name = name.to_string();

name
}

fn main() {
// Rerun if running with e.g. cargo clippy
println!("cargo:rerun-if-env-changed=RUSTC_WORKSPACE_WRAPPER");
Expand All @@ -14,32 +26,26 @@ fn main() {
let target: PathBuf = ["..", "target"].iter().collect();
force_reexport_specs(target.join("verify").as_path());

// Copy just-built binaries to `target/dir` dir
let bin_dir = if cfg!(debug_assertions) {
target.join("debug")
} else {
target.join("release")
};
let target = get_prusti_contracts_build_target_dir(&target);
let bin_dir = target.join("bin");
std::fs::create_dir_all(&bin_dir).unwrap();

// Copies all files into `bin_dir`. `cargo_prusti` cannot be run directly
// from std::env::var("CARGO_BIN_FILE_PRUSTI_LAUNCH_cargo-prusti")
// because it requires `prusti-rustc` and `prusti-driver` to be in the same
// path.
for (krate, file) in [
("PRUSTI_LAUNCH", "cargo-prusti"),
("PRUSTI_LAUNCH", "prusti-rustc"),
("PRUSTI", "prusti-driver"),
] {
let file_from = std::env::var(format!("CARGO_BIN_FILE_{krate}_{file}")).unwrap();
let file_to = &format!("{file}{}", if cfg!(windows) { ".exe" } else { "" });
let file_to = executable_name(file);
let file_to = bin_dir.join(file_to);
std::fs::copy(file_from, file_to).unwrap();
}

// Run `cargo-prusti`
let cargo_prusti = format!("cargo-prusti{}", if cfg!(windows) { ".exe" } else { "" });
let cargo_prusti = bin_dir.join(cargo_prusti);

// In theory we should build to here (i.e. set `CARGO_TARGET_DIR` to this),
// but this is hard to find for linking. So instead build to the `prusti-contracts` dir.
// let out_dir = std::env::var("OUT_DIR").unwrap();
// println!("cargo:warning=out_dir: {}", out_dir);

let cargo_prusti = bin_dir.join(executable_name("cargo-prusti"));
let mut cmd = Command::new(cargo_prusti);
cmd.env("CARGO_TARGET_DIR", target.as_os_str());
cmd.current_dir(&prusti_contracts);
Expand Down
40 changes: 6 additions & 34 deletions prusti-launch/tests/test_binaries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,41 +5,13 @@
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use glob::glob;
use prusti_utils::utils::find_compiled_executable;
use std::{
io::{BufRead, BufReader},
path::PathBuf,
process::{Child, Command, Stdio},
};

fn find_executable_path(base_name: &str) -> PathBuf {
let target_directory = if cfg!(debug_assertions) {
"debug"
} else {
"release"
};
let executable_name = if cfg!(windows) {
format!("{base_name}.exe")
} else {
base_name.to_string()
};
let local_prusti_rustc_path: PathBuf = ["target", target_directory, &executable_name]
.iter()
.collect();
if local_prusti_rustc_path.exists() {
return local_prusti_rustc_path;
}
let workspace_prusti_rustc_path: PathBuf = ["..", "target", target_directory, &executable_name]
.iter()
.collect();
if workspace_prusti_rustc_path.exists() {
return workspace_prusti_rustc_path;
}
panic!(
"Could not find the {target_directory:?} prusti-rustc binary to be used in tests. \
It might be that Prusti has not been compiled correctly."
);
}

fn run_on_test_files<F: Fn(&PathBuf) -> Command>(run: F) {
let mut num_pass_tests = 0;
let pass_entries = glob("tests/pass/**/*.rs").expect("failed to read glob pattern");
Expand Down Expand Up @@ -107,7 +79,7 @@ impl Drop for ChildGuard {

#[test]
fn test_prusti_rustc() {
let prusti_rustc = find_executable_path("prusti-rustc");
let prusti_rustc = find_compiled_executable("prusti-rustc");

run_on_test_files(|program: &PathBuf| {
let mut cmd = Command::new(&prusti_rustc);
Expand All @@ -121,7 +93,7 @@ fn test_prusti_rustc() {

#[test]
fn test_prusti_rustc_dump() {
let prusti_rustc = find_executable_path("prusti-rustc");
let prusti_rustc = find_compiled_executable("prusti-rustc");

run_on_test_files(|program: &PathBuf| {
let mut cmd = Command::new(&prusti_rustc);
Expand All @@ -146,7 +118,7 @@ fn test_prusti_rustc_dump() {
// so this test fails.
#[test]
fn test_prusti_be_rustc() {
let prusti_rustc = find_executable_path("prusti-rustc");
let prusti_rustc = find_compiled_executable("prusti-rustc");
run_on_test_files(|program: &PathBuf| {
let mut cmd = Command::new(&prusti_rustc);
Expand All @@ -162,8 +134,8 @@ fn test_prusti_be_rustc() {

#[test]
fn test_prusti_rustc_with_server() {
let prusti_rustc = find_executable_path("prusti-rustc");
let prusti_server = find_executable_path("prusti-server");
let prusti_rustc = find_compiled_executable("prusti-rustc");
let prusti_server = find_compiled_executable("prusti-server");

// Preserve SYSTEMROOT on Windows.
// See: https://travis-ci.community/t/socket-the-requested-service-provider-could-not-be-loaded-or-initialized/1127
Expand Down
2 changes: 1 addition & 1 deletion prusti-utils/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ pub fn viper_home() -> String {
if let Some(path) = find_viper_home(&current_executable_dir) {
path.to_str().unwrap().to_owned()
} else {
panic!("Failed to detect Vipe home, please set viper_home configuration flag")
panic!("Failed to detect Viper home, please set viper_home configuration flag")
}
}
}
Expand Down
82 changes: 45 additions & 37 deletions prusti-utils/src/launch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ pub mod job;
/// for `prusti-rustc`.
pub const PRUSTI_LIBS: [&str; 2] = ["prusti-contracts", "prusti-std"];

#[cfg(debug_assertions)]
pub const BUILD_MODE: &str = "debug";

#[cfg(not(debug_assertions))]
pub const BUILD_MODE: &str = "release";

pub fn get_current_executable_dir() -> PathBuf {
env::current_exe()
.expect("current executable path invalid")
Expand All @@ -26,26 +32,32 @@ pub fn get_current_executable_dir() -> PathBuf {
.to_path_buf()
}

/// Finds the closest `target` directory in the current path.
/// This should be the target directory at the root of the repository,
/// i.e. `prusti-dev/target`.
pub fn get_target_dir(exe_dir: &Path) -> PathBuf {
let mut root_dir = exe_dir;
while root_dir.file_name().unwrap() != "target" {
root_dir = root_dir.parent().unwrap();
}
root_dir.to_path_buf()
}

pub fn get_prusti_contracts_build_target_dir(target_dir: &Path) -> PathBuf {
target_dir.join("prusti-contracts").join(BUILD_MODE)
}

pub fn get_prusti_contracts_dir(exe_dir: &Path) -> Option<PathBuf> {
let a_prusti_contracts_file = format!("lib{}.rlib", PRUSTI_LIBS[0].replace('-', "_"));
let target_dir = if cfg!(debug_assertions) {
"debug"
} else {
"release"
};

let target_dir = get_target_dir(exe_dir);
let candidates = [
// Libraries in the Prusti artifact will show up here
exe_dir.to_path_buf(),
get_prusti_contracts_build_target_dir(&target_dir),
// Libraries when building Prusti will show up here
exe_dir
.parent()
.unwrap()
.parent()
.unwrap()
.join("target")
.join("verify")
.join(target_dir),
];
target_dir,
]
.map(|path| path.join("verify").join(BUILD_MODE));
candidates
.into_iter()
.find(|candidate| candidate.join(&a_prusti_contracts_file).exists())
Expand Down Expand Up @@ -178,28 +190,24 @@ fn get_sysroot_from_rustup() -> Option<PathBuf> {

/// Find Viper home
pub fn find_viper_home(base_dir: &Path) -> Option<PathBuf> {
let candidates = vec![
base_dir.join("viper_tools").join("server"),
base_dir
.join("..")
.join("..")
.join("viper_tools")
.join("server"),
base_dir.join("viper_tools").join("backends"),
base_dir
.join("..")
.join("..")
.join("viper_tools")
.join("backends"),
base_dir
.join("..")
.join("..")
.join("..")
.join("viper_tools")
.join("backends"),
];

candidates.into_iter().find(|candidate| candidate.is_dir())
let mut dir = base_dir;
loop {
if dir.join("viper_tools").is_dir() {
let viper_tools_dir = dir.join("viper_tools");
let backends_dir = viper_tools_dir.join("backends");
if backends_dir.is_dir() {
return Some(backends_dir);
}
let server_dir = viper_tools_dir.join("server");
if server_dir.is_dir() {
return Some(server_dir);
}
}
match dir.parent() {
Some(parent) => dir = parent,
None => return None,
}
}
}

/// Find Z3 executable
Expand Down
52 changes: 52 additions & 0 deletions prusti-utils/src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,55 @@

pub mod identifiers;
pub mod to_string;
use std::{env, path::PathBuf};

pub fn find_compiled_executable(name: &str) -> PathBuf {
let target_directory = if cfg!(debug_assertions) {
"debug"
} else {
"release"
};

let mut target_path = PathBuf::from("target");

// If prusti was compiled for a custom target, e.g. via x.py build --target
// <triple>, then the executables will be placed in /target/<triple>/debug
// rather than /target/debug.

// The environment variable COMPILATION_TARGET_PRUSTI should be set to the
// appropriate triple when running the tests, so that executable for that
// target is used.
if let Ok(triple) = env::var("COMPILATION_TARGET_PRUSTI") {
if !triple.is_empty() {
target_path.push(triple);
}
}

target_path.push(target_directory);

let executable_name = if cfg!(windows) {
format!("{name}.exe")
} else {
name.to_string()
};

let mut local_driver_path = target_path.clone();
local_driver_path.push(&executable_name);

if local_driver_path.exists() {
return local_driver_path;
}

let mut workspace_driver_path = PathBuf::from("..");
workspace_driver_path.push(target_path);
workspace_driver_path.push(&executable_name);

if workspace_driver_path.exists() {
return workspace_driver_path;
}

panic!(
"Could not find the {target_directory:?} {executable_name:?} binary to be used in tests. \
It might be that the project has not been compiled correctly."
);
}

0 comments on commit a59d989

Please sign in to comment.