rust-lang / cc-rs

Rust library for build scripts to compile C/C++ code into a Rust library
https://docs.rs/cc
Apache License 2.0
1.76k stars 425 forks source link

`cc` fails to parse CC with multiple compilers listed #1081

Open Redrield opened 1 month ago

Redrield commented 1 month ago

Summary

I use lunarvim as my development environment for my work, including Rust projects. A combination of lunarvim on NixOS prefixing the CC environment variable with the value cc, and Nix development environments exporting CC=gcc leads to an overall environment of CC=cc:gcc in Lunarvim. When executing commands in a normal shell, this isn't an issue. exec $CC with CC=cc:gcc calls the C compiler correctly. However, given this somewhat bizarre environment in Lunarvim, coupled with the fact that it launches rust-analyzer (which will therefore inherit the environment), I ran into the situation where cc's logic to extract the compiler name from the environment leads to an argv[0] of cc:gcc, which is of course incorrect.

Minimal reproduction

fn list_var() {
    let test = Test::gnu();
    env::set_var("CC", "cc:gcc");
    let compiler = test.gcc().file("foo.c").get_compiler();
    assert_eq!(compiler.path(), Path::new("cc"));
}

I've tested this in the cc_env test suite on the latest diff of cc-rs, and the test fails with the following output:

thread 'main' panicked at tests/cc_env.rs:125:5:
assertion `left == right` failed
  left: "cc:gcc"
 right: "cc"
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

failures:
    main

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.45s

Root cause

The root cause is :-delimited lists not being accounted for in Build::env_tool (lib.rs 3010:3076). tool at line 3016 = cc:gcc, which falls through to the wrapper handling code, leading to maybe_wrapper = cc:gcc, which continues to fall through to the final return statement, where cc:gcc is returned as the compiler path (.0 of the tuple returned by env_tool).

NobodyXu commented 4 weeks ago

How does nix/lunarvim interprets cc:gcc

Redrield commented 4 weeks ago

exec $CC in that case calls cc I believe (Hard to tell, because they both lead to calling gcc)

NobodyXu commented 4 weeks ago

That's really confusing though, the convention is for CC to be a path, and : is a valid character in the path.

Not sure how lunarvim/nix supports it.