Browse Source

Improved CMake::get_executable, now also looks in compile_commands.json if no executable was found previously.

merge-requests/365/head
eidheim 9 years ago
parent
commit
7ec8f03039
  1. 65
      src/cmake.cc
  2. 2
      src/cmake.h
  3. 6
      src/project_build.cc
  4. 71
      tests/cmake_build_test.cc
  5. 4
      tests/source_clang_test_files/build/compile_commands.json

65
src/cmake.cc

@ -4,6 +4,7 @@
#include "config.h" #include "config.h"
#include "terminal.h" #include "terminal.h"
#include <regex> #include <regex>
#include "compile_commands.h"
CMake::CMake(const boost::filesystem::path &path) { CMake::CMake(const boost::filesystem::path &path) {
const auto find_cmake_project=[this](const boost::filesystem::path &cmake_path) { const auto find_cmake_project=[this](const boost::filesystem::path &cmake_path) {
@ -110,29 +111,67 @@ bool CMake::update_debug_build(const boost::filesystem::path &debug_build_path,
return false; return false;
} }
boost::filesystem::path CMake::get_executable(const boost::filesystem::path &file_path) { boost::filesystem::path CMake::get_executable(const boost::filesystem::path &build_path, const boost::filesystem::path &file_path) {
auto executables = get_functions_parameters("add_executable"); auto cmake_executables = get_functions_parameters("add_executable");
//Attempt to find executable based add_executable files and opened tab //Attempt to find executable based on add_executable in cmake files
boost::filesystem::path executable_path; auto cmake_fix_executable=[this, &build_path](std::string executable) {
size_t pos=executable.find(project_path.string());
if(pos!=std::string::npos)
executable.replace(pos, project_path.string().size(), build_path.string());
return executable;
};
if(!file_path.empty()) { if(!file_path.empty()) {
for(auto &executable: executables) { for(auto &executable: cmake_executables) {
if(executable.second.size()>1) { if(executable.second.size()>1) {
for(size_t c=1;c<executable.second.size();c++) { for(size_t c=1;c<executable.second.size();c++) {
if(executable.second[c]==file_path.filename()) { if(executable.second[c]==file_path.filename() &&
executable_path=executable.first.parent_path()/executable.second[0]; executable.second[0].size()>0 && cmake_executables[0].second[0].substr(0, 2)!="${") {
break; return cmake_fix_executable((executable.first.parent_path()/executable.second[0]).string());
}
}
}
}
}
if(cmake_executables.size()>0 && cmake_executables[0].second.size()>0 && cmake_executables[0].second[0].size()>0 &&
cmake_executables[0].second[0].substr(0, 2)!="${") {
return cmake_fix_executable((cmake_executables[0].first.parent_path()/cmake_executables[0].second[0]).string());
}
//Attempt to find executable based on compile_commands.json
CompileCommands compile_commands(build_path);
size_t compile_commands_best_match_size=-1;
boost::filesystem::path compile_commands_best_match_executable;
for(auto &command: compile_commands.commands) {
boost::system::error_code ec;
auto command_file=boost::filesystem::canonical(command.file, ec);
if(!ec) {
auto values=command.paramter_values("-o");
if(!values.empty()) {
size_t pos;
values[0].erase(0, 11);
if((pos=values[0].find(".dir"))!=std::string::npos) {
boost::filesystem::path executable=values[0].substr(0, pos);
auto relative_path=filesystem::get_relative_path(command_file, project_path);
if(!relative_path.empty()) {
executable=build_path/relative_path.parent_path()/executable;
if(command_file==file_path)
return executable;
auto command_file_directory=command_file.parent_path();
if(filesystem::file_in_path(file_path, command_file_directory)) {
auto size=command_file_directory.string().size();
if(compile_commands_best_match_size==static_cast<size_t>(-1) || compile_commands_best_match_size<size) {
compile_commands_best_match_size=size;
compile_commands_best_match_executable=executable;
}
}
} }
} }
} }
if(!executable_path.empty())
break;
} }
} }
if(executable_path.empty() && executables.size()>0 && executables[0].second.size()>0)
executable_path=executables[0].first.parent_path()/executables[0].second[0];
return executable_path; return compile_commands_best_match_executable;
} }
void CMake::read_files() { void CMake::read_files() {

2
src/cmake.h

@ -13,7 +13,7 @@ public:
bool update_default_build(const boost::filesystem::path &default_build_path, bool force=false); bool update_default_build(const boost::filesystem::path &default_build_path, bool force=false);
bool update_debug_build(const boost::filesystem::path &debug_build_path, bool force=false); bool update_debug_build(const boost::filesystem::path &debug_build_path, bool force=false);
boost::filesystem::path get_executable(const boost::filesystem::path &file_path); boost::filesystem::path get_executable(const boost::filesystem::path &build_path, const boost::filesystem::path &file_path);
private: private:
std::vector<boost::filesystem::path> paths; std::vector<boost::filesystem::path> paths;
std::vector<std::string> files; std::vector<std::string> files;

6
src/project_build.cc

@ -97,11 +97,7 @@ bool Project::CMakeBuild::update_debug(bool force) {
} }
boost::filesystem::path Project::CMakeBuild::get_executable(const boost::filesystem::path &path) { boost::filesystem::path Project::CMakeBuild::get_executable(const boost::filesystem::path &path) {
auto executable=cmake.get_executable(path).string(); return cmake.get_executable(get_default_path(), path).string();
size_t pos=executable.find(project_path.string());
if(pos!=std::string::npos)
executable.replace(pos, project_path.string().size(), get_default_path().string());
return executable;
} }
Project::MesonBuild::MesonBuild(const boost::filesystem::path &path) : Project::Build(), meson(path) { Project::MesonBuild::MesonBuild(const boost::filesystem::path &path) : Project::Build(), meson(path) {

71
tests/cmake_build_test.cc

@ -4,36 +4,67 @@
#include "config.h" #include "config.h"
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <iostream>
using namespace std;
int main() { int main() {
auto tests_path=boost::filesystem::canonical(JUCI_TESTS_PATH); auto tests_path=boost::filesystem::canonical(JUCI_TESTS_PATH);
auto project_path=boost::filesystem::canonical(tests_path/".."); {
auto project_path=boost::filesystem::canonical(tests_path/"..");
{
CMake cmake(project_path);
g_assert(cmake.get_executable(project_path/"build", project_path)=="");
g_assert(cmake.get_executable(project_path/"build"/"non_existing_file.cc", project_path)=="");
}
{
CMake cmake(project_path/"src");
g_assert(cmake.get_executable(project_path/"build", project_path/"src")==project_path/"build"/"src"/"juci");
g_assert(cmake.get_executable(project_path/"build", project_path/"src"/"cmake.cc")==project_path/"build"/"src"/"juci");
g_assert(cmake.get_executable(project_path/"build", project_path/"src"/"juci.cc")==project_path/"build"/"src"/"juci");
g_assert(cmake.get_executable(project_path/"build", project_path/"src"/"non_existing_file.cc")==project_path/"build"/"src"/"juci");
}
{
CMake cmake(tests_path);
g_assert(cmake.project_path==project_path);
CMake cmake(tests_path); auto functions_parameters=cmake.get_functions_parameters("project");
g_assert(functions_parameters.at(0).second.at(0)=="juci");
g_assert(cmake.project_path==project_path); g_assert(cmake.get_executable(project_path/"build", tests_path)==project_path/"build"/"tests"/"git_test");
g_assert(cmake.get_executable(project_path/"build", tests_path/"cmake_build_test.cc")==project_path/"build"/"tests"/"cmake_build_test");
g_assert(cmake.get_executable(project_path/"build", tests_path/"non_existing_file.cc")==project_path/"build"/"tests"/"git_test");
}
auto functions_parameters=cmake.get_functions_parameters("project"); auto build=Project::Build::create(tests_path);
g_assert(functions_parameters.at(0).second.at(0)=="juci"); g_assert(dynamic_cast<Project::CMakeBuild*>(build.get()));
g_assert(cmake.get_executable(tests_path/"cmake_build_test.cc").filename()=="cmake_build_test"); build=Project::Build::create(tests_path/"stubs");
g_assert(dynamic_cast<Project::CMakeBuild*>(build.get()));
g_assert(build->project_path==project_path);
auto build=Project::Build::create(tests_path); Config::get().project.default_build_path="./build";
g_assert(dynamic_cast<Project::CMakeBuild*>(build.get())); g_assert(build->get_default_path()==project_path/"./build");
build=Project::Build::create(tests_path/"stubs"); Config::get().project.debug_build_path="<default_build_path>/debug";
g_assert(dynamic_cast<Project::CMakeBuild*>(build.get())); g_assert(build->get_debug_path()==project_path/"./build/debug");
g_assert(build->project_path==project_path);
Config::get().project.default_build_path="./build"; auto project_path_filename=project_path.filename();
g_assert(build->get_default_path()==project_path/"./build"); Config::get().project.debug_build_path="../debug_<project_directory_name>";
g_assert(build->get_debug_path()==project_path/("../debug_"+project_path_filename.string()));
Config::get().project.debug_build_path="<default_build_path>/debug"; Config::get().project.default_build_path="../build_<project_directory_name>";
g_assert(build->get_debug_path()==project_path/"./build/debug"); g_assert(build->get_default_path()==project_path/("../build_"+project_path_filename.string()));
}
{
auto project_path=tests_path/"source_clang_test_files";
CMake cmake(project_path);
auto project_path_filename=project_path.filename(); g_assert(cmake.project_path==project_path);
Config::get().project.debug_build_path="../debug_<project_directory_name>";
g_assert(build->get_debug_path()==project_path/("../debug_"+project_path_filename.string()));
Config::get().project.default_build_path="../build_<project_directory_name>"; g_assert(cmake.get_executable(project_path/"build", project_path/"main.cpp")==project_path/"build"/"test");
g_assert(build->get_default_path()==project_path/("../build_"+project_path_filename.string())); g_assert(cmake.get_executable(project_path/"build", project_path/"non_existing_file.cpp")==project_path/"build"/"test");
g_assert(cmake.get_executable(project_path/"build", project_path)==project_path/"build"/"test");
}
} }

4
tests/source_clang_test_files/build/compile_commands.json

@ -1,7 +1,7 @@
[ [
{ {
"directory": "build", "directory": "build",
"command": "c++ -std=c++1y -Wall -Wextra -Wno-unused-parameter main.cpp", "command": "c++ -std=c++1y -Wall -Wextra -Wno-unused-parameter -o CMakeFiles/test.dir/main.cpp.o main.cpp",
"file": "main.cpp" "file": "../main.cpp"
} }
] ]
Loading…
Cancel
Save