Browse Source

Cleanup after merging with latest master.

cl-test
Peter Jin 7 years ago
parent
commit
79a2b73931
  1. 16
      README.md
  2. 120
      src/lib.rs

16
README.md

@ -159,18 +159,26 @@ linked to the crate target.
## CUDA C++ support
`gcc-rs` also supports compiling CUDA C++ libraries by using the `cuda` method
`cc-rs` also supports compiling CUDA C++ libraries by using the `cuda` method
on `Build` (currently for GNU/Clang toolchains only):
```rust,no_run
extern crate gcc;
extern crate cc;
fn main() {
gcc::Build::new()
cc::Build::new()
// Switch to CUDA C++ library compilation using NVCC.
.cuda(true)
// Generate code for Maxwell architecture.
// Generate code for Maxwell (GTX 970, 980, 980 Ti, Titan X).
.flag("-gencode").flag("arch=compute_52,code=sm_52")
// Generate code for Maxwell (Jetson TX1).
.flag("-gencode").flag("arch=compute_53,code=sm_53")
// Generate code for Pascal (GTX 1070, 1080, 1080 Ti, Titan Xp).
.flag("-gencode").flag("arch=compute_61,code=sm_61")
// Generate code for Pascal (Tesla P100).
.flag("-gencode").flag("arch=compute_60,code=sm_60")
// Generate code for Pascal (Jetson TX2).
.flag("-gencode").flag("arch=compute_62,code=sm_62")
.file("bar.cu")
.compile("libbar.a");
}

120
src/lib.rs

@ -98,7 +98,6 @@ pub struct Build {
flags: Vec<String>,
flags_supported: Vec<String>,
files: Vec<PathBuf>,
dialect: Dialect,
cpp: bool,
cpp_link_stdlib: Option<Option<String>>,
cpp_set_stdlib: Option<String>,
@ -174,6 +173,7 @@ pub struct Tool {
args: Vec<OsString>,
env: Vec<(OsString, OsString)>,
family: ToolFamily,
cuda: bool,
}
/// Represents the family of tools this tool belongs to.
@ -257,52 +257,19 @@ impl ToolFamily {
}
}
/// Represents different C-like dialects.
///
/// Each dialect may require different compilers and compiler invocations.
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Dialect {
/// Language dialect is C.
C,
/// Language dialect is C++.
Cpp,
/// Language dialect is CUDA C++ (currently a superset of C++11).
Cuda,
}
/// Detect the language dialect based on source file extension.
pub fn autodetect_ext(src: &Path) -> Dialect {
if let Some(ext) = src.extension().and_then(|e| e.to_str()) {
match ext {
"c" => Dialect::C,
"cc" |
"cpp" |
"cxx" => Dialect::Cpp,
"cu" => Dialect::Cuda,
_ => panic!("unknown source extension: {:?}", src),
}
} else {
panic!("source is missing an extension: {:?}", src);
}
}
/// Represents an object.
///
/// This is a source file -> object file pair, with an associated language
/// dialect.
/// This is a source file -> object file pair.
#[derive(Clone, Debug)]
pub struct Object {
dialect: Dialect,
src: PathBuf,
dst: PathBuf,
}
impl Object {
/// Create a new source file -> object file pair, while autodetecting the
/// dialect from the source file extension.
pub fn new(src: PathBuf, dst: PathBuf) -> Object {
/// Create a new source file -> object file pair.
fn new(src: PathBuf, dst: PathBuf) -> Object {
Object {
dialect: autodetect_ext(&src),
src: src,
dst: dst,
}
@ -325,7 +292,6 @@ impl Build {
files: Vec::new(),
shared_flag: None,
static_flag: None,
dialect: Dialect::C,
cpp: false,
cpp_link_stdlib: None,
cpp_set_stdlib: None,
@ -436,7 +402,7 @@ impl Build {
.opt_level(0)
.host(&target)
.debug(false)
.cpp(self.cpp);
.cpp(self.cpp)
.cuda(self.cuda);
let compiler = cfg.try_get_compiler()?;
let mut cmd = compiler.to_command();
@ -511,13 +477,6 @@ impl Build {
/// Add a file which will be compiled
pub fn file<P: AsRef<Path>>(&mut self, p: P) -> &mut Build {
self.files.push(p.as_ref().to_path_buf());
match (self.dialect, autodetect_ext(p.as_ref())) {
(_, Dialect::C) => {}
(Dialect::C, Dialect::Cpp) |
(Dialect::Cpp, Dialect::Cpp) => { self.cpp(true); }
(Dialect::Cuda, Dialect::Cpp) => {}
(_, Dialect::Cuda) => { self.cuda(true); }
}
self
}
@ -539,9 +498,6 @@ impl Build {
/// `true`.
pub fn cpp(&mut self, cpp: bool) -> &mut Build {
self.cpp = cpp;
if cpp {
self.dialect = Dialect::Cpp;
}
self
}
@ -556,7 +512,6 @@ impl Build {
pub fn cuda(&mut self, cuda: bool) -> &mut Build {
self.cuda = cuda;
if cuda {
self.dialect = Dialect::Cuda;
self.cpp = true;
}
self
@ -929,8 +884,8 @@ impl Build {
let results: Mutex<Vec<Result<(), Error>>> = Mutex::new(Vec::new());
objs.par_iter().with_max_len(1).for_each(
|&(ref src, ref dst)| {
let res = self.compile_object(src, dst);
|obj| {
let res = self.compile_object(obj);
results.lock().unwrap().push(res)
},
);
@ -1066,11 +1021,6 @@ impl Build {
let target = self.get_target()?;
let mut cmd = self.get_base_compiler()?;
let nvcc = cmd.path
.file_name()
.and_then(|p| p.to_str())
.map(|p| p.contains("nvcc"))
.unwrap_or(false);
// Non-target flags
// If the flag is not conditioned on target variable, it belongs here :)
@ -1113,13 +1063,10 @@ impl Build {
cmd.args.push(format!("-O{}", opt_level).into());
}
cmd.nvcc_wrap_arg(self.cuda);
cmd.args.push("-ffunction-sections".into());
cmd.nvcc_wrap_arg(self.cuda);
cmd.args.push("-fdata-sections".into());
cmd.push_cc_arg("-ffunction-sections".into());
cmd.push_cc_arg("-fdata-sections".into());
if self.pic.unwrap_or(!target.contains("windows-gnu")) {
cmd.nvcc_wrap_arg(self.cuda);
cmd.args.push("-fPIC".into());
cmd.push_cc_arg("-fPIC".into());
}
}
}
@ -1129,11 +1076,11 @@ impl Build {
if self.get_debug() {
if self.cuda {
let nvcc_debug_arg = cmd.family.nvcc_debug_flag().into();
cmd.args.push(nvcc_debug_arg);
let nvcc_debug_flag = cmd.family.nvcc_debug_flag().into();
cmd.args.push(nvcc_debug_flag);
}
cmd.nvcc_wrap_arg(self.cuda);
cmd.args.push(cmd.family.debug_flag().into());
let debug_flag = cmd.family.debug_flag().into();
cmd.push_cc_arg(debug_flag);
}
// Target flags
@ -1248,8 +1195,7 @@ impl Build {
(None, _) => {}
(Some(stdlib), ToolFamily::Gnu) |
(Some(stdlib), ToolFamily::Clang) => {
cmd.nvcc_wrap_arg(self.cuda);
cmd.args.push(format!("-stdlib=lib{}", stdlib).into());
cmd.push_cc_arg(format!("-stdlib=lib{}", stdlib).into());
}
_ => {
println!(
@ -1268,7 +1214,7 @@ impl Build {
if self.warnings {
for flag in cmd.family.warnings_flags().iter() {
cmd.args.push(flag.into());
cmd.push_cc_arg(flag.into());
}
}
@ -1278,8 +1224,7 @@ impl Build {
for flag in self.flags_supported.iter() {
if self.is_flag_supported(flag).unwrap_or(false) {
cmd.nvcc_wrap_arg(self.cuda);
cmd.args.push(flag.into());
cmd.push_cc_arg(flag.into());
}
}
@ -1296,16 +1241,9 @@ impl Build {
}
}
if self.warnings {
for flag in cmd.family.warnings_flags().iter() {
cmd.nvcc_wrap_arg(self.cuda);
cmd.args.push(flag.into());
}
}
if self.warnings_into_errors {
cmd.nvcc_wrap_arg(self.cuda);
cmd.args.push(cmd.family.warnings_to_errors_flag().into());
let warnings_to_errors_flag = cmd.family.warnings_to_errors_flag().into();
cmd.push_cc_arg(warnings_to_errors_flag);
}
Ok(cmd)
@ -1361,9 +1299,7 @@ impl Build {
let mut out = OsString::from("/OUT:");
out.push(dst);
run(
cmd.arg(out).arg("/nologo").args(objects).args(
&self.objects,
),
cmd.arg(out).arg("/nologo").args(&objects).args(&self.objects),
"lib.exe",
)?;
@ -1387,7 +1323,7 @@ impl Build {
} else {
let (mut ar, cmd) = self.get_ar()?;
run(
ar.arg("crs").arg(dst).args(objects).args(&self.objects),
ar.arg("crs").arg(dst).args(&objects).args(&self.objects),
&cmd,
)?;
}
@ -1590,7 +1526,7 @@ impl Build {
Err(_) => "nvcc".into(),
Ok(nvcc) => nvcc,
};
let mut nvcc_tool = Tool::new(PathBuf::from(nvcc));
let mut nvcc_tool = Tool::with_features(PathBuf::from(nvcc), self.cuda);
nvcc_tool.args.push(format!("-ccbin={}", tool.path.display()).into());
nvcc_tool
} else {
@ -1767,6 +1703,10 @@ impl Default for Build {
impl Tool {
fn new(path: PathBuf) -> Tool {
Tool::with_features(path, false)
}
fn with_features(path: PathBuf, cuda: bool) -> Tool {
// Try to detect family of the tool from its name, falling back to Gnu.
let family = if let Some(fname) = path.file_name().and_then(|p| p.to_str()) {
if fname.contains("clang") {
@ -1786,18 +1726,20 @@ impl Tool {
args: Vec::new(),
env: Vec::new(),
family: family,
cuda: cuda,
}
}
/// Optionally appends the NVCC wrapper flag "-Xcompiler".
/// Add a flag, and optionally prepend the NVCC wrapper flag "-Xcompiler".
///
/// Currently this is only used for compiling CUDA sources, since NVCC only
/// accepts a limited set of GNU-like flags, and the rest must be prefixed
/// with a "-Xcompiler" flag to get passed to the underlying C++ compiler.
fn nvcc_wrap_arg(&mut self, cuda: bool) {
if cuda {
fn push_cc_arg(&mut self, flag: OsString) {
if self.cuda {
self.args.push(self.family.nvcc_redirect_flag().into());
}
self.args.push(flag);
}
/// Converts this compiler into a `Command` that's ready to be run.

Loading…
Cancel
Save