5656#![ allow( deprecated) ]
5757#![ deny( missing_docs) ]
5858
59+ pub use crate :: json_compilation_database:: CompileCommand ;
60+ pub use crate :: json_compilation_database:: store_json_compilation_database;
5961use std:: collections:: HashMap ;
6062use std:: env;
6163use std:: ffi:: { OsStr , OsString } ;
@@ -81,6 +83,7 @@ mod setup_config;
8183#[ cfg( windows) ]
8284mod vs_instances;
8385
86+ mod json_compilation_database;
8487pub mod windows_registry;
8588
8689/// A builder for compilation of a native library.
@@ -943,8 +946,17 @@ impl Build {
943946
944947 /// Run the compiler, generating the file `output`
945948 ///
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.
947950 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 > {
948960 let mut output_components = Path :: new ( output) . components ( ) ;
949961 match ( output_components. next ( ) , output_components. next ( ) ) {
950962 ( Some ( Component :: Normal ( _) ) , None ) => { }
@@ -990,7 +1002,7 @@ impl Build {
9901002
9911003 objects. push ( Object :: new ( file. to_path_buf ( ) , obj) ) ;
9921004 }
993- self . compile_objects ( & objects) ?;
1005+ let entries = self . compile_objects ( & objects) ?;
9941006 self . assemble ( lib_name, & dst. join ( gnu_lib_name) , & objects) ?;
9951007
9961008 if self . get_target ( ) ?. contains ( "msvc" ) {
@@ -1074,7 +1086,7 @@ impl Build {
10741086 }
10751087 }
10761088
1077- Ok ( ( ) )
1089+ Ok ( entries )
10781090 }
10791091
10801092 /// Run the compiler, generating the file `output`
@@ -1120,6 +1132,26 @@ impl Build {
11201132 }
11211133 }
11221134
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+
11231155 #[ cfg( feature = "parallel" ) ]
11241156 fn compile_objects < ' me > ( & ' me self , objs : & [ Object ] ) -> Result < ( ) , Error > {
11251157 use std:: sync:: atomic:: { AtomicBool , Ordering :: SeqCst } ;
@@ -1272,14 +1304,15 @@ impl Build {
12721304 }
12731305
12741306 #[ 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 ( ) ;
12761309 for obj in objs {
1277- self . compile_object ( obj) ?;
1310+ entries . push ( self . compile_object ( obj) ?) ;
12781311 }
1279- Ok ( ( ) )
1312+ Ok ( entries )
12801313 }
12811314
1282- fn compile_object ( & self , obj : & Object ) -> Result < ( ) , Error > {
1315+ fn compile_object ( & self , obj : & Object ) -> Result < CompileCommand , Error > {
12831316 let is_asm = obj. src . extension ( ) . and_then ( |s| s. to_str ( ) ) == Some ( "asm" ) ;
12841317 let target = self . get_target ( ) ?;
12851318 let msvc = target. contains ( "msvc" ) ;
@@ -1324,7 +1357,7 @@ impl Build {
13241357 }
13251358
13261359 run ( & mut cmd, & name) ?;
1327- Ok ( ( ) )
1360+ Ok ( CompileCommand :: new ( & cmd , obj . src . clone ( ) , obj . dst . clone ( ) ) )
13281361 }
13291362
13301363 /// 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<
32873320 }
32883321}
32893322
3290- fn which ( tool : & Path ) -> Option < PathBuf > {
3323+ pub ( crate ) fn which < P > ( tool : P ) -> Option < PathBuf > where P : AsRef < Path > {
32913324 fn check_exe ( exe : & mut PathBuf ) -> bool {
32923325 let exe_ext = std:: env:: consts:: EXE_EXTENSION ;
32933326 exe. exists ( ) || ( !exe_ext. is_empty ( ) && exe. set_extension ( exe_ext) && exe. exists ( ) )
32943327 }
32953328
32963329 // If |tool| is not just one "word," assume it's an actual path...
3330+ let tool = tool. as_ref ( ) ;
32973331 if tool. components ( ) . count ( ) > 1 {
32983332 let mut exe = PathBuf :: from ( tool) ;
32993333 return if check_exe ( & mut exe) { Some ( exe) } else { None } ;
0 commit comments