/// Configuration used to represent an invocation of a C compiler. /// /// This can be used to figure out what compiler is in use, what the arguments /// to it are, and what the environment variables look like for the compiler. /// This can be used to further configure other build systems (e.g. forward /// along CC and/or CFLAGS) or the `to_command` method can be used to run the /// compiler itself. #[derive(Clone, Debug)] #[allow(missing_docs)] pubstruct Tool { pub(crate) path: PathBuf, pub(crate) cc_wrapper_path: Option<PathBuf>, pub(crate) cc_wrapper_args: Vec<OsString>, pub(crate) args: Vec<OsString>, pub(crate) env: Vec<(OsString, OsString)>, pub(crate) family: ToolFamily, pub(crate) cuda: bool, pub(crate) removed_args: Vec<OsString>, pub(crate) has_internal_target_arg: bool,
}
/// Add an argument to be stripped from the final command arguments. pub(crate) fn remove_arg(&mutself, flag: OsString) { self.removed_args.push(flag);
}
/// Push an "exotic" flag to the end of the compiler's arguments list. /// /// Nvidia compiler accepts only the most common compiler flags like `-D`, /// `-I`, `-c`, etc. Options meant specifically for the underlying /// host C++ compiler have to be prefixed with `-Xcompiler`. /// [Another possible future application for this function is passing /// clang-specific flags to clang-cl, which otherwise accepts only /// MSVC-specific options.] pub(crate) fn push_cc_arg(&mutself, flag: OsString) { ifself.cuda { self.args.push("-Xcompiler".into());
} self.args.push(flag);
}
/// Checks if an argument or flag has already been specified or conflicts. /// /// Currently only checks optimization flags. pub(crate) fn is_duplicate_opt_arg(&self, flag: &OsString) -> bool { let flag = flag.to_str().unwrap(); letmut chars = flag.chars();
// Only duplicate check compiler flags ifself.is_like_msvc() { if chars.next() != Some('/') { returnfalse;
}
} elseifself.is_like_gnu() || self.is_like_clang() { if chars.next() != Some('-') { returnfalse;
}
}
/// 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. pubfn to_command(&self) -> Command { letmut cmd = matchself.cc_wrapper_path {
Some(ref cc_wrapper_path) => { letmut cmd = Command::new(cc_wrapper_path);
cmd.arg(&self.path);
cmd
}
None => Command::new(&self.path),
};
cmd.args(&self.cc_wrapper_args);
let value = self
.args
.iter()
.filter(|a| !self.removed_args.contains(a))
.collect::<Vec<_>>();
cmd.args(&value);
for (k, v) inself.env.iter() {
cmd.env(k, v);
}
cmd
}
/// Returns the path for this compiler. /// /// Note that this may not be a path to a file on the filesystem, e.g. "cc", /// but rather something which will be resolved when a process is spawned. pubfn path(&self) -> &Path {
&self.path
}
/// Returns the default set of arguments to the compiler needed to produce /// executables for the target this compiler generates. pubfn args(&self) -> &[OsString] {
&self.args
}
/// Returns the set of environment variables needed for this compiler to /// operate. /// /// This is typically only used for MSVC compilers currently. pubfn env(&self) -> &[(OsString, OsString)] {
&self.env
}
/// Returns the compiler command in format of CC environment variable. /// Or empty string if CC env was not present /// /// This is typically used by configure script pubfn cc_env(&self) -> OsString { matchself.cc_wrapper_path {
Some(ref cc_wrapper_path) => { letmut cc_env = cc_wrapper_path.as_os_str().to_owned();
cc_env.push(" ");
cc_env.push(self.path.to_path_buf().into_os_string()); for arg inself.cc_wrapper_args.iter() {
cc_env.push(" ");
cc_env.push(arg);
}
cc_env
}
None => OsString::from(""),
}
}
/// Returns the compiler flags in format of CFLAGS environment variable. /// Important here - this will not be CFLAGS from env, its internal gcc's flags to use as CFLAGS /// This is typically used by configure script pubfn cflags_env(&self) -> OsString { letmut flags = OsString::new(); for (i, arg) inself.args.iter().enumerate() { if i > 0 {
flags.push(" ");
}
flags.push(arg);
}
flags
}
/// Whether the tool is GNU Compiler Collection-like. pubfn is_like_gnu(&self) -> bool { self.family == ToolFamily::Gnu
}
/// Whether the tool is Clang-like. pubfn is_like_clang(&self) -> bool { self.family == ToolFamily::Clang
}
/// Whether the tool is AppleClang under .xctoolchain #[cfg(target_vendor = "apple")] pub(crate) fn is_xctoolchain_clang(&self) -> bool { let path = self.path.to_string_lossy();
path.contains(".xctoolchain/")
} #[cfg(not(target_vendor = "apple"))] pub(crate) fn is_xctoolchain_clang(&self) -> bool { false
}
/// Represents the family of tools this tool belongs to. /// /// Each family of tools differs in how and what arguments they accept. /// /// Detection of a family is done on best-effort basis and may not accurately reflect the tool. #[derive(Copy, Clone, Debug, PartialEq)] pubenum ToolFamily { /// Tool is GNU Compiler Collection-like.
Gnu, /// Tool is Clang-like. It differs from the GCC in a sense that it accepts superset of flags /// and its cross-compilation approach is different.
Clang, /// Tool is the MSVC cl.exe.
Msvc { clang_cl: bool },
}
impl ToolFamily { /// What the flag to request debug info for this family of tools look like pub(crate) fn add_debug_flags(&self, cmd: &mut Tool, dwarf_version: Option<u32>) { match *self {
ToolFamily::Msvc { .. } => {
cmd.push_cc_arg("-Z7".into());
}
ToolFamily::Gnu | ToolFamily::Clang => {
cmd.push_cc_arg(
dwarf_version
.map_or_else(|| "-g".into(), |v| format!("-gdwarf-{}", v))
.into(),
);
}
}
}
/// What the flag to force frame pointers. pub(crate) fn add_force_frame_pointer(&self, cmd: &mut Tool) { match *self {
ToolFamily::Gnu | ToolFamily::Clang => {
cmd.push_cc_arg("-fno-omit-frame-pointer".into());
}
_ => (),
}
}
/// What the flags to enable all warnings pub(crate) fn warnings_flags(&self) -> &'static str { match *self {
ToolFamily::Msvc { .. } => "-W4",
ToolFamily::Gnu | ToolFamily::Clang => "-Wall",
}
}
/// What the flags to enable extra warnings pub(crate) fn extra_warnings_flags(&self) -> Option<&'static str> { match *self {
ToolFamily::Msvc { .. } => None,
ToolFamily::Gnu | ToolFamily::Clang => Some("-Wextra"),
}
}
/// What the flag to turn warning into errors pub(crate) fn warnings_to_errors_flag(&self) -> &'static str { match *self {
ToolFamily::Msvc { .. } => "-WX",
ToolFamily::Gnu | ToolFamily::Clang => "-Werror",
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.