diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | MakefileReader.cpp | 64 | ||||
-rw-r--r-- | MakefileReader.h | 15 | ||||
-rw-r--r-- | file.cpp | 7 | ||||
-rw-r--r-- | file.h | 3 | ||||
-rw-r--r-- | test-ymake.cpp | 1 | ||||
-rw-r--r-- | ymake.cpp | 4 |
7 files changed, 93 insertions, 3 deletions
@@ -1,6 +1,6 @@ PROJECTNAME=ymake -SRC=main.cpp ymake.cpp Builder.cpp ProcessRunner.cpp file.cpp LanguageSettings.cpp +SRC=main.cpp ymake.cpp Builder.cpp ProcessRunner.cpp file.cpp LanguageSettings.cpp MakefileReader.cpp OBJ=$(SRC:.cpp=.o) YSCAN=yscan diff --git a/MakefileReader.cpp b/MakefileReader.cpp new file mode 100644 index 0000000..ebcc0a8 --- /dev/null +++ b/MakefileReader.cpp @@ -0,0 +1,64 @@ +#include "MakefileReader.h" + +#include <boost/property_tree/xml_parser.hpp> + +#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<std::string> path_elements{"name", "source", "test"}; + + // 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("ymake")}; + const pt::ptree& source{makefile_tree.get_child("ymake")}; + 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; + + 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) { + 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())); + } + } + + return ptree; +} diff --git a/MakefileReader.h b/MakefileReader.h new file mode 100644 index 0000000..7ad63c2 --- /dev/null +++ b/MakefileReader.h @@ -0,0 +1,15 @@ +#pragma once + +#include <filesystem> + +#include <boost/property_tree/ptree.hpp> + +class MakefileReader +{ +public: + MakefileReader(); + + boost::property_tree::ptree read(const std::filesystem::path& path) const; +}; + + @@ -22,3 +22,10 @@ bool is_compile_unit_source_by_extension(const fs::path& p) { return compile_unit_source_types.find(ext) != compile_unit_source_types.end(); } +std::filesystem::path simplified_path(const std::filesystem::path& p) +{ + if (p.string().substr(0, 2) == "./") { + return p.string().substr(2); + } + return p; +} @@ -6,3 +6,6 @@ extern const std::filesystem::path YMakefile; bool is_buildable_by_extension(const std::filesystem::path& p); bool is_compile_unit_source_by_extension(const std::filesystem::path& p); + +// removes initial "./" +std::filesystem::path simplified_path(const std::filesystem::path& p); diff --git a/test-ymake.cpp b/test-ymake.cpp index a6edc5f..dfed871 100644 --- a/test-ymake.cpp +++ b/test-ymake.cpp @@ -198,6 +198,7 @@ TEST_F(ymakeTest, build_three_cpp) // TODO: multiple builds // TODO: test tests // TODO: test g++/clang++ +// TODO: multiple dirs / YMakefiles TEST_F(yscanTest, no_cpp_file) { @@ -2,6 +2,7 @@ #include "file.h" #include "Builder.h" +#include "MakefileReader.h" #include <algorithm> #include <cstdlib> @@ -41,8 +42,7 @@ namespace { int ymake(int argc, char* argv[]) { try { - pt::ptree ptree; - pt::read_xml(YMakefile, ptree, pt::xml_parser::no_comments | pt::xml_parser::trim_whitespace); + pt::ptree ptree{MakefileReader{}.read(".")}; std::string action{"default"}; |