|
|
|
@ -3,6 +3,7 @@ |
|
|
|
#include "config.hpp" |
|
|
|
#include "config.hpp" |
|
|
|
#include "dialog.hpp" |
|
|
|
#include "dialog.hpp" |
|
|
|
#include "filesystem.hpp" |
|
|
|
#include "filesystem.hpp" |
|
|
|
|
|
|
|
#include "json.hpp" |
|
|
|
#include "terminal.hpp" |
|
|
|
#include "terminal.hpp" |
|
|
|
#include "utility.hpp" |
|
|
|
#include "utility.hpp" |
|
|
|
#include <boost/algorithm/string.hpp> |
|
|
|
#include <boost/algorithm/string.hpp> |
|
|
|
@ -60,6 +61,8 @@ bool CMake::update_default_build(const boost::filesystem::path &default_build_pa |
|
|
|
if(!force && boost::filesystem::exists(default_build_path / "compile_commands.json", ec)) |
|
|
|
if(!force && boost::filesystem::exists(default_build_path / "compile_commands.json", ec)) |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
set_file_api_queries(default_build_path); |
|
|
|
|
|
|
|
|
|
|
|
auto compile_commands_path = default_build_path / "compile_commands.json"; |
|
|
|
auto compile_commands_path = default_build_path / "compile_commands.json"; |
|
|
|
bool canceled = false; |
|
|
|
bool canceled = false; |
|
|
|
Dialog::Message message("Creating/updating default build", [&canceled] { |
|
|
|
Dialog::Message message("Creating/updating default build", [&canceled] { |
|
|
|
@ -121,6 +124,8 @@ bool CMake::update_debug_build(const boost::filesystem::path &debug_build_path, |
|
|
|
if(!force && boost::filesystem::exists(debug_build_path / "CMakeCache.txt", ec)) |
|
|
|
if(!force && boost::filesystem::exists(debug_build_path / "CMakeCache.txt", ec)) |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
set_file_api_queries(debug_build_path); |
|
|
|
|
|
|
|
|
|
|
|
bool canceled = false; |
|
|
|
bool canceled = false; |
|
|
|
Dialog::Message message("Creating/updating debug build", [&canceled] { |
|
|
|
Dialog::Message message("Creating/updating debug build", [&canceled] { |
|
|
|
canceled = true; |
|
|
|
canceled = true; |
|
|
|
@ -146,6 +151,13 @@ 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) { |
|
|
|
boost::filesystem::path CMake::get_executable(const boost::filesystem::path &build_path, const boost::filesystem::path &file_path) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// prefer the CMake file API (if available) which gives exact information about the targets a file belongs to
|
|
|
|
|
|
|
|
auto executables = get_executables(build_path, file_path); |
|
|
|
|
|
|
|
if(!executables.empty()) { |
|
|
|
|
|
|
|
return executables.front(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// CMake does not store in compile_commands.json if an object is part of an executable or not.
|
|
|
|
// 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
|
|
|
|
// 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
|
|
|
|
// are then used to identify if a file in compile_commands.json is part of an executable or not
|
|
|
|
@ -350,3 +362,68 @@ void CMake::parse_file(const std::string &src, std::map<std::string, std::list<s |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CMake::set_file_api_queries(const boost::filesystem::path &build_path) { |
|
|
|
|
|
|
|
auto query_directory = build_path / ".cmake" / "api" / "v1" / "query" / "client-jucipp"; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
boost::system::error_code ec; |
|
|
|
|
|
|
|
if(!boost::filesystem::exists(query_directory, ec)) { |
|
|
|
|
|
|
|
boost::system::error_code ec; |
|
|
|
|
|
|
|
boost::filesystem::create_directories(query_directory, ec); |
|
|
|
|
|
|
|
if(ec) { |
|
|
|
|
|
|
|
Terminal::get().print("\e[31mError\e[m: could not create " + filesystem::get_short_path(query_directory).string() + ": " + ec.message() + "\n", true); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
filesystem::write(query_directory / "query.json", R"({ |
|
|
|
|
|
|
|
"requests": [ |
|
|
|
|
|
|
|
{ "kind": "codemodel" , "version": 2 } |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
})"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<boost::filesystem::path> CMake::get_executables(const boost::filesystem::path &build_path, const boost::filesystem::path &file_path) { |
|
|
|
|
|
|
|
auto reply_directory = build_path / ".cmake" / "api" / "v1" / "reply"; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
boost::system::error_code ec; |
|
|
|
|
|
|
|
if(!boost::filesystem::exists(reply_directory, ec)) { |
|
|
|
|
|
|
|
// If the reply directory does not exist, either CMake was not run or the file API is not yet supported
|
|
|
|
|
|
|
|
return {}; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// check all target-*.json files and filter for the given file path
|
|
|
|
|
|
|
|
std::vector<boost::filesystem::path> executables; |
|
|
|
|
|
|
|
for(const auto &reply_file : boost::filesystem::directory_iterator(reply_directory)) { |
|
|
|
|
|
|
|
if(reply_file.path().stem().string().find("target-") != 0) { |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
JSON json{reply_file.path()}; |
|
|
|
|
|
|
|
auto artifacts = json.array_optional("artifacts"); |
|
|
|
|
|
|
|
if(!artifacts || artifacts->empty()) { |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto relative_path = artifacts->front().string_optional("path"); |
|
|
|
|
|
|
|
if(!relative_path) { |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto type = json.string_optional("type"); |
|
|
|
|
|
|
|
if(!type || *type != "EXECUTABLE") { |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto sources = json.array_optional("sources"); |
|
|
|
|
|
|
|
if(!sources) { |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
for(const auto &source : *sources) { |
|
|
|
|
|
|
|
auto source_path = project_path / source.string_or("path", ""); |
|
|
|
|
|
|
|
if(source_path == file_path) { |
|
|
|
|
|
|
|
executables.emplace_back(build_path / *relative_path); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return executables; |
|
|
|
|
|
|
|
} |
|
|
|
|