Skip to content
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

Add independent flags to C or C++ files #1019

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
50 changes: 46 additions & 4 deletions src/lib.rs
Expand Up @@ -265,6 +265,8 @@ pub struct Build {
known_flag_support_status: Arc<Mutex<HashMap<String, bool>>>,
ar_flags: Vec<Arc<str>>,
asm_flags: Vec<Arc<str>>,
c_flags: Vec<Arc<str>>,
cpp_flags: Vec<Arc<str>>,
no_default_flags: bool,
files: Vec<Arc<Path>>,
cpp: bool,
Expand Down Expand Up @@ -388,6 +390,8 @@ impl Build {
known_flag_support_status: Arc::new(Mutex::new(HashMap::new())),
ar_flags: Vec::new(),
asm_flags: Vec::new(),
c_flags: Vec::new(),
cpp_flags: Vec::new(),
no_default_flags: false,
files: Vec::new(),
shared_flag: None,
Expand Down Expand Up @@ -564,6 +568,36 @@ impl Build {
self
}

/// Add an arbitrary flag to the invocation of the compiler for c files
///
/// # Example
///
/// ```no_run
/// cc::Build::new()
/// .file("src/foo.c")
/// .c_flag("-std=c99")
/// .compile("foo");
/// ```
pub fn c_flag(&mut self, flag: &str) -> &mut Build {
self.c_flags.push(flag.into());
self
}

/// Add an arbitrary flag to the invocation of the compiler for cpp files
///
/// # Example
///
/// ```no_run
/// cc::Build::new()
/// .file("src/foo.cpp")
/// .cpp_flag("-std=c++17")
/// .compile("foo");
/// ```
pub fn cpp_flag(&mut self, flag: &str) -> &mut Build {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think cxx_flags makes more sense.

cpp could be confused with pre-processors of C/C++ compiler.

self.cpp_flags.push(flag.into());
self
}

fn ensure_check_file(&self) -> Result<PathBuf, Error> {
let out_dir = self.get_out_dir()?;
let src = if self.cuda {
Expand Down Expand Up @@ -630,7 +664,7 @@ impl Build {
compiler.push_cc_arg("-Wno-unused-command-line-argument".into());
}

let mut cmd = compiler.to_command();
let mut cmd = compiler.to_command(None);
let is_arm = target.contains("aarch64") || target.contains("arm");
let clang = compiler.is_like_clang();
let gnu = compiler.family == ToolFamily::Gnu;
Expand Down Expand Up @@ -1587,7 +1621,7 @@ impl Build {
let (cmd, name) = self.msvc_macro_assembler()?;
(cmd, Cow::Borrowed(Path::new(name)))
} else {
let mut cmd = compiler.to_command();
let mut cmd = compiler.to_command(Some(&obj.src));
for (a, b) in self.env.iter() {
cmd.env(a, b);
}
Expand Down Expand Up @@ -1633,7 +1667,7 @@ impl Build {
/// This will return a result instead of panicking; see expand() for the complete description.
pub fn try_expand(&self) -> Result<Vec<u8>, Error> {
let compiler = self.try_get_compiler()?;
let mut cmd = compiler.to_command();
let mut cmd = compiler.to_command(None);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm I wonder if there's any C/C++ that affects the expand of C/C++ program?

I can't think of any specific to C or specific to C++, AFAIK the only way to affect that is via -D.

Maybe changing std version would affect that, I recalled that newer C standard introduces more macros.

for (a, b) in self.env.iter() {
cmd.env(a, b);
}
Expand Down Expand Up @@ -1790,6 +1824,14 @@ impl Build {
cmd.push_cc_arg(warnings_to_errors_flag);
}

for flag in self.c_flags.iter() {
cmd.c_args.push((**flag).into());
}

for flag in self.cpp_flags.iter() {
cmd.cpp_args.push((**flag).into());
}

Comment on lines +1827 to +1834
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need to do this in get_base_compiler, there are some functions which call it directly.

Ok(cmd)
}

Expand Down Expand Up @@ -2391,7 +2433,7 @@ impl Build {

let out_dir = self.get_out_dir()?;
let dlink = out_dir.join(lib_name.to_owned() + "_dlink.o");
let mut nvcc = self.get_compiler().to_command();
let mut nvcc = self.get_compiler().to_command(None);
nvcc.arg("--device-link").arg("-o").arg(&dlink).arg(dst);
run(&mut nvcc, "nvcc", &self.cargo_output)?;
self.assemble_progressive(dst, &[dlink.as_path()])?;
Expand Down
67 changes: 64 additions & 3 deletions src/tool.rs
Expand Up @@ -29,6 +29,8 @@ pub struct Tool {
pub(crate) cc_wrapper_path: Option<PathBuf>,
pub(crate) cc_wrapper_args: Vec<OsString>,
pub(crate) args: Vec<OsString>,
pub(crate) c_args: Vec<OsString>,
pub(crate) cpp_args: Vec<OsString>,
pub(crate) env: Vec<(OsString, OsString)>,
pub(crate) family: ToolFamily,
pub(crate) cuda: bool,
Expand Down Expand Up @@ -77,6 +79,8 @@ impl Tool {
cc_wrapper_path: None,
cc_wrapper_args: Vec::new(),
args: Vec::new(),
c_args: Vec::new(),
cpp_args: Vec::new(),
env: Vec::new(),
family,
cuda: false,
Expand Down Expand Up @@ -193,6 +197,8 @@ impl Tool {
cc_wrapper_path: None,
cc_wrapper_args: Vec::new(),
args: Vec::new(),
c_args: Vec::new(),
cpp_args: Vec::new(),
env: Vec::new(),
family,
cuda,
Expand Down Expand Up @@ -258,19 +264,72 @@ impl Tool {
}
}

/// Returns preferred compiler for source file.
fn preferred_compiler_for_source(&self, src: Option<&PathBuf>) -> (PathBuf, &[OsString]) {
let mut path = self.path.clone();
let mut extra_args: &[OsString] = &[];
if let Some(src) = src {
let mut is_c = false;
let mut is_cpp = false;
if let Some(ext) = src.extension().and_then(|x| x.to_str()) {
match ext {
"c" => {
is_c = true;
}
"cc" | "cpp" | "cxx" | "c++" => {
is_cpp = true;
}
_ => {}
}
}
match self.family {
ToolFamily::Clang { zig_cc } if !zig_cc => {
let s = path.to_string_lossy().to_string();
if is_c {
path = PathBuf::from(s.replace("clang++", "clang"));
extra_args = &self.c_args;
}
if is_cpp {
if s.ends_with("clang") {
path = PathBuf::from(s.replace("clang", "clang++"));
}
extra_args = &self.cpp_args;
}
}
ToolFamily::Gnu => {
let s = path.to_string_lossy().to_string();
if is_c {
path = PathBuf::from(s.replace("g++", "gcc"));
extra_args = &self.c_args;
}
if is_cpp {
path = PathBuf::from(s.replace("gcc", "g++"));
extra_args = &self.cpp_args;
}
}
_ => {}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that the c_flags and cpp_flags are ignored for msvc?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MSVC has only one cl.exe and has no special parameters for C or C++, so it can be ignored.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't have -std=c11 which is used in example?

}
}
(path, extra_args)
}

/// Converts this compiler into a `Command` that's ready to be run.
///
/// This is useful for when the compiler needs to be executed and the
/// command returned will already have the initial arguments and environment
/// variables configured.
pub fn to_command(&self) -> Command {
///
/// The `src` argument is used to determine the preferred compiler for the
/// source file. If `None`, the default compiler is used.
pub fn to_command(&self, src: Option<&PathBuf>) -> Command {
let (path, extra_args) = self.preferred_compiler_for_source(src);
let mut cmd = match self.cc_wrapper_path {
Some(ref cc_wrapper_path) => {
let mut cmd = Command::new(cc_wrapper_path);
cmd.arg(&self.path);
cmd.arg(&path);
cmd
}
None => Command::new(&self.path),
None => Command::new(&path),
};
cmd.args(&self.cc_wrapper_args);

Expand All @@ -281,6 +340,8 @@ impl Tool {
.collect::<Vec<_>>();
cmd.args(&value);

cmd.args(extra_args);

for (k, v) in self.env.iter() {
cmd.env(k, v);
}
Expand Down
2 changes: 1 addition & 1 deletion src/windows/find_tools.rs
Expand Up @@ -49,7 +49,7 @@ impl<'a> From<TargetArch<'a>> for &'a str {
///
/// Note that this function always returns `None` for non-MSVC targets.
pub fn find(target: &str, tool: &str) -> Option<Command> {
find_tool(target, tool).map(|c| c.to_command())
find_tool(target, tool).map(|c| c.to_command(None))
}

/// Similar to the `find` function above, this function will attempt the same
Expand Down