Browse Source

Fixes #423: now uses clang++ to find system include paths

pipelines/143601543
eidheim 6 years ago
parent
commit
672108f120
  1. 65
      src/compile_commands.cc
  2. 11
      src/compile_commands.h
  3. 8
      tests/compile_commands_test.cc

65
src/compile_commands.cc

@ -1,9 +1,35 @@
#include "compile_commands.h" #include "compile_commands.h"
#include "clangmm.h" #include "clangmm.h"
#include "terminal.h"
#include <algorithm> #include <algorithm>
#include <boost/property_tree/json_parser.hpp> #include <boost/property_tree/json_parser.hpp>
#include <regex> #include <regex>
CompileCommands::FindSystemIncludePaths::FindSystemIncludePaths() {
std::stringstream stdin_stream, stdout_stream;
stdin_stream << "int main() {}";
exit_status = Terminal::get().process(stdin_stream, stdout_stream, "clang++ -v -x c++ -E 2>&1 -");
if(exit_status != 0)
return;
std::string line;
while(std::getline(stdout_stream, line)) {
if(line == "#include <...> search starts here:") {
while(std::getline(stdout_stream, line)) {
if(!line.empty() && line[0] == ' ') {
auto end = line.find(" (framework directory)", 1);
if(end == std::string::npos)
include_paths.emplace_back(line.substr(1, end));
else
framework_paths.emplace_back(line.substr(1, end));
}
else
return;
}
return;
}
}
}
std::vector<std::string> CompileCommands::Command::parameter_values(const std::string &parameter_name) const { std::vector<std::string> CompileCommands::Command::parameter_values(const std::string &parameter_name) const {
std::vector<std::string> parameter_values; std::vector<std::string> parameter_values;
@ -135,25 +161,34 @@ std::vector<std::string> CompileCommands::get_arguments(const boost::filesystem:
else else
arguments.emplace_back(default_std_argument); arguments.emplace_back(default_std_argument);
auto clang_version_string = clangmm::to_string(clang_getClangVersion()); static FindSystemIncludePaths system_include_paths;
const static std::regex clang_version_regex(R"(^[A-Za-z ]+([0-9.]+).*$)"); if(system_include_paths) {
std::smatch sm; for(auto &path : system_include_paths.include_paths)
if(std::regex_match(clang_version_string, sm, clang_version_regex)) { arguments.emplace_back("-I" + path);
auto clang_version = sm[1].str(); for(auto &path : system_include_paths.framework_paths)
arguments.emplace_back("-I/usr/lib/clang/" + clang_version + "/include"); arguments.emplace_back("-F" + path);
arguments.emplace_back("-I/usr/lib64/clang/" + clang_version + "/include"); // For Fedora }
else {
auto clang_version_string = clangmm::to_string(clang_getClangVersion());
const static std::regex clang_version_regex(R"(^[A-Za-z ]+([0-9.]+).*$)");
std::smatch sm;
if(std::regex_match(clang_version_string, sm, clang_version_regex)) {
auto clang_version = sm[1].str();
arguments.emplace_back("-I/usr/lib/clang/" + clang_version + "/include");
arguments.emplace_back("-I/usr/lib64/clang/" + clang_version + "/include"); // For Fedora
#if defined(__APPLE__) #if defined(__APPLE__)
// Missing include and framework folders for MacOS: // Missing include and framework folders for MacOS:
arguments.emplace_back("-I/usr/local/opt/llvm/include/c++/v1"); arguments.emplace_back("-I/usr/local/opt/llvm/include/c++/v1");
arguments.emplace_back("-I/usr/local/opt/llvm/lib/clang/" + clang_version + "/include"); arguments.emplace_back("-I/usr/local/opt/llvm/lib/clang/" + clang_version + "/include");
arguments.emplace_back("-I/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include"); arguments.emplace_back("-I/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include");
arguments.emplace_back("-F/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks"); arguments.emplace_back("-F/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks");
#endif #endif
#ifdef _WIN32 #ifdef _WIN32
auto env_msystem_prefix = std::getenv("MSYSTEM_PREFIX"); auto env_msystem_prefix = std::getenv("MSYSTEM_PREFIX");
if(env_msystem_prefix != nullptr) if(env_msystem_prefix != nullptr)
arguments.emplace_back("-I" + (boost::filesystem::path(env_msystem_prefix) / "lib/clang" / clang_version / "include").string()); arguments.emplace_back("-I" + (boost::filesystem::path(env_msystem_prefix) / "lib/clang" / clang_version / "include").string());
#endif #endif
}
} }
// Do not add -fretain-comments-from-system-headers if pch is used, since the pch was most likely made without this flag // Do not add -fretain-comments-from-system-headers if pch is used, since the pch was most likely made without this flag

11
src/compile_commands.h

@ -5,6 +5,17 @@
class CompileCommands { class CompileCommands {
public: public:
class FindSystemIncludePaths {
int exit_status;
public:
std::vector<std::string> include_paths;
std::vector<std::string> framework_paths;
operator bool() const { return exit_status == 0; }
FindSystemIncludePaths();
};
class Command { class Command {
public: public:
boost::filesystem::path directory; boost::filesystem::path directory;

8
tests/compile_commands_test.cc

@ -1,9 +1,17 @@
#include "compile_commands.h" #include "compile_commands.h"
#include <glib.h> #include <glib.h>
#include <gtkmm.h>
int main() { int main() {
auto app = Gtk::Application::create();
auto tests_path = boost::filesystem::canonical(JUCI_TESTS_PATH); auto tests_path = boost::filesystem::canonical(JUCI_TESTS_PATH);
{
CompileCommands::FindSystemIncludePaths system_include_paths;
g_assert(system_include_paths);
g_assert(!system_include_paths.include_paths.empty());
}
{ {
CompileCommands compile_commands(tests_path / "meson_test_files" / "build"); CompileCommands compile_commands(tests_path / "meson_test_files" / "build");

Loading…
Cancel
Save