From 3bb864165c3d2755393248269b286e8f9a2e84d4 Mon Sep 17 00:00:00 2001 From: Max Schwarz Date: Sat, 6 Sep 2025 00:02:37 +0200 Subject: [PATCH 1/2] core: package_registry: look in associated source directories for each ws Related to #188. --- rosmon_core/src/package_registry.cpp | 95 ++++++++++++++++++++++++---- 1 file changed, 81 insertions(+), 14 deletions(-) diff --git a/rosmon_core/src/package_registry.cpp b/rosmon_core/src/package_registry.cpp index 995a4099..2ce00e77 100644 --- a/rosmon_core/src/package_registry.cpp +++ b/rosmon_core/src/package_registry.cpp @@ -11,20 +11,73 @@ #include #include +#include + #include #include +#include + +namespace fs = boost::filesystem; + namespace rosmon { +struct CatkinWorkspace +{ + explicit CatkinWorkspace(const fs::path& path) + : path{path} + {} + + fs::path path; + + bool sourcePackagesCrawled = false; + std::map packageSourcePaths; + + void crawlSourcePackage(const fs::path& packageXMLPath) + { + TiXmlDocument document(packageXMLPath.string()); + + TiXmlBase::SetCondenseWhiteSpace(false); + + if(!document.LoadFile()) + return; + + if(document.RootElement()->ValueStr() != "package") + return; + + auto name = document.RootElement()->FirstChildElement("name"); + if(!name) + return; + + packageSourcePaths[name->GetText()] = packageXMLPath.parent_path(); + } + + void crawlSourcePackages() + { + if(sourcePackagesCrawled) + return; + + fs::path catkinPath = path / ".catkin"; + std::ifstream file{catkinPath.string()}; + + for(std::string line; std::getline(file, line);) + { + for(fs::recursive_directory_iterator it(line); it != fs::recursive_directory_iterator(); ++it) + { + if(it->path().filename() == "package.xml") + crawlSourcePackage(it->path()); + } + } + } +}; + static std::map g_cache; static rospack::Rospack g_pack; -static std::vector g_catkin_workspaces; +static std::vector g_catkin_workspaces; static std::map, std::string> g_executableCache; static bool g_initialized = false; -namespace fs = boost::filesystem; - static void init() { if(g_initialized) @@ -49,7 +102,7 @@ static void init() continue; // printf("Found catkin workspace: '%s'\n", path.string().c_str()); - g_catkin_workspaces.push_back(path.string()); + g_catkin_workspaces.emplace_back(path); } } } @@ -97,17 +150,22 @@ static std::string _getExecutable(const std::string& package, const std::string& init(); // Try catkin libexec & catkin share first - for(const auto& workspace : g_catkin_workspaces) + for(auto& workspace : g_catkin_workspaces) { - fs::path workspacePath(workspace); - - fs::path execPath = workspacePath / "lib" / package / name; + fs::path execPath = workspace.path / "lib" / package / name; if(fs::exists(execPath) && access(execPath.c_str(), X_OK) == 0) return execPath.string(); - std::string sharePath = getExecutableInPath(workspacePath / "share" / package, name); + std::string sharePath = getExecutableInPath(workspace.path / "share" / package, name); if(!sharePath.empty()) return sharePath; + + // Look in associated source directories of the workspace + workspace.crawlSourcePackages(); + + auto it = workspace.packageSourcePaths.find(package); + if(it != workspace.packageSourcePaths.end()) + return getExecutableInPath(it->second, name); } // Crawl package directory for an appropriate executable @@ -139,19 +197,28 @@ std::string PackageRegistry::findPathToFile(const std::string& package, const st init(); // Try catkin libexec & catkin share first - for(const auto& workspace : g_catkin_workspaces) + for(auto& workspace : g_catkin_workspaces) { - fs::path workspacePath(workspace); - - fs::path execPath = workspacePath / "lib" / package; + fs::path execPath = workspace.path / "lib" / package; fs::path filePath = execPath / name; if(fs::exists(filePath) && access(filePath.c_str(), X_OK) == 0) return execPath.string(); - fs::path sharePath = workspacePath / "share" / package; + fs::path sharePath = workspace.path / "share" / package; filePath = sharePath / name; if(fs::exists(filePath) && access(filePath.c_str(), X_OK) == 0) return sharePath.string(); + + // Look in associated source directories of the workspace + workspace.crawlSourcePackages(); + + auto it = workspace.packageSourcePaths.find(package); + if(it != workspace.packageSourcePaths.end()) + { + fs::path filePath = it->second / name; + if(fs::exists(filePath) && access(filePath.c_str(), X_OK) == 0) + return it->second.string(); + } } // Try package directory (src) From 351c18602fa7329b69477dba38535753bd98cf81 Mon Sep 17 00:00:00 2001 From: Max Schwarz Date: Tue, 30 Sep 2025 10:53:05 +0200 Subject: [PATCH 2/2] core: package_registry: .catkin file is delimited with semicolons --- rosmon_core/src/package_registry.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/rosmon_core/src/package_registry.cpp b/rosmon_core/src/package_registry.cpp index 2ce00e77..9a4d935b 100644 --- a/rosmon_core/src/package_registry.cpp +++ b/rosmon_core/src/package_registry.cpp @@ -61,9 +61,15 @@ struct CatkinWorkspace fs::path catkinPath = path / ".catkin"; std::ifstream file{catkinPath.string()}; - for(std::string line; std::getline(file, line);) + for(std::string path; std::getline(file, path, ';');) { - for(fs::recursive_directory_iterator it(line); it != fs::recursive_directory_iterator(); ++it) + if(!fs::exists(path)) + { + fmt::print(stderr, "Warning: source path '{}' found in '{}' does not exist.\n", path, catkinPath.string()); + continue; + } + + for(fs::recursive_directory_iterator it(path); it != fs::recursive_directory_iterator(); ++it) { if(it->path().filename() == "package.xml") crawlSourcePackage(it->path());