summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--xmake.cpp90
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 <target>" << std::endl;
}
- std::string get_target(pt::ptree& ptree) {
+ fs::path get_target(const pt::ptree& ptree) {
return ptree.get<std::string>("xmake.build.name");
}
- std::vector<std::string> get_sources(pt::ptree& ptree) {
- std::vector<std::string> sources;
- for (pt::ptree::value_type &v: ptree.get_child("xmake.build")) {
+ std::vector<fs::path> get_sources(const pt::ptree& ptree) {
+ std::vector<fs::path> 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<std::string> get_objects(pt::ptree& ptree) {
- std::vector<std::string> objects{get_sources(ptree)};
+ std::vector<fs::path> get_objects(const pt::ptree& ptree) {
+ std::vector<fs::path> 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<fs::path> &dependencies) {
+ if (!fs::exists(p))
+ return true;
+
+ for (auto& dep: dependencies) {
+ if (!exists(dep) || is_older(p, dep)) {
+ return true;
+ }
+ }
- std::vector<std::string> sources{get_sources(ptree)};
+ return false;
+ }
+
+ void build(const pt::ptree& ptree) {
+ fs::path target{get_target(ptree)};
+
+ std::vector<fs::path> sources{get_sources(ptree)};
std::cout << "Target: " << target << std::endl;
@@ -64,44 +82,52 @@ namespace {
std::vector<std::string> 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<fs::path>{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<std::string> objects{get_objects(ptree)};
- for (auto &i: objects) {
- link_command += fmt::format(" {}", i);
+ std::vector<fs::path> objects{get_objects(ptree)};
+ std::vector<fs::path> 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<std::string> cleanlist{get_objects(ptree)};
+ void clean(const pt::ptree& ptree) {
+ std::vector<fs::path> cleanlist{get_objects(ptree)};
cleanlist.push_back(get_target(ptree));
std::vector<std::string> 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;