diff options
author | Roland Reichwein <mail@reichwein.it> | 2024-05-01 21:44:11 +0200 |
---|---|---|
committer | Roland Reichwein <mail@reichwein.it> | 2024-05-01 21:44:11 +0200 |
commit | 16031a8ca3e6e36e39b5ac52853f39e559f0460a (patch) | |
tree | e8bb388355606c0f44899f87558bba69e5fdd82b | |
parent | 623def43b2ae0cd23ecef6688257c540e3118856 (diff) |
Create dependencies
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | xmake.cpp | 47 |
2 files changed, 44 insertions, 5 deletions
@@ -6,7 +6,7 @@ OBJ=$(SRC:.cpp=.o) all: $(PROJECTNAME) -LDLIBS += -lfmt +LDLIBS += -lfmt -lreichwein CXXFLAGS += -std=c++17 $(PROJECTNAME): $(OBJ) @@ -1,8 +1,10 @@ #include "xmake.h" +#include <algorithm> #include <cstdlib> #include <filesystem> #include <iostream> +#include <iterator> #include <sstream> #include <stdexcept> #include <string> @@ -15,6 +17,9 @@ #include <fmt/format.h> +#include <libreichwein/file.h> +#include <libreichwein/stringhelper.h> + namespace fs = std::filesystem; namespace bp = boost::process; namespace pt = boost::property_tree; @@ -69,6 +74,37 @@ namespace { return false; } + std::vector<fs::path> deps_from_depfile(const fs::path& path) { + std::string depfile_content{Reichwein::File::getFile(path)}; + std::vector<std::string> parts {Reichwein::Stringhelper::split(depfile_content, ":\r\n")}; + if (parts.size() >= 2) { + std::vector<std::string> deps {Reichwein::Stringhelper::split(parts[1], " ")}; + std::vector<fs::path> result; + std::transform(deps.cbegin(), deps.cend(), std::back_inserter(result), [](const std::string& s){ return s; }); + return result; + } else { + throw std::runtime_error("Bad depfile contents: "s + path.string()); + } + } + + // return contained dependencies + // input: cpp + std::vector<fs::path> make_depfile_from(const fs::path& p) { + fs::path depfile{p}; + depfile.replace_extension("d"); + + // check if depfile exists and if it contains up to date info + if (!fs::exists(depfile) || is_outdated(depfile, deps_from_depfile(depfile))) { + // actually create depfile + int result{system(fmt::format("g++ -MM -MF {} -c {}", depfile.string(), p.string()).c_str())}; + if (result != 0) { + throw std::runtime_error(fmt::format("Depfile {} can't be created", depfile.string())); + } + } + + return deps_from_depfile(depfile); + } + void build(const pt::ptree& ptree) { fs::path target{get_target(ptree)}; std::vector<fs::path> objects{get_objects(ptree)}; @@ -81,14 +117,14 @@ namespace { std::cout << " " << i << std::endl; } + std::cout << "Calculating dependencies..." << std::endl; std::unordered_map<fs::path, std::vector<fs::path>> dependencies; dependencies.emplace(target, objects); for (const auto& p: sources) { fs::path p_obj{p}; p_obj.replace_extension("o"); - dependencies.emplace(p_obj, std::vector<fs::path>{p}); - // TODO: add headers dependencies: - // g++ -MM -MF <depsfile> -c <cppfile> + std::vector<fs::path> deps {make_depfile_from(p)}; + dependencies.emplace(p_obj, deps); } std::vector<std::string> commands; @@ -107,7 +143,7 @@ namespace { for (auto &i: objects) { link_command += fmt::format(" {}", i.string()); } - link_command += " -lfmt"; + link_command += " -lfmt -lreichwein"; link_command += fmt::format(" -o {}", target.string()); commands.push_back(link_command); } @@ -138,6 +174,9 @@ namespace { std::vector<std::string> commands; for (auto &i: cleanlist) { commands.push_back(fmt::format("rm -f {}", i.string())); + fs::path dep{i}; + dep.replace_extension("d"); + commands.push_back(fmt::format("rm -f {}", dep.string())); } std::cout << "Running commands: " << std::endl; |