@@ -95,21 +95,42 @@ std::optional<std::uint32_t> CompilationDatabase::get_option_id(llvm::StringRef
9595 }
9696}
9797
98+ namespace {
99+
100+ llvm::SmallVector<llvm::StringRef, 4 > driver_invocation_argv (llvm::StringRef driver) {
101+ // / FIXME: MSVC command:` cl /Bv`, should we support it?
102+ // / if (driver.starts_with("gcc") || driver.starts_with("g++") || driver.starts_with("clang")) {
103+ // / return {"-E", "-v", "-xc++", "/dev/null"};
104+ // / } else if (driver.starts_with("cl") || driver.starts_with("clang-cl")) {
105+ // / return {"/Bv"};
106+ // / }
107+ return {driver, " -E" , " -v" , " -xc++" , " /dev/null" };
108+ }
109+
110+ using QueryDriverError = CompilationDatabase::QueryDriverError;
111+ using ErrorKind = CompilationDatabase::QueryDriverError::ErrorKind;
112+
113+ auto unexpected (ErrorKind kind, std::string message) {
114+ return std::unexpected<QueryDriverError>({kind, std::move (message)});
115+ };
116+
117+ } // namespace
118+
98119auto CompilationDatabase::query_driver (this Self& self, llvm::StringRef driver)
99- -> std::expected<DriverInfo, std::string > {
100- llvm::SmallString< 128 > buffer;
101-
102- // / FIXME: Should we use a better way?
103- if (auto error = fs::real_path (driver, buffer )) {
104- auto result = llvm::sys::findProgramByName (driver);
105- if (!result) {
106- return std:: unexpected (std::format ( " {} " , result.getError ()));
107- } else {
108- buffer = *result;
120+ -> std::expected<DriverInfo, QueryDriverError > {
121+ {
122+ // / FIXME: Should we use a better way?
123+ llvm::SmallString< 128 > absolute_path;
124+ if (auto error = fs::real_path (driver, absolute_path )) {
125+ auto result = llvm::sys::findProgramByName (driver);
126+ if (!result) {
127+ return unexpected (ErrorKind::NotFoundInPATH , result.getError (). message ( ));
128+ }
129+ absolute_path = *result;
109130 }
110- }
111131
112- driver = self.save_string (buffer);
132+ driver = self.save_string (absolute_path);
133+ }
113134
114135 auto it = self.driver_infos .find (driver.data ());
115136 if (it != self.driver_infos .end ()) {
@@ -120,18 +141,26 @@ auto CompilationDatabase::query_driver(this Self& self, llvm::StringRef driver)
120141
121142 llvm::SmallString<128 > output_path;
122143 if (auto error = llvm::sys::fs::createTemporaryFile (" system-includes" , " clice" , output_path)) {
123- return std:: unexpected (std::format ( " {} " , error));
144+ return unexpected (ErrorKind::FailToCreateTempFile , error. message ( ));
124145 }
125146
126- auto clean_up = llvm::make_scope_exit ([&output_path]() { fs::remove (output_path); });
147+ // If we fail to get the driver infomation, keep the output file for user to debug.
148+ bool keep_output_file = true ;
149+ auto clean_up = llvm::make_scope_exit ([&output_path, &keep_output_file]() {
150+ if (keep_output_file) {
151+ return ;
152+ }
127153
128- bool is_std_err = true ;
154+ if (auto errc = llvm::sys::fs::remove (output_path)) {
155+ log::warn (" Fail to remove temporary file: {}" , errc.message ());
156+ }
157+ });
129158
159+ bool is_std_err = true ;
130160 std::optional<llvm::StringRef> redirects[] = {{" " }, {" " }, {" " }};
131161 redirects[is_std_err ? 2 : 1 ] = output_path.str ();
132162
133- llvm::StringRef argv[] = {driver, " -E" , " -v" , " -xc++" , " /dev/null" };
134-
163+ llvm::SmallVector argv = driver_invocation_argv (driver);
135164 std::string message;
136165 if (int RC = llvm::sys::ExecuteAndWait (driver,
137166 argv,
@@ -140,12 +169,12 @@ auto CompilationDatabase::query_driver(this Self& self, llvm::StringRef driver)
140169 /* SecondsToWait=*/ 0 ,
141170 /* MemoryLimit=*/ 0 ,
142171 &message)) {
143- return std:: unexpected (std::format ( " {} " , message));
172+ return unexpected (ErrorKind::InvokeDriverFail, std::move ( message));
144173 }
145174
146175 auto file = llvm::MemoryBuffer::getFile (output_path);
147176 if (!file) {
148- return std:: unexpected (std::format ( " {} " , file.getError ()));
177+ return unexpected (ErrorKind::OutputFileNotReadable , file.getError (). message ( ));
149178 }
150179
151180 llvm::StringRef content = file.get ()->getBuffer ();
@@ -191,13 +220,16 @@ auto CompilationDatabase::query_driver(this Self& self, llvm::StringRef driver)
191220 }
192221
193222 if (!found_start_marker) {
194- return std:: unexpected (" Start marker not found..." );
223+ return unexpected (ErrorKind::InvalidOutputFormat, " Start marker not found..." );
195224 }
196225
197226 if (in_includes_block) {
198- return std:: unexpected (" End marker not found..." );
227+ return unexpected (ErrorKind::InvalidOutputFormat, " End marker not found..." );
199228 }
200229
230+ // Get driver information success, remove temporary file.
231+ keep_output_file = false ;
232+
201233 llvm::SmallVector<const char *, 8 > includes;
202234 for (auto include: system_includes) {
203235 llvm::SmallString<64 > buffer;
@@ -415,10 +447,8 @@ auto CompilationDatabase::load_commands(this Self& self, llvm::StringRef json_co
415447 return infos;
416448}
417449
418- auto CompilationDatabase::get_command (this Self& self,
419- llvm::StringRef file,
420- bool resource_dir,
421- bool query_driver) -> LookupInfo {
450+ auto CompilationDatabase::get_command (this Self& self, llvm::StringRef file, CommandOptions options)
451+ -> LookupInfo {
422452 LookupInfo info;
423453
424454 file = self.save_string (file);
@@ -439,8 +469,9 @@ auto CompilationDatabase::get_command(this Self& self,
439469 info.arguments .emplace_back (self.save_string (argument).data ());
440470 };
441471
442- if (query_driver) {
443- if (auto driver_info = self.query_driver (info.arguments [0 ])) {
472+ if (options.query_driver ) {
473+ llvm::StringRef driver = info.arguments [0 ];
474+ if (auto driver_info = self.query_driver (driver)) {
444475 append_argument (" -nostdlibinc" );
445476
446477 // / FIXME: Use target information here, this is useful for cross compilation.
@@ -450,18 +481,16 @@ auto CompilationDatabase::get_command(this Self& self,
450481 append_argument (" -I" );
451482 append_argument (system_header);
452483 }
453- } else {
454- // / FIXME: Error handle here.
455- log::warn (" Fail query info for {}, because" , info.arguments [0 ], driver_info.error ());
484+ } else if (!options.suppress_log ) {
485+ log::warn (" Failed to query driver:{}, error:{}" , driver, driver_info.error ());
456486 }
457487 }
458488
459- if (resource_dir) {
489+ if (options. resource_dir ) {
460490 append_argument (std::format (" -resource-dir={}" , fs::resource_dir));
461491 }
462492
463493 info.arguments .emplace_back (file.data ());
464-
465494 return info;
466495}
467496
0 commit comments