From 3a5222b2ecb6b33c4357a0bd63034740c24c7e1e Mon Sep 17 00:00:00 2001 From: Rainer Kartmann <rainer.kartmann@kit.edu> Date: Tue, 7 Nov 2023 13:21:18 +0100 Subject: [PATCH] Handle ARON includes to packages with namespace --- .../codegeneration/typereader/xml/Reader.cpp | 87 ++++++++++++++++--- 1 file changed, 76 insertions(+), 11 deletions(-) diff --git a/source/RobotAPI/libraries/aron/codegeneration/typereader/xml/Reader.cpp b/source/RobotAPI/libraries/aron/codegeneration/typereader/xml/Reader.cpp index 10aeca408..1955a7658 100644 --- a/source/RobotAPI/libraries/aron/codegeneration/typereader/xml/Reader.cpp +++ b/source/RobotAPI/libraries/aron/codegeneration/typereader/xml/Reader.cpp @@ -42,12 +42,13 @@ namespace armarx::aron::typereader::xml { /// Resolve a relative package path std::optional<fs::path> - resolveRelativePackagePath(const fs::path& path, const std::vector<fs::path>& includePaths) + resolveRelativePackagePath(const fs::path& filepath, + const std::vector<fs::path>& includePaths) { // new behavior: using provided include paths for (const auto& includePath : includePaths) { - fs::path absPath = includePath / path; + fs::path absPath = includePath / filepath; if (fs::is_regular_file(absPath)) { // path is valid @@ -56,20 +57,80 @@ namespace armarx::aron::typereader::xml } // legacy behavior: using cmake package finder paths - const std::string package = *path.begin(); - armarx::CMakePackageFinder finder(package); - if (finder.packageFound()) + + std::vector<std::string> packageNameCandidates; + { + auto it = filepath.begin(); + + std::string packageName = *it; + packageNameCandidates.push_back(packageName); + + ++it; + if (it != filepath.end()) + { + packageName += "_" + it->string(); + packageNameCandidates.push_back(packageName); + } + } + + std::vector<armarx::CMakePackageFinder> finders; + size_t foundFinderIndex = 0; + size_t numberOfFoundCandidates = 0; + for (const std::string& packageName : packageNameCandidates) { - for (const std::string& includePath : finder.getIncludePathList()) + armarx::CMakePackageFinder& finder = finders.emplace_back(packageName); + if (finder.packageFound()) { - fs::path absPath = includePath / path; - if (fs::is_regular_file(absPath)) + // TODO: In theory, we could also consider whether the requested file exists in + // the found package (see check below). + numberOfFoundCandidates++; + foundFinderIndex = finders.size() - 1; + } + } + + if (numberOfFoundCandidates == 0) + { + std::stringstream msg; + msg << "No package matching the ARON include " << filepath + << " found. Tried CMake project names:"; + for (const std::string& packageName : packageNameCandidates) + { + msg << " '" << packageName << "',"; + } + throw error::AronException(__PRETTY_FUNCTION__, msg.str()); + } + if (numberOfFoundCandidates > 1) + { + std::stringstream msg; + msg << "The ARON include " << filepath << " is ambiguous: The following " + << numberOfFoundCandidates + << " CMake projects matching the include were found:"; + ARMARX_CHECK_EQUAL(packageNameCandidates.size(), finders.size()); + for (size_t i = 0; i < packageNameCandidates.size(); ++i) + { + if (finders[i].packageFound()) { - // path is valid - return absPath; + msg << "\n- project '" << packageNameCandidates[i] << "' at '" + << finders[i].getPackageDir() << "'"; } } - return std::nullopt; + throw error::AronException(__PRETTY_FUNCTION__, msg.str()); + } + + ARMARX_CHECK_EQUAL(numberOfFoundCandidates, 1); + ARMARX_CHECK_LESS(foundFinderIndex, finders.size()); + + CMakePackageFinder& finder = finders.at(foundFinderIndex); + ARMARX_CHECK(finder.packageFound()); + + for (const std::string& includePath : finder.getIncludePathList()) + { + fs::path absPath = includePath / filepath; + if (fs::is_regular_file(absPath)) + { + // path is valid + return absPath; + } } return std::nullopt; @@ -138,7 +199,9 @@ namespace armarx::aron::typereader::xml { auto i = readCodeInclude(include, filePath.parent_path(), includePaths); if (not i.empty()) + { this->systemIncludes.push_back(i); + } } } @@ -149,7 +212,9 @@ namespace armarx::aron::typereader::xml { auto i = readAronInclude(include, filePath.parent_path(), includePaths); if (not i.empty()) + { this->aronIncludes.push_back(i); + } } } -- GitLab