From aed6caab9ce43a830c45da08f0380760a2ae4aec Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Wed, 1 May 2024 17:25:11 +0200 Subject: Skip actions for up-to-date targets --- Makefile | 1 + xmake.cpp | 90 ++++++++++++++++++++++++++++++++++++++++----------------------- 2 files changed, 59 insertions(+), 32 deletions(-) diff --git a/Makefile b/Makefile index fec3007..011a775 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,7 @@ OBJ=$(SRC:.cpp=.o) all: $(PROJECTNAME) LDLIBS += -lfmt +CXXFLAGS += -std=c++17 $(PROJECTNAME): $(OBJ) $(CXX) $(LDFLAGS) $^ $(LDLIBS) $(LIBS) -o $@ diff --git a/xmake.cpp b/xmake.cpp index e0a972d..e5f85ac 100644 --- a/xmake.cpp +++ b/xmake.cpp @@ -27,33 +27,51 @@ namespace { std::cout << "Usage: xmake " << std::endl; } - std::string get_target(pt::ptree& ptree) { + fs::path get_target(const pt::ptree& ptree) { return ptree.get("xmake.build.name"); } - std::vector get_sources(pt::ptree& ptree) { - std::vector sources; - for (pt::ptree::value_type &v: ptree.get_child("xmake.build")) { + std::vector get_sources(const pt::ptree& ptree) { + std::vector sources; + for (const pt::ptree::value_type &v: ptree.get_child("xmake.build")) { if (v.first == "source") sources.push_back(v.second.data()); } return sources; } - std::vector get_objects(pt::ptree& ptree) { - std::vector objects{get_sources(ptree)}; + std::vector get_objects(const pt::ptree& ptree) { + std::vector objects{get_sources(ptree)}; for (auto &i: objects) { - fs::path p{i}; - p.replace_extension("o"); - i = p.string(); + i.replace_extension("o"); } return objects; } - void build(pt::ptree& ptree) { - std::string target{get_target(ptree)}; + // both need to exist + bool is_older(const fs::path& p, const fs::path& other) { + auto t_p{fs::last_write_time(p)}; + auto t_other{fs::last_write_time(other)}; + return t_p < t_other; + } + + bool is_outdated(const fs::path& p, const std::vector &dependencies) { + if (!fs::exists(p)) + return true; + + for (auto& dep: dependencies) { + if (!exists(dep) || is_older(p, dep)) { + return true; + } + } - std::vector sources{get_sources(ptree)}; + return false; + } + + void build(const pt::ptree& ptree) { + fs::path target{get_target(ptree)}; + + std::vector sources{get_sources(ptree)}; std::cout << "Target: " << target << std::endl; @@ -64,44 +82,52 @@ namespace { std::vector commands; // compile - for (auto &i: sources) { - fs::path p{i}; - fs::path p_obj{i}; + for (auto &p: sources) { + fs::path p_obj{p}; p_obj.replace_extension("o"); - commands.push_back(fmt::format("g++ -std=c++17 -c {} -o {}", p.string(), p_obj.string())); + if (is_outdated(p_obj, std::vector{p})) { + commands.push_back(fmt::format("g++ -std=c++17 -c {} -o {}", p.string(), p_obj.string())); + } } // link - std::string link_command{"g++"}; - std::vector objects{get_objects(ptree)}; - for (auto &i: objects) { - link_command += fmt::format(" {}", i); + std::vector objects{get_objects(ptree)}; + std::vector dependencies{sources}; + if (is_outdated(target, dependencies)) { + std::string link_command{"g++"}; + for (auto &i: objects) { + link_command += fmt::format(" {}", i.string()); + } + link_command += " -lfmt"; + link_command += fmt::format(" -o {}", target.string()); + commands.push_back(link_command); } - link_command += " -lfmt"; - link_command += fmt::format(" -o {}", target); - commands.push_back(link_command); std::cout << "Commands: " << std::endl; for (auto &i: commands) { std::cout << " " << i << std::endl; } - std::cout << "Running commands: " << std::endl; - for (auto &i: commands) { - std::cout << i << std::endl; - int result{system(i.c_str())}; - if (result != 0) { - throw std::runtime_error(fmt::format("Error {}", result)); + if (commands.size() == 0) { + std::cout << "Everything up to date." << std::endl; + } else { + std::cout << "Running commands: " << std::endl; + for (auto &i: commands) { + std::cout << i << std::endl; + int result{system(i.c_str())}; + if (result != 0) { + throw std::runtime_error(fmt::format("Error {}", result)); + } } } } - void clean(pt::ptree& ptree) { - std::vector cleanlist{get_objects(ptree)}; + void clean(const pt::ptree& ptree) { + std::vector cleanlist{get_objects(ptree)}; cleanlist.push_back(get_target(ptree)); std::vector commands; for (auto &i: cleanlist) { - commands.push_back(fmt::format("rm -f {}", i)); + commands.push_back(fmt::format("rm -f {}", i.string())); } std::cout << "Running commands: " << std::endl; -- cgit v1.2.3