Skip to content

Commit

Permalink
Add support for parsing *FLAGS with shlex
Browse files Browse the repository at this point in the history
  • Loading branch information
xbjfk committed Aug 12, 2024
1 parent eb33906 commit ff44133
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 6 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ rust-version = "1.63"

[dependencies]
jobserver = { version = "0.1.30", default-features = false, optional = true }
shlex = "1.3.0"

[target.'cfg(unix)'.dependencies]
# Don't turn on the feature "std" for this, see https://github.com/rust-lang/cargo/issues/4866
Expand Down
37 changes: 31 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@
//! * `CC_ENABLE_DEBUG_OUTPUT` - if set, compiler command invocations and exit codes will
//! be logged to stdout. This is useful for debugging build script issues, but can be
//! overly verbose for normal use.
//! * `CC_PARSE_FLAGS_WITH_SHLEX` - if set, *FLAGS will be parsed with shlex, similar to
//! `make` and `cmake`. `CFLAGS='-foo "-bar baz"'` will be parsed as `["foo", "-bar baz"]`
//! instead of `["-foo", "\"-bar", "baz\""]`
//! * `CXX...` - see [C++ Support](#c-support).
//!
//! Furthermore, projects using this crate may specify custom environment variables
Expand Down Expand Up @@ -227,6 +230,7 @@ use std::sync::{Arc, RwLock};
#[cfg(feature = "parallel")]
mod parallel;
mod windows;
use shlex::Shlex;
// Regardless of whether this should be in this crate's public API,
// it has been since 2015, so don't break it.
pub use windows::find_tools as windows_registry;
Expand Down Expand Up @@ -301,6 +305,7 @@ pub struct Build {
apple_versions_cache: Arc<RwLock<HashMap<Box<str>, Arc<str>>>>,
emit_rerun_if_env_changed: bool,
cached_compiler_family: Arc<RwLock<HashMap<Box<Path>, ToolFamily>>>,
parse_flags_with_shlex: Option<bool>,
}

/// Represents the types of errors that may occur while using cc-rs.
Expand Down Expand Up @@ -425,6 +430,7 @@ impl Build {
apple_versions_cache: Arc::new(RwLock::new(HashMap::new())),
emit_rerun_if_env_changed: true,
cached_compiler_family: Arc::default(),
parse_flags_with_shlex: None,
}
}

Expand Down Expand Up @@ -1277,6 +1283,15 @@ impl Build {
self
}

/// Configure whether *FLAGS variables are parsed using `shlex`, similarly to `make` and
/// `cmake`.
///
/// This option defaults to `false`.
pub fn parse_flags_with_shlex(&mut self, parse_flags_with_shlex: bool) -> &mut Build {
self.parse_flags_with_shlex = Some(parse_flags_with_shlex);
self
}

#[doc(hidden)]
pub fn __set_env<A, B>(&mut self, a: A, b: B) -> &mut Build
where
Expand Down Expand Up @@ -3634,6 +3649,11 @@ impl Build {
})
}

fn get_parse_flags_with_shlex(&self) -> bool {
self.parse_flags_with_shlex
.unwrap_or_else(|| self.getenv("CC_PARSE_FLAGS_WITH_SHLEX").is_some())
}

fn get_dwarf_version(&self) -> Option<u32> {
// Tentatively matches the DWARF version defaults as of rustc 1.62.
let target = self.get_target().ok()?;
Expand Down Expand Up @@ -3748,12 +3768,17 @@ impl Build {
}

fn envflags(&self, name: &str) -> Result<Vec<String>, Error> {
Ok(self
.getenv_with_target_prefixes(name)?
.to_string_lossy()
.split_ascii_whitespace()
.map(ToString::to_string)
.collect())
let env_os = self.getenv_with_target_prefixes(name)?;
let env = env_os.to_string_lossy();

if self.get_parse_flags_with_shlex() {
Ok(Shlex::new(&env).collect())
} else {
Ok(env
.split_ascii_whitespace()
.map(ToString::to_string)
.collect())
}
}

fn fix_env_for_apple_os(&self, cmd: &mut Command) -> Result<(), Error> {
Expand Down
24 changes: 24 additions & 0 deletions tests/cflags_shlex.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
mod support;

use crate::support::Test;
use std::env;

/// This test is in its own module because it modifies the environment and would affect other tests
/// when run in parallel with them.
#[test]
fn gnu_test_parse_flags_with_shlex() {
env::set_var("CFLAGS", "foo \"bar baz\"");
env::set_var("CC_PARSE_FLAGS_WITH_SHLEX", "1");
let test = Test::gnu();
test.gcc().file("foo.c").compile("foo");

test.cmd(0).must_have("foo").must_have("bar baz");

env::remove_var("CC_PARSE_FLAGS_WITH_SHLEX");
let test = Test::gnu();
test.gcc().file("foo.c").compile("foo");

test.cmd(0)
.must_have("foo")
.must_have_in_order("\"bar", "baz\"");
}

0 comments on commit ff44133

Please sign in to comment.