diff --git a/src/project.cpp b/src/project.cpp index b4c698f..588f4cd 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -362,8 +362,12 @@ void Project::LLDB::debug_start() { auto view = Notebook::get().get_current_view(); *run_arguments = build->get_executable(view ? view->file_path : Directories::get().path).string(); if(run_arguments->empty()) { - Terminal::get().print("Warning: could not find executable.\n"); - Terminal::get().print("Solution: either use Debug Set Run Arguments, or open a source file within a directory where an executable is defined.\n", true); + if(build->is_valid()) { + Terminal::get().print("Warning: could not find executable.\n"); + Terminal::get().print("Solution: either use Project Set Run Arguments, or open a source file within a directory where an executable is defined.\n"); + } + else + Terminal::get().print("Error: build folder no longer valid, please rebuild project.\n", true); return; } size_t pos = run_arguments->find(default_build_path.string()); @@ -870,8 +874,12 @@ void Project::Clang::compile_and_run() { auto view = Notebook::get().get_current_view(); auto executable = build->get_executable(view ? view->file_path : Directories::get().path); if(executable.empty()) { - Terminal::get().print("Warning: could not find executable.\n"); - Terminal::get().print("Solution: either use Project Set Run Arguments, or open a source file within a directory where an executable is defined.\n", true); + if(build->is_valid()) { + Terminal::get().print("Warning: could not find executable.\n"); + Terminal::get().print("Solution: either use Project Set Run Arguments, or open a source file within a directory where an executable is defined.\n"); + } + else + Terminal::get().print("Error: build folder no longer valid, please rebuild project.\n", true); return; } arguments = filesystem::escape_argument(filesystem::get_short_path(executable).string()); diff --git a/src/project_build.cpp b/src/project_build.cpp index eb20764..09fba20 100644 --- a/src/project_build.cpp +++ b/src/project_build.cpp @@ -2,6 +2,8 @@ #include "config.hpp" #include "filesystem.hpp" #include +#include +#include std::unique_ptr Project::Build::create(const boost::filesystem::path &path) { if(path.empty()) @@ -125,6 +127,25 @@ boost::filesystem::path Project::CMakeBuild::get_executable(const boost::filesys return executable; } +bool Project::CMakeBuild::is_valid() { + if(project_path.empty()) + return true; + auto default_path = get_default_path(); + if(default_path.empty()) + return true; + std::ifstream input((default_path / "CMakeCache.txt").string(), std::ofstream::binary); + if(!input) + return true; + std::string line; + while(std::getline(input, line)) { + const static std::regex regex("^.*_SOURCE_DIR:STATIC=(.*)$", std::regex::optimize); + std::smatch sm; + if(std::regex_match(line, sm, regex)) + return boost::filesystem::path(sm[1].str()) == project_path; + } + return true; +} + std::vector Project::CMakeBuild::get_exclude_paths() { auto exclude_paths = Project::Build::get_exclude_paths(); exclude_paths.emplace_back(get_default_path()); @@ -160,6 +181,22 @@ boost::filesystem::path Project::MesonBuild::get_executable(const boost::filesys return executable; } +bool Project::MesonBuild::is_valid() { + if(project_path.empty()) + return true; + auto default_path = get_default_path(); + if(default_path.empty()) + return true; + boost::property_tree::ptree pt; + try { + boost::property_tree::json_parser::read_json((default_path / "meson-info" / "meson-info.json").string(), pt); + return boost::filesystem::path(pt.get("directories.source")) == project_path; + } + catch(...) { + } + return true; +} + std::vector Project::MesonBuild::get_exclude_paths() { auto exclude_paths = Project::Build::get_exclude_paths(); exclude_paths.emplace_back(get_default_path()); diff --git a/src/project_build.hpp b/src/project_build.hpp index 3fccb10..16bfb2a 100644 --- a/src/project_build.hpp +++ b/src/project_build.hpp @@ -18,6 +18,9 @@ namespace Project { virtual std::string get_compile_command() { return std::string(); } virtual boost::filesystem::path get_executable(const boost::filesystem::path &path) { return boost::filesystem::path(); } + /// Returns true if the project path reported by build system is correct + virtual bool is_valid() { return true; } + virtual std::vector get_exclude_paths(); static std::unique_ptr create(const boost::filesystem::path &path); @@ -35,6 +38,8 @@ namespace Project { std::string get_compile_command() override; boost::filesystem::path get_executable(const boost::filesystem::path &path) override; + bool is_valid() override; + std::vector get_exclude_paths() override; }; @@ -50,6 +55,8 @@ namespace Project { std::string get_compile_command() override; boost::filesystem::path get_executable(const boost::filesystem::path &path) override; + bool is_valid() override; + std::vector get_exclude_paths() override; };