diff --git a/src/cmake.cc b/src/cmake.cc index 7773775..5667057 100644 --- a/src/cmake.cc +++ b/src/cmake.cc @@ -102,54 +102,27 @@ bool CMake::update_debug_build(const boost::filesystem::path &debug_build_path, } boost::filesystem::path CMake::get_executable(const boost::filesystem::path &build_path, const boost::filesystem::path &file_path) { - auto cmake_executables = get_functions_parameters("add_executable"); + // CMake does not store in compile_commands.json if an object is part of an executable or not. + // Therefore, executables are first attempted found in the cmake files. These executables + // are then used to identify if a file in compile_commands.json is part of an executable or not - 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; - }; + auto parameters = get_functions_parameters("add_executable"); - if(!file_path.empty()) { - for(auto &executable: cmake_executables) { - if(executable.second.size()>1) { - for(size_t c=1;c0 && cmake_executables[0].second[0].compare(0, 2, "${")!=0) - return cmake_fix_executable((executable.first.parent_path()/executable.second[0]).string()); - return get_executable_from_compile_commands(build_path, file_path); - } - } - } + std::vector cmake_executables; + for(auto ¶meter: parameters) { + if(parameter.second.size()>1 && parameter.second[0].size()>0 && parameter.second[0].compare(0, 2, "${")!=0) { + auto executable=(parameter.first.parent_path()/parameter.second[0]).string(); + auto project_path_str=project_path.string(); + size_t pos=executable.find(project_path_str); + if(pos!=std::string::npos) + executable.replace(pos, project_path_str.size(), build_path.string()); + cmake_executables.emplace_back(executable); } } - size_t best_match_c=-1; - size_t best_match_size=-1; - for(size_t c=0;c0) { - auto size=cmake_executables[c].first.parent_path().string().size(); - if(best_match_size==static_cast(-1) || best_match_size(-1) && - cmake_executables[best_match_c].second[0].size()>0 && - cmake_executables[best_match_c].second[0].compare(0, 2, "${")!=0) { - return cmake_fix_executable((cmake_executables[best_match_c].first.parent_path()/cmake_executables[best_match_c].second[0]).string()); - } - return get_executable_from_compile_commands(build_path, file_path); -} - -boost::filesystem::path CMake::get_executable_from_compile_commands(const boost::filesystem::path &build_path, const boost::filesystem::path &file_path) { CompileCommands compile_commands(build_path); - - size_t compile_commands_best_match_size=-1; - boost::filesystem::path compile_commands_best_match_executable; + std::vector> command_files_and_maybe_executables; for(auto &command: compile_commands.commands) { auto command_file=filesystem::get_normal_path(command.file); auto values=command.parameter_values("-o"); @@ -157,26 +130,51 @@ boost::filesystem::path CMake::get_executable_from_compile_commands(const boost: 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(-1) || compile_commands_best_match_size(std::distance(command_file_directory.begin(), command_file_directory.end())); + if(best_match_size==static_cast(-1) || best_match_size(std::distance(command_file_directory.begin(), command_file_directory.end())); + if(best_match_size==static_cast(-1) || best_match_size paths; std::vector files; std::unordered_map variables; diff --git a/src/meson.cc b/src/meson.cc index 04bb296..129dabd 100644 --- a/src/meson.cc +++ b/src/meson.cc @@ -102,7 +102,7 @@ boost::filesystem::path Meson::get_executable(const boost::filesystem::path &bui 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(); + auto size=static_cast(std::distance(command_file_directory.begin(), command_file_directory.end())); if(best_match_size==static_cast(-1) || best_match_size +#include "process.hpp" #include using namespace std; @@ -14,6 +15,9 @@ int main() { { CMake cmake(project_path); + Process process("cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..", (project_path/"build").string(), [](const char *bytes, size_t n) {}); + g_assert(process.get_exit_status()==0); + g_assert(cmake.get_executable(project_path/"build", project_path)==""); g_assert(cmake.get_executable(project_path/"build"/"non_existing_file.cc", project_path)==""); } @@ -32,9 +36,9 @@ int main() { auto functions_parameters=cmake.get_functions_parameters("project"); g_assert(functions_parameters.at(0).second.at(0)=="juci"); - g_assert(cmake.get_executable(project_path/"build", tests_path)==project_path/"build"/"tests"/"process_test"); + g_assert(cmake.get_executable(project_path/"build", tests_path).parent_path()==project_path/"build"/"tests"); 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"/"process_test"); + g_assert(cmake.get_executable(project_path/"build", tests_path/"non_existing_file.cc").parent_path()==project_path/"build"/"tests"); } auto build=Project::Build::create(tests_path); @@ -63,8 +67,8 @@ int main() { g_assert(cmake.project_path==project_path); - g_assert(cmake.get_executable(project_path/"build", project_path/"main.cpp")==project_path/"build"/"test"); - 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"); + g_assert(cmake.get_executable(project_path/"build", project_path/"main.cpp")==boost::filesystem::path(".")/"test"); + g_assert(cmake.get_executable(project_path/"build", project_path/"non_existing_file.cpp")==boost::filesystem::path(".")/"test"); + g_assert(cmake.get_executable(project_path/"build", project_path)==boost::filesystem::path(".")/"test"); } } diff --git a/tests/compile_commands_test.cc b/tests/compile_commands_test.cc index 5601c03..ca72f38 100644 --- a/tests/compile_commands_test.cc +++ b/tests/compile_commands_test.cc @@ -27,7 +27,7 @@ int main() { { CompileCommands compile_commands(tests_path/"source_clang_test_files"/"build"); - g_assert(compile_commands.commands.at(0).directory=="build"); + g_assert(compile_commands.commands.at(0).directory=="."); g_assert_cmpuint(compile_commands.commands.size(), ==, 1); diff --git a/tests/source_clang_test_files/build/compile_commands.json b/tests/source_clang_test_files/build/compile_commands.json index 21f0088..829dcc1 100644 --- a/tests/source_clang_test_files/build/compile_commands.json +++ b/tests/source_clang_test_files/build/compile_commands.json @@ -1,6 +1,6 @@ [ { - "directory": "build", + "directory": ".", "command": "c++ -std=c++1y -Wall -Wextra -Wno-unused-parameter -o CMakeFiles/test.dir/main.cpp.o main.cpp", "file": "../main.cpp" }