56
56
#![allow(deprecated)]
57
57
#![deny(missing_docs)]
58
58
59
+ pub use crate::json_compilation_database::store_json_compilation_database;
60
+ pub use crate::json_compilation_database::CompileCommand;
59
61
use std::collections::HashMap;
60
62
use std::env;
61
63
use std::ffi::{OsStr, OsString};
@@ -81,6 +83,7 @@ mod setup_config;
81
83
#[cfg(windows)]
82
84
mod vs_instances;
83
85
86
+ mod json_compilation_database;
84
87
pub mod windows_registry;
85
88
86
89
/// A builder for compilation of a native library.
@@ -943,8 +946,17 @@ impl Build {
943
946
944
947
/// Run the compiler, generating the file `output`
945
948
///
946
- /// This will return a result instead of panicing; see compile() for the complete description.
949
+ /// This will return a result instead of panicing; see [ compile()](Build::compile ) for the complete description.
947
950
pub fn try_compile(&self, output: &str) -> Result<(), Error> {
951
+ self.try_recorded_compile(output)?;
952
+ Ok(())
953
+ }
954
+
955
+ /// Run the compiler, generating the file `output` and provides compile commands for creating
956
+ /// [JSON Compilation Database](https://clang.llvm.org/docs/JSONCompilationDatabase.html).
957
+ ///
958
+ /// This will return a result instead of panicing; see [recorded_compile()](Build::recorded_compile) for the complete description.
959
+ pub fn try_recorded_compile(&self, output: &str) -> Result<Vec<CompileCommand>, Error> {
948
960
let mut output_components = Path::new(output).components();
949
961
match (output_components.next(), output_components.next()) {
950
962
(Some(Component::Normal(_)), None) => {}
@@ -990,7 +1002,7 @@ impl Build {
990
1002
991
1003
objects.push(Object::new(file.to_path_buf(), obj));
992
1004
}
993
- self.compile_objects(&objects)?;
1005
+ let entries = self.compile_objects(&objects)?;
994
1006
self.assemble(lib_name, &dst.join(gnu_lib_name), &objects)?;
995
1007
996
1008
if self.get_target()?.contains("msvc") {
@@ -1074,7 +1086,7 @@ impl Build {
1074
1086
}
1075
1087
}
1076
1088
1077
- Ok(() )
1089
+ Ok(entries )
1078
1090
}
1079
1091
1080
1092
/// Run the compiler, generating the file `output`
@@ -1120,6 +1132,26 @@ impl Build {
1120
1132
}
1121
1133
}
1122
1134
1135
+ /// Run the compiler, generating the file `output` and provides compile commands for creating
1136
+ /// [JSON Compilation Database](https://clang.llvm.org/docs/JSONCompilationDatabase.html),
1137
+ ///
1138
+ /// ```no_run
1139
+ /// let compile_commands = cc::Build::new().file("blobstore.c")
1140
+ /// .recorded_compile("blobstore");
1141
+ ///
1142
+ /// cc::store_json_compilation_database(&compile_commands, "target/compilation_database.json");
1143
+ /// ```
1144
+ ///
1145
+ /// See [compile()](Build::compile) for the further description.
1146
+ pub fn recorded_compile(&self, output: &str) -> Vec<CompileCommand> {
1147
+ match self.try_recorded_compile(output) {
1148
+ Ok(entries) => entries,
1149
+ Err(e) => {
1150
+ fail(&e.message);
1151
+ }
1152
+ }
1153
+ }
1154
+
1123
1155
#[cfg(feature = "parallel")]
1124
1156
fn compile_objects<'me>(&'me self, objs: &[Object]) -> Result<(), Error> {
1125
1157
use std::sync::atomic::{AtomicBool, Ordering::SeqCst};
@@ -1272,14 +1304,15 @@ impl Build {
1272
1304
}
1273
1305
1274
1306
#[cfg(not(feature = "parallel"))]
1275
- fn compile_objects(&self, objs: &[Object]) -> Result<(), Error> {
1307
+ fn compile_objects(&self, objs: &[Object]) -> Result<Vec<CompileCommand>, Error> {
1308
+ let mut entries = Vec::new();
1276
1309
for obj in objs {
1277
- self.compile_object(obj)?;
1310
+ entries.push( self.compile_object(obj)?) ;
1278
1311
}
1279
- Ok(() )
1312
+ Ok(entries )
1280
1313
}
1281
1314
1282
- fn compile_object(&self, obj: &Object) -> Result<() , Error> {
1315
+ fn compile_object(&self, obj: &Object) -> Result<CompileCommand , Error> {
1283
1316
let is_asm = obj.src.extension().and_then(|s| s.to_str()) == Some("asm");
1284
1317
let target = self.get_target()?;
1285
1318
let msvc = target.contains("msvc");
@@ -1324,7 +1357,7 @@ impl Build {
1324
1357
}
1325
1358
1326
1359
run(&mut cmd, &name)?;
1327
- Ok(( ))
1360
+ Ok(CompileCommand::new(&cmd, obj.src.clone(), obj.dst.clone() ))
1328
1361
}
1329
1362
1330
1363
/// This will return a result instead of panicing; see expand() for the complete description.
@@ -3287,13 +3320,17 @@ fn map_darwin_target_from_rust_to_compiler_architecture(target: &str) -> Option<
3287
3320
}
3288
3321
}
3289
3322
3290
- fn which(tool: &Path) -> Option<PathBuf> {
3323
+ pub(crate) fn which<P>(tool: P) -> Option<PathBuf>
3324
+ where
3325
+ P: AsRef<Path>,
3326
+ {
3291
3327
fn check_exe(exe: &mut PathBuf) -> bool {
3292
3328
let exe_ext = std::env::consts::EXE_EXTENSION;
3293
3329
exe.exists() || (!exe_ext.is_empty() && exe.set_extension(exe_ext) && exe.exists())
3294
3330
}
3295
3331
3296
3332
// If |tool| is not just one "word," assume it's an actual path...
3333
+ let tool = tool.as_ref();
3297
3334
if tool.components().count() > 1 {
3298
3335
let mut exe = PathBuf::from(tool);
3299
3336
return if check_exe(&mut exe) { Some(exe) } else { None };
0 commit comments