summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2021-06-11 19:07:09 +0200
committerBent Bisballe Nyeng <deva@aasimon.org>2021-06-11 19:07:16 +0200
commit474ce1322f3c13fe414b5e2201d82a4136a947da (patch)
tree841d4771e451d646c7a83384a148a7b791f1ff44
Simple build config with dependency tracking.
-rw-r--r--Makefile11
-rw-r--r--cppbuild.cc19
-rw-r--r--libcppbuild.cc204
-rw-r--r--libcppbuild.h12
-rw-r--r--src/bar.cc9
-rw-r--r--src/bar.obin0 -> 2848 bytes
-rw-r--r--src/bas.h2
-rw-r--r--src/foo.cc6
-rw-r--r--src/foo.h5
9 files changed, 268 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..7cad9bd
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,11 @@
+all: libcppbuild.a cppbuild
+
+libcppbuild.a: libcppbuild.cc
+ g++ -g -std=c++17 libcppbuild.cc -c -o libcppbuild.o
+ ar rcs libcppbuild.a libcppbuild.o
+
+cppbuild: cppbuild.cc libcppbuild.a
+ g++ -g -std=c++17 cppbuild.cc libcppbuild.a -o cppbuild
+
+clean:
+ rm -f cppbuild libcppbuild.o libcppbuild.a
diff --git a/cppbuild.cc b/cppbuild.cc
new file mode 100644
index 0000000..b06b082
--- /dev/null
+++ b/cppbuild.cc
@@ -0,0 +1,19 @@
+#include <vector>
+#include <string>
+#include <utility>
+
+#include "libcppbuild.h"
+
+BuildConfiguration configs()
+{
+ return
+ {
+ // target
+ "bas",
+ {
+ // source files
+ "src/foo.cc",
+ "src/bar.cc",
+ }
+ };
+}
diff --git a/libcppbuild.cc b/libcppbuild.cc
new file mode 100644
index 0000000..ff208b3
--- /dev/null
+++ b/libcppbuild.cc
@@ -0,0 +1,204 @@
+#include <vector>
+#include <string>
+#include <filesystem>
+#include <iostream>
+#include <fstream>
+#include <regex>
+#include <utility>
+
+#include "libcppbuild.h"
+
+namespace
+{
+std::string readFile(const std::string &fileName)
+{
+ std::ifstream ifs(fileName.c_str(), std::ios::in | std::ios::binary | std::ios::ate);
+
+ std::ifstream::pos_type fileSize = ifs.tellg();
+ ifs.seekg(0, std::ios::beg);
+
+ std::vector<char> bytes(fileSize);
+ ifs.read(bytes.data(), fileSize);
+
+ return std::string(bytes.data(), fileSize);
+}
+
+std::vector<std::string> readDeps(const std::string& depFile)
+{
+ if(!std::filesystem::exists(depFile))
+ {
+ return {};
+ }
+
+ auto str = readFile(depFile);
+
+ std::vector<std::string> output;
+ std::string tmp;
+ bool start{false};
+ bool in_whitespace{false};
+ for(const auto& c : str)
+ {
+ if(c == '\\' || c == '\n')
+ {
+ continue;
+ }
+
+ if(c == ':')
+ {
+ start = true;
+ continue;
+ }
+
+ if(!start)
+ {
+ continue;
+ }
+
+ if(c == ' ' || c == '\t')
+ {
+ if(in_whitespace)
+ {
+ continue;
+ }
+
+ if(!tmp.empty())
+ {
+ output.push_back(tmp);
+ }
+ tmp.clear();
+ in_whitespace = true;
+ }
+ else
+ {
+ in_whitespace = false;
+ tmp += c;
+ }
+ }
+
+ if(!tmp.empty())
+ {
+ output.push_back(tmp);
+ }
+
+ return output;
+}
+} // namespace ::
+
+
+
+int main(int argc, const char* argv[])
+{
+ if(argc == 2 && std::string(argv[1]) == "clean")
+ {
+ system("rm -Rf build");
+ return 0;
+ }
+
+ std::filesystem::path builddir("build/");
+ std::filesystem::create_directory(builddir);
+
+ auto project = configs();
+ std::string output = "build/" + project.target;
+ const auto& files = project.sources;
+ std::vector<std::string> objects;
+
+ std::cout << "Building\n";
+ for(const auto& file : files)
+ {
+ auto path = std::filesystem::path(file);
+ std::string object = builddir / path.stem();
+ object += ".o";
+ objects.push_back(object);
+
+ std::string deps = builddir / path.stem();
+ deps += ".d";
+
+ if(!std::filesystem::exists(file))
+ {
+ std::cout << "Missing source file: " << file << "\n";
+ return 1;
+ }
+
+ bool recompile{false};
+
+ if(!std::filesystem::exists(object) ||
+ !std::filesystem::exists(deps))
+ {
+ recompile = true;
+ }
+
+ if(!recompile &&
+ std::filesystem::last_write_time(file) >
+ std::filesystem::last_write_time(deps))
+ {
+ recompile = true;
+ }
+
+ if(!recompile)
+ {
+ auto depList = readDeps(deps);
+ for(const auto& dep : depList)
+ {
+ if(!std::filesystem::exists(dep) ||
+ std::filesystem::last_write_time(object) <
+ std::filesystem::last_write_time(dep))
+ {
+ recompile = true;
+ break;
+ }
+ }
+ }
+
+ if(recompile ||
+ !std::filesystem::exists(object) ||
+ std::filesystem::last_write_time(file) >
+ std::filesystem::last_write_time(object))
+ {
+ std::string compiler = "g++ -MMD -c " + file + " -o " + object;
+ std::cout << compiler << "\n";
+ if(system(compiler.data()))
+ {
+ return 1;
+ }
+ }
+ }
+
+ std::cout << "Linking\n";
+ bool dolink{false};
+ if(!std::filesystem::exists(output))
+ {
+ dolink = true;
+ }
+ else
+ {
+ for(const auto& object : objects)
+ {
+ if(std::filesystem::last_write_time(output) <=
+ std::filesystem::last_write_time(object))
+ {
+ dolink = true;
+ break;
+ }
+ }
+ }
+
+ if(!dolink)
+ {
+ std::cout << "No linking needed\n";
+ return 0;
+ }
+
+ std::string objectlist;
+ for(const auto& object : objects)
+ {
+ objectlist += object + " ";
+ }
+ std::string compiler = "g++ " + objectlist + " -o " + output;
+ std::cout << compiler << "\n";
+ if(system(compiler.data()))
+ {
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/libcppbuild.h b/libcppbuild.h
new file mode 100644
index 0000000..11a8eb7
--- /dev/null
+++ b/libcppbuild.h
@@ -0,0 +1,12 @@
+#pragma once
+
+#include <string>
+#include <vector>
+
+struct BuildConfiguration
+{
+ std::string target;
+ std::vector<std::string> sources;
+};
+
+BuildConfiguration configs();
diff --git a/src/bar.cc b/src/bar.cc
new file mode 100644
index 0000000..2486a0a
--- /dev/null
+++ b/src/bar.cc
@@ -0,0 +1,9 @@
+#include <iostream>
+
+#include "foo.h"
+
+int main()
+{
+ foo();
+ std::cout << __FILE__ << "\n";
+}
diff --git a/src/bar.o b/src/bar.o
new file mode 100644
index 0000000..37903db
--- /dev/null
+++ b/src/bar.o
Binary files differ
diff --git a/src/bas.h b/src/bas.h
new file mode 100644
index 0000000..3f59c93
--- /dev/null
+++ b/src/bas.h
@@ -0,0 +1,2 @@
+#pragma once
+
diff --git a/src/foo.cc b/src/foo.cc
new file mode 100644
index 0000000..b2c478c
--- /dev/null
+++ b/src/foo.cc
@@ -0,0 +1,6 @@
+#include <iostream>
+
+void foo()
+{
+ std::cout << __FILE__ << "\n";
+}
diff --git a/src/foo.h b/src/foo.h
new file mode 100644
index 0000000..9620fc7
--- /dev/null
+++ b/src/foo.h
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "bas.h"
+
+void foo();