diff --git a/source/RobotAPI/applications/AronCodeGenerator/main.cpp b/source/RobotAPI/applications/AronCodeGenerator/main.cpp index 5da09c7a9a41abf9fca00adff864567125983938..dbe232179fa40b7b8c24a8957730ca1a7113995d 100644 --- a/source/RobotAPI/applications/AronCodeGenerator/main.cpp +++ b/source/RobotAPI/applications/AronCodeGenerator/main.cpp @@ -63,7 +63,8 @@ int main(int argc, char* argv[]) options.add_options("IO") ("i,input", "XML file name", cxxopts::value<std::string>()->default_value(input_default)) - ("o,output", "The output path", cxxopts::value<std::string>()->default_value(output_default)); + ("o,output", "The output path", cxxopts::value<std::string>()->default_value(output_default)) + ("I,include", "include path", cxxopts::value<std::vector<std::string>>()); options.add_options("Generation") ("f,force", "Enforce the generation", cxxopts::value<bool>()->default_value("false")); @@ -108,6 +109,17 @@ int main(int argc, char* argv[]) std::filesystem::path input_file(filename); std::filesystem::path output_folder(output); + std::vector<std::filesystem::path> includePaths; + + if(result.count("I") > 0) + { + for(const auto& path: result["I"].as<std::vector<std::string>>()) + { + includePaths.emplace_back(path); + } + } + + if (!std::filesystem::exists(input_file) || !std::filesystem::is_regular_file(input_file)) { std::cerr << "The input file does not exist or is not a regular file." << std::endl; @@ -132,7 +144,7 @@ int main(int argc, char* argv[]) } typereader::xml::Reader reader; - reader.parseFile(input_file); + reader.parseFile(input_file, includePaths); if (verbose) { std::cout << "Parsing the XML file... done!" << std::endl; diff --git a/source/RobotAPI/libraries/aron/core/typereader/Reader.h b/source/RobotAPI/libraries/aron/core/typereader/Reader.h index c5e7b72347c0fe22541649c61305c3aff0962eed..d09c5967d34b70ee0d68ef7c72d233ca30c187e9 100644 --- a/source/RobotAPI/libraries/aron/core/typereader/Reader.h +++ b/source/RobotAPI/libraries/aron/core/typereader/Reader.h @@ -47,10 +47,10 @@ namespace armarx::aron::typereader Reader() = default; /// parse a filename - virtual void parseFile(const std::string& filename) = 0; + virtual void parseFile(const std::string& filename, const std::vector<std::filesystem::path>& includePaths) = 0; /// path a file given by std::filesystem - virtual void parseFile(const std::filesystem::path& file) = 0; + virtual void parseFile(const std::filesystem::path& file, const std::vector<std::filesystem::path>& includePaths) = 0; std::vector<std::string> getCodeIncludes() const { diff --git a/source/RobotAPI/libraries/aron/core/typereader/xml/Reader.cpp b/source/RobotAPI/libraries/aron/core/typereader/xml/Reader.cpp index c12e495c0c64693ab78e6af7ae7b84561b25d83e..a150fa341e4b427476e2ee17389bdade64c138dc 100644 --- a/source/RobotAPI/libraries/aron/core/typereader/xml/Reader.cpp +++ b/source/RobotAPI/libraries/aron/core/typereader/xml/Reader.cpp @@ -26,6 +26,7 @@ // Header #include "Reader.h" +#include <sstream> // ArmarX #include <ArmarXCore/core/rapidxml/wrapper/RapidXmlReader.h> @@ -42,8 +43,20 @@ namespace armarx::aron::typereader::xml namespace { /// Resolve a relative Package path. This may be removed in a newer version of aron - std::optional<fs::path> resolveRelativePackagePath(const fs::path& path) + std::optional<fs::path> resolveRelativePackagePath(const fs::path& path, const std::vector<fs::path>& includePaths) { + // new behavior: using provided include paths + for (const auto& includePath : includePaths) + { + fs::path absPath = includePath / path; + if (fs::is_regular_file(absPath)) + { + // path is valid + return absPath; + } + } + + // legacy behavior: using cmake package finder paths const std::string package = *path.begin(); armarx::CMakePackageFinder finder(package); if (finder.packageFound()) @@ -59,14 +72,12 @@ namespace armarx::aron::typereader::xml } return std::nullopt; } - else - { - return std::nullopt; - } + + return std::nullopt; } } - void Reader::parseFile(const std::string& _filename) + void Reader::parseFile(const std::string& _filename, const std::vector<std::filesystem::path>& includePaths) { std::string filename = _filename; // Handle C++ style includes like "<path/to/file>". @@ -74,19 +85,19 @@ namespace armarx::aron::typereader::xml { filename = filename.substr(1, filename.size() - 2); } - parseFile(std::filesystem::path(filename)); + parseFile(std::filesystem::path(filename), includePaths); } - void Reader::parseFile(const std::filesystem::path& _file) + void Reader::parseFile(const std::filesystem::path& _file, const std::vector<std::filesystem::path>& includePaths) { fs::path file = _file; RapidXmlReaderPtr reader = RapidXmlReader::FromFile(file.string()); - parse(reader, _file); + parse(reader, _file, includePaths); } // private method reading nodes - void Reader::parse(const RapidXmlReaderPtr& reader, const std::filesystem::path& filePath) + void Reader::parse(const RapidXmlReaderPtr& reader, const std::filesystem::path& filePath, const std::vector<std::filesystem::path>& includePaths) { RapidXmlReaderNode root = reader->getRoot(); @@ -104,7 +115,7 @@ namespace armarx::aron::typereader::xml { for (const auto& include : (*code_includes).nodes()) { - this->codeIncludes.push_back(readCodeInclude(include, filePath)); + this->codeIncludes.push_back(readCodeInclude(include, filePath, includePaths)); } } @@ -113,7 +124,7 @@ namespace armarx::aron::typereader::xml { for (const auto& aronInclude : (*aron_includes).nodes()) { - this->aronIncludes.push_back(readAronInclude(aronInclude, filePath)); + this->aronIncludes.push_back(readAronInclude(aronInclude, filePath, includePaths)); } } @@ -144,7 +155,7 @@ namespace armarx::aron::typereader::xml } } - std::string Reader::readCodeInclude(const RapidXmlReaderNode& node, const std::filesystem::path& filePath) + std::string Reader::readCodeInclude(const RapidXmlReaderNode& node, const std::filesystem::path& filePath, const std::vector<std::filesystem::path>& includePaths) { util::EnforceTagName(node, constantes::INCLUDE_TAG); util::EnforceAttribute(node, constantes::INCLUDE_ATTRIBUTE_NAME); @@ -152,7 +163,7 @@ namespace armarx::aron::typereader::xml return include; } - std::string Reader::readAronInclude(const RapidXmlReaderNode& node, const std::filesystem::path& filePath) + std::string Reader::readAronInclude(const RapidXmlReaderNode& node, const std::filesystem::path& filePath, const std::vector<std::filesystem::path>& includePaths) { util::EnforceTagName(node, constantes::INCLUDE_TAG); std::string specifiedPath = util::GetAttribute(node, constantes::INCLUDE_ATTRIBUTE_NAME); @@ -166,7 +177,8 @@ namespace armarx::aron::typereader::xml if (!xmlincludepath.empty() && xmlincludepath.is_relative()) { - if (std::optional<fs::path> resolvedPackagePath = resolveRelativePackagePath(xmlincludepath); resolvedPackagePath.has_value()) + // ARMARX_INFO << "Checking file " << xmlincludepath; + if (std::optional<fs::path> resolvedPackagePath = resolveRelativePackagePath(xmlincludepath, includePaths); resolvedPackagePath.has_value()) { // check if relative path belongs to a package resolved_absolute_path = resolvedPackagePath.value(); @@ -181,7 +193,13 @@ namespace armarx::aron::typereader::xml if (!fs::is_regular_file(resolved_absolute_path)) { - throw error::AronException(__PRETTY_FUNCTION__, "Could not find an aron XML file. Last path tried was: " + resolved_absolute_path.string()); + std::stringstream ss; + for(const auto& includePath: includePaths) + { + ss << includePath << ", "; + } + + throw error::AronException(__PRETTY_FUNCTION__, "Could not find an aron XML file `" + xmlincludepath.string() + "`. Search paths are: " + ss.str()); } } } @@ -189,7 +207,7 @@ namespace armarx::aron::typereader::xml // parse parent xml file and add objects to alreday known Reader anotherReader; - anotherReader.parseFile(resolved_absolute_path); + anotherReader.parseFile(resolved_absolute_path, includePaths); for (const auto& previouslyKnown : anotherReader.factory.allPreviouslyKnownPublicTypes) { factory.allPreviouslyKnownPublicTypes.push_back(previouslyKnown); @@ -224,5 +242,3 @@ namespace armarx::aron::typereader::xml return type::IntEnum::DynamicCastAndCheck(factory.create(node, Path())); } } - - diff --git a/source/RobotAPI/libraries/aron/core/typereader/xml/Reader.h b/source/RobotAPI/libraries/aron/core/typereader/xml/Reader.h index cd048d4dca481083639bfa282072570f61ac8d5d..91647c64a238cbd237656e5ac454670e82873e19 100644 --- a/source/RobotAPI/libraries/aron/core/typereader/xml/Reader.h +++ b/source/RobotAPI/libraries/aron/core/typereader/xml/Reader.h @@ -50,14 +50,14 @@ namespace armarx::aron::typereader::xml public: Reader() = default; - void parseFile(const std::string&) override; - void parseFile(const std::filesystem::path&) override; + void parseFile(const std::string& filename, const std::vector<std::filesystem::path>& includePaths) override; + void parseFile(const std::filesystem::path& file, const std::vector<std::filesystem::path>& includePaths) override; private: - void parse(const RapidXmlReaderPtr& node, const std::filesystem::path& filePath); + void parse(const RapidXmlReaderPtr& node, const std::filesystem::path& filePath, const std::vector<std::filesystem::path>& includePaths); - std::string readCodeInclude(const RapidXmlReaderNode& node, const std::filesystem::path& filePath); - std::string readAronInclude(const RapidXmlReaderNode& node, const std::filesystem::path& filePath); + std::string readCodeInclude(const RapidXmlReaderNode& node, const std::filesystem::path& filePath, const std::vector<std::filesystem::path>& includePaths); + std::string readAronInclude(const RapidXmlReaderNode& node, const std::filesystem::path& filePath, const std::vector<std::filesystem::path>& includePaths); type::ObjectPtr readGenerateObject(const RapidXmlReaderNode& node); type::IntEnumPtr readGenerateIntEnum(const RapidXmlReaderNode& node);