#include "MakefileReader.h" #include #include "file.h" namespace pt = boost::property_tree; namespace fs = std::filesystem; namespace { // the elements with this name are considered paths, where relative prefixes will be added if necessary std::vector path_elements{"name", "source", "test"}; const std::string topelement{"ymake"}; // add path to respective elements in tree, recursively void adjust_path(pt::ptree::value_type& element, const fs::path& path) { // add path prefix if path element if (std::find(path_elements.begin(), path_elements.end(), element.first) != path_elements.end()) { std::string content{element.second.data()}; element.second.data() = simplified_path(path / fs::path{content}).string(); } for (auto &i: element.second) { // recursively run adjust_path(i, path); } } void join(pt::ptree& tree, const pt::ptree& makefile_tree, const fs::path& path) { if (tree.empty()) { tree = makefile_tree; // including top level single "ymake" element } else { // copy all elements inside single "ymake" pt::ptree& target{tree.get_child(topelement)}; const pt::ptree& source{makefile_tree.get_child(topelement)}; for (const auto& i: source) { auto it {target.push_back(i)}; auto &element{*it}; adjust_path(element, path); } } } } MakefileReader::MakefileReader() { } pt::ptree MakefileReader::read(const fs::path& path) const { pt::ptree ptree; // YMakefile needs to exist, but it can be in a subdir, so we need to // iterate first over directories bool makefile_found{}; for (const fs::directory_entry& dir_entry: fs::recursive_directory_iterator(path)) { pt::ptree makefile_tree; fs::path path{dir_entry.path()}; if (dir_entry.is_regular_file() && path.filename() == YMakefile) { makefile_found = true; pt::read_xml(path, makefile_tree, pt::xml_parser::no_comments | pt::xml_parser::trim_whitespace); join(ptree, makefile_tree, simplified_path(path.parent_path())); } } if (!makefile_found) { throw std::runtime_error("YMakefile not found"); } return ptree; }