@@ -41,10 +41,11 @@ struct CompletedProcess {
41
41
}
42
42
};
43
43
44
- struct ResourceDirResult {
44
+ struct ToolchainPathsResult {
45
45
std::string resourceDir;
46
46
std::vector<std::string> cliInvocation;
47
47
CompilerKind compilerKind;
48
+ std::string compilerDriverPath; // non-null for Clang
48
49
};
49
50
} // namespace
50
51
@@ -78,11 +79,19 @@ static CompletedProcess runProcess(std::vector<std::string> &args,
78
79
}
79
80
80
81
// / Returns an empty path if we failed to determine the resource dir
81
- ResourceDirResult static determineResourceDir (
82
+ ToolchainPathsResult static determineToolchainPaths (
82
83
const scip_clang::AbsolutePath &compilerPath) {
83
- ResourceDirResult out{" " ,
84
- {compilerPath.asStringRef (), " -print-resource-dir" },
85
- CompilerKind::Clang};
84
+ ToolchainPathsResult out{" " ,
85
+ {compilerPath.asStringRef (), " -print-resource-dir" },
86
+ CompilerKind::Clang,
87
+ " " };
88
+
89
+ auto noteStdlib = []() {
90
+ spdlog::warn (" may be unable to locate standard library headers" );
91
+ spdlog::info (" compilation errors are suppressed by default, but can be "
92
+ " turned on using --show-compiler-diagnostics" );
93
+ };
94
+
86
95
auto printResourceDirResult =
87
96
::runProcess (out.cliInvocation, " attempting to find resource dir" );
88
97
if (printResourceDirResult.isSuccess ()) {
@@ -93,17 +102,33 @@ ResourceDirResult static determineResourceDir(
93
102
}
94
103
out.resourceDir = std::string (
95
104
absl::StripAsciiWhitespace (printResourceDirResult.stdoutLines .front ()));
105
+ out.cliInvocation = {compilerPath.asStringRef (), " -###" };
106
+ auto hashHashHashResult = ::runProcess (
107
+ out.cliInvocation , " attempting to find installed directory" );
108
+ if (hashHashHashResult.isSuccess ()) {
109
+ for (auto &line : hashHashHashResult.stderrLines ) {
110
+ auto clangDriverDir = absl::StripPrefix (line, " InstalledDir: " );
111
+ if (clangDriverDir.length () != line.length ()) {
112
+ out.compilerDriverPath = absl::StripAsciiWhitespace (clangDriverDir);
113
+ out.compilerDriverPath .push_back (
114
+ std::filesystem::path::preferred_separator);
115
+ out.compilerDriverPath .append (" clang" );
116
+ break ;
117
+ }
118
+ }
119
+ }
120
+ if (out.compilerDriverPath .empty ()) {
121
+ spdlog::warn (
122
+ " failed to determine compiler path using -### for compiler at '{}'" ,
123
+ compilerPath.asStringRef ());
124
+ noteStdlib ();
125
+ }
96
126
return out;
97
127
}
98
128
out.compilerKind = CompilerKind::Gcc;
99
129
out.cliInvocation = {compilerPath.asStringRef (), " -print-search-dirs" };
100
130
auto printSearchDirsResult =
101
131
::runProcess (out.cliInvocation, " attempting to find search dirs" );
102
- auto noteStdlib = []() {
103
- spdlog::warn (" may be unable to locate standard library headers" );
104
- spdlog::info (" compilation errors are suppressed by default, but can be "
105
- " turned on using --show-compiler-diagnostics" );
106
- };
107
132
if (!printSearchDirsResult.isSuccess ()) {
108
133
spdlog::warn (
109
134
" both -print-resource-dir and -print-search-dirs failed for {}" ,
@@ -610,73 +635,82 @@ void ResumableParser::parseMore(
610
635
611
636
void ResumableParser::tryInferResourceDir (
612
637
const std::string &directoryPath, std::vector<std::string> &commandLine) {
613
- auto &compilerPath = commandLine.front ();
614
- auto it = this ->extraArgsMap .find (compilerPath);
615
- if (it != this ->extraArgsMap .end ()) {
616
- for (auto &extraArg : it->second ) {
638
+ auto &compilerOrWrapperPath = commandLine.front ();
639
+ auto adjustCommandLine = [](auto &commandLine, auto it) {
640
+ if (!it->second .compilerDriverPath .empty ()) {
641
+ commandLine[0 ] = it->second .compilerDriverPath ;
642
+ }
643
+ for (auto &extraArg : it->second .extraArgs ) {
617
644
commandLine.push_back (extraArg);
618
645
}
646
+ };
647
+ auto it = this ->toolchainConfigMap .find (compilerOrWrapperPath);
648
+ if (it != this ->toolchainConfigMap .end ()) {
649
+ adjustCommandLine (commandLine, it);
619
650
return ;
620
651
}
621
652
AbsolutePath compilerInvocationPath;
622
- auto fail = [&]() { this ->extraArgsMap .insert ({compilerPath, {}}); };
653
+ auto fail = [&]() {
654
+ this ->toolchainConfigMap .insert (
655
+ {compilerOrWrapperPath, ToolchainConfig{" " , {}}});
656
+ };
623
657
624
- if (compilerPath .find (std::filesystem::path::preferred_separator)
658
+ if (compilerOrWrapperPath .find (std::filesystem::path::preferred_separator)
625
659
== std::string::npos) {
626
- auto absPath = boost::process::search_path (compilerPath ).native ();
660
+ auto absPath = boost::process::search_path (compilerOrWrapperPath ).native ();
627
661
if (absPath.empty ()) {
628
662
this ->emitResourceDirError (fmt::format (
629
663
" scip-clang needs to be invoke '{0}' (found via the compilation"
630
664
" database) to determine the resource directory, but couldn't find"
631
665
" '{0}' on PATH. Hint: Use a modified PATH to invoke scip-clang,"
632
666
" or change the compilation database to use absolute paths"
633
667
" for the compiler." ,
634
- compilerPath ));
668
+ compilerOrWrapperPath ));
635
669
return fail ();
636
670
}
637
671
compilerInvocationPath =
638
672
AbsolutePath (std::string (absPath.data (), absPath.size ()));
639
- } else if (llvm::sys::path::is_relative (compilerPath )) {
673
+ } else if (llvm::sys::path::is_relative (compilerOrWrapperPath )) {
640
674
if (llvm::sys::path::is_absolute (directoryPath)) {
641
675
compilerInvocationPath = AbsolutePath (fmt::format (
642
676
" {}{}{}" , directoryPath, std::filesystem::path::preferred_separator,
643
- compilerPath ));
677
+ compilerOrWrapperPath ));
644
678
} else {
645
679
spdlog::warn (
646
680
R"( "directory": "{}" key in compilation database is not an absolute path)"
647
681
" ; unable to determine resource directory for compiler: {}" ,
648
- directoryPath, compilerPath );
682
+ directoryPath, compilerOrWrapperPath );
649
683
}
650
684
} else {
651
- ENFORCE (llvm::sys::path::is_absolute (compilerPath ));
652
- compilerInvocationPath = AbsolutePath (std::string (compilerPath ));
685
+ ENFORCE (llvm::sys::path::is_absolute (compilerOrWrapperPath ));
686
+ compilerInvocationPath = AbsolutePath (std::string (compilerOrWrapperPath ));
653
687
}
654
688
if (compilerInvocationPath.asStringRef ().empty ()) {
655
689
return fail ();
656
690
}
657
- auto resourceDirResult = ::determineResourceDir (compilerInvocationPath);
658
- if (resourceDirResult .resourceDir .empty ()) {
691
+ auto toolchainPathsResult = ::determineToolchainPaths (compilerInvocationPath);
692
+ if (toolchainPathsResult .resourceDir .empty ()) {
659
693
return fail ();
660
694
}
661
- auto &resourceDir = resourceDirResult .resourceDir ;
695
+ auto &resourceDir = toolchainPathsResult .resourceDir ;
662
696
std::vector<std::string> extraArgs{" -resource-dir" , resourceDir};
663
- if (resourceDirResult .compilerKind == CompilerKind::Gcc) {
697
+ if (toolchainPathsResult .compilerKind == CompilerKind::Gcc) {
664
698
// gcc-7 adds headers like limits.h and syslimits.h in include-fixed
665
699
extraArgs.push_back (fmt::format (" -I{}/include-fixed" , resourceDir));
666
700
}
667
701
spdlog::debug (" got resource dir '{}'" , resourceDir);
668
702
if (!std::filesystem::exists (resourceDir)) {
669
703
this ->emitResourceDirError (fmt::format (
670
704
" '{}' returned '{}' but the directory does not exist" ,
671
- fmt::join (resourceDirResult .cliInvocation , " " ), resourceDir));
705
+ fmt::join (toolchainPathsResult .cliInvocation , " " ), resourceDir));
672
706
return fail ();
673
707
}
674
- auto [newIt, inserted] =
675
- this ->extraArgsMap .emplace (compilerPath, std::move (extraArgs));
708
+ auto [newIt, inserted] = this ->toolchainConfigMap .emplace (
709
+ compilerOrWrapperPath,
710
+ ToolchainConfig{toolchainPathsResult.compilerDriverPath ,
711
+ std::move (extraArgs)});
676
712
ENFORCE (inserted);
677
- for (auto &arg : newIt->second ) {
678
- commandLine.push_back (arg);
679
- }
713
+ adjustCommandLine (commandLine, newIt);
680
714
}
681
715
682
716
void ResumableParser::emitResourceDirError (std::string &&error) {
0 commit comments