56
56
#![ allow( deprecated) ]
57
57
#![ deny( missing_docs) ]
58
58
59
+ pub use crate :: json_compilation_database:: CompileCommand ;
60
+ pub use crate :: json_compilation_database:: store_json_compilation_database;
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,14 @@ 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 > where P : AsRef < Path > {
3291
3324
fn check_exe ( exe : & mut PathBuf ) -> bool {
3292
3325
let exe_ext = std:: env:: consts:: EXE_EXTENSION ;
3293
3326
exe. exists ( ) || ( !exe_ext. is_empty ( ) && exe. set_extension ( exe_ext) && exe. exists ( ) )
3294
3327
}
3295
3328
3296
3329
// If |tool| is not just one "word," assume it's an actual path...
3330
+ let tool = tool. as_ref ( ) ;
3297
3331
if tool. components ( ) . count ( ) > 1 {
3298
3332
let mut exe = PathBuf :: from ( tool) ;
3299
3333
return if check_exe ( & mut exe) { Some ( exe) } else { None } ;
0 commit comments