Skip to content

Add cargo_warnings config to control the use of the cargo warning instruction #917

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 24 commits into from
Jan 24, 2024
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
01e6e98
fix some instances of broken cargo:warning instruction
scootermon Jan 14, 2024
e7af292
allow disabling cargo warnings for compilation
scootermon Jan 14, 2024
4a90bd8
comply with MSRV
scootermon Jan 14, 2024
40bb482
allow dead_code to make ci pass
scootermon Jan 14, 2024
7d51284
make print thread optional
scootermon Jan 15, 2024
cf795f2
simplify warnings using macros
scootermon Jan 15, 2024
17535c3
add a test case
scootermon Jan 15, 2024
67213e0
this line in the docstring is no longer true
scootermon Jan 15, 2024
afada42
apply review suggestions
scootermon Jan 16, 2024
a3b4614
write warnings to buffered stdout
scootermon Jan 16, 2024
c8c61a2
add proper output tests
scootermon Jan 16, 2024
3079bb0
reduce import diff and always print stdout in tests
scootermon Jan 16, 2024
00e980c
correct println
scootermon Jan 16, 2024
fc72499
add an output abstraction
scootermon Jan 23, 2024
fc2fb66
hopefully make the tests work on win32
scootermon Jan 23, 2024
690269a
msvc-compatible warnings
scootermon Jan 23, 2024
a629690
turns out we can't capture warnings for msvc...
scootermon Jan 23, 2024
19174cb
fix unconditional metadata output
scootermon Jan 23, 2024
4b5cdf4
skip warnings_on test for msvc
scootermon Jan 23, 2024
4ab4158
Update src/lib.rs
scootermon Jan 24, 2024
02f8895
Update src/lib.rs
scootermon Jan 24, 2024
7495e35
Update src/lib.rs
scootermon Jan 24, 2024
d475e93
Update src/lib.rs
scootermon Jan 24, 2024
00ae7e0
Merge branch 'main' into disable-warnings
scootermon Jan 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 69 additions & 1 deletion cc-test/build.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,35 @@
use std::env;
use std::fs;
use std::path::PathBuf;
use std::path::{Path, PathBuf};
use std::process::Command;

fn main() {
// if we are being executed from a `fork_run_action` call (i.e. this is a
// "fork"), perform the requested action and then return.
if run_action_if_forked() {
return;
}

let out = PathBuf::from(env::var_os("OUT_DIR").unwrap());
fs::remove_dir_all(&out).unwrap();
fs::create_dir(&out).unwrap();

// The following are builds where we want to capture the output (i.e. stdout and
// stderr). We do that by re-running _this_ executable and passing in the
// action as the first argument.
run_forked_capture_output(&out, "metadata-on");
run_forked_capture_output(&out, "metadata-off");

run_forked_capture_output(&out, "warnings-off");
if cc::Build::new().get_compiler().is_like_msvc() {
// MSVC doesn't output warnings to stderr, so we can't capture them.
// the test will use this env var to know whether to run the test.
println!("cargo:rustc-env=TEST_WARNINGS_ON=0");
} else {
println!("cargo:rustc-env=TEST_WARNINGS_ON=1");
run_forked_capture_output(&out, "warnings-on");
}

cc::Build::new()
.file("src/foo.c")
.flag_if_supported("-Wall")
Expand Down Expand Up @@ -104,3 +127,48 @@ fn main() {
let out = String::from_utf8(out).unwrap();
assert!(out.contains("hello world"));
}

#[track_caller]
fn run_forked_capture_output(out: &Path, action: &str) {
let program = env::current_exe().unwrap();
let output = Command::new(&program).arg(action).output().unwrap();
assert!(output.status.success(), "output: {:#?}", output);
// we've captured the output and now we write it to a dedicated directory in the
// build output so our tests can access the output.
let action_dir = out.join(action);
fs::create_dir_all(&action_dir).unwrap();
fs::write(action_dir.join("stdout"), output.stdout).unwrap();
fs::write(action_dir.join("stderr"), output.stderr).unwrap();
}

fn run_action_if_forked() -> bool {
let mut args = env::args();
let _program = args.next().unwrap();
let action = args.next();
match action.as_deref() {
Some("metadata-on") => build_cargo_metadata(true),
Some("metadata-off") => build_cargo_metadata(false),
Some("warnings-on") => build_cargo_warnings(true),
Some("warnings-off") => build_cargo_warnings(false),
// No action requested, we're being called from cargo. Proceed with build.
_ => return false,
}
true
}

fn build_cargo_warnings(warnings: bool) {
cc::Build::new()
.cargo_metadata(false)
.cargo_warnings(warnings)
.file("src/compile_error.c")
.try_compile("compile_error")
.unwrap_err();
}

fn build_cargo_metadata(metadata: bool) {
cc::Build::new()
.cargo_metadata(metadata)
.file("src/dummy.c")
.try_compile("dummy")
.unwrap();
}
1 change: 1 addition & 0 deletions cc-test/src/compile_error.c
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#error "if you see this, cargo_warnings(false) didn't do its job"
3 changes: 3 additions & 0 deletions cc-test/src/dummy.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/* just an empty file */

void dummy(void) {}
68 changes: 68 additions & 0 deletions cc-test/tests/output.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use std::fs;
use std::path::PathBuf;

#[test]
fn cargo_warnings_on() {
if env!("TEST_WARNINGS_ON") == "0" {
// in some cases we don't catch compiler warnings and turn them into cargo
// instructions.
return;
}
let (stdout, stderr) = load_output("warnings-on");
assert!(stderr.is_empty());
assert!(stdout.contains("cargo:warning="));
}

#[test]
fn cargo_warnings_off() {
let (stdout, stderr) = load_output("warnings-off");
assert!(stderr.is_empty());
assert!(!stdout.contains("cargo:warning="));
}

#[test]
fn cargo_metadata_on() {
let (stdout, stderr) = load_output("metadata-on");
assert!(stderr.is_empty());
assert!(stdout.contains("cargo:rustc-link-lib="));
assert!(stdout.contains("cargo:rustc-link-search="));
}

#[test]
fn cargo_metadata_off() {
let (stdout, stderr) = load_output("metadata-off");
assert!(stderr.is_empty());

// most of the instructions aren't currently used
const INSTRUCTIONS: &[&str] = &[
"cargo:rerun-if-changed=",
"cargo:rerun-if-env-changed=",
"cargo:rustc-cdylib-link-arg=",
"cargo:rustc-cfg=",
"cargo:rustc-env=",
"cargo:rustc-flags=",
"cargo:rustc-link-arg-benches=",
"cargo:rustc-link-arg-bin=",
"cargo:rustc-link-arg-bins=",
"cargo:rustc-link-arg-examples=",
"cargo:rustc-link-arg-tests=",
"cargo:rustc-link-arg=",
"cargo:rustc-link-lib=",
"cargo:rustc-link-search=",
];
for instr in INSTRUCTIONS {
assert!(!stdout.contains(instr), "instruction present: {}", instr);
}
}

#[track_caller]
fn load_output(action: &str) -> (String, String) {
// these files are written by the `run_forked_capture_output` function in the
// build script.
let action_dir = PathBuf::from(env!("OUT_DIR")).join(action);
let stdout = fs::read_to_string(action_dir.join("stdout")).unwrap();
let stderr = fs::read_to_string(action_dir.join("stderr")).unwrap();
println!("compile stdout: {:?}", stdout);
println!("compile stderr: {:?}", stderr);
(stdout, stderr)
}
Loading