|
|
@@ -0,0 +1,83 @@
|
|
|
+#pragma once
|
|
|
+
|
|
|
+// Because Apple refuses to update libc++ in a timely manner
|
|
|
+// In exchange, this in C++11 compatible...
|
|
|
+#include <string>
|
|
|
+#include <vector>
|
|
|
+
|
|
|
+#include "command_builder.h"
|
|
|
+#include "types.h"
|
|
|
+
|
|
|
+#define CXX "clang++"
|
|
|
+
|
|
|
+namespace build {
|
|
|
+
|
|
|
+ class project {
|
|
|
+ private:
|
|
|
+ version vers_{version::none};
|
|
|
+ std::string name_;
|
|
|
+ std::vector<source_file> source_files_;
|
|
|
+
|
|
|
+ public:
|
|
|
+ project(int argc, char const * const * const argv);
|
|
|
+
|
|
|
+ project & set_version(version vers);
|
|
|
+ project & set_name(std::string const & name);
|
|
|
+ project & set_source_file(fs::path const & file);
|
|
|
+
|
|
|
+ int generate() const;
|
|
|
+
|
|
|
+ private:
|
|
|
+ std::pair<std::vector<object_file>, int> generate_objects() const;
|
|
|
+ };
|
|
|
+
|
|
|
+ // TODO(samjaffe): Are there actually any arguments that belong here?
|
|
|
+ project::project(int argc, char const * const * const argv) {}
|
|
|
+
|
|
|
+ project & project::set_version(version vers) {
|
|
|
+ vers_ = vers;
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+
|
|
|
+ project & project::set_name(std::string const & name) {
|
|
|
+ name_ = name;
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+
|
|
|
+ project & project::set_source_file(fs::path const & file) {
|
|
|
+ if (!fs::is_regular_file(file)) {
|
|
|
+ throw std::logic_error(file.string() + " is not a regular file");
|
|
|
+ }
|
|
|
+ source_files_.emplace_back(file);
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+
|
|
|
+ std::pair<std::vector<object_file>, int> project::generate_objects() const {
|
|
|
+ fs::path obj_dir(".obj");
|
|
|
+ fs::create_directory(obj_dir);
|
|
|
+ std::vector<object_file> objects;
|
|
|
+ for (auto const & file : source_files_) {
|
|
|
+ output_file const outfile =
|
|
|
+ obj_dir / file.get().filename().replace_extension(".o");
|
|
|
+ auto cmd = command_builder(CXX, 1) << vers_ << file << outfile;
|
|
|
+ if (int rc = cmd.execute()) { return {{}, rc}; }
|
|
|
+ objects.emplace_back(outfile);
|
|
|
+ }
|
|
|
+ return {objects, 0};
|
|
|
+ }
|
|
|
+
|
|
|
+ int project::generate() const {
|
|
|
+ std::cout << "Generating Project: " << name_ << std::endl;
|
|
|
+ // Step 1: Compile Object files
|
|
|
+ auto [objects, rc] = generate_objects();
|
|
|
+ if (rc) { return rc; }
|
|
|
+
|
|
|
+ // Step 2: Generate Executable
|
|
|
+ fs::path bin_dir(".bin");
|
|
|
+ fs::create_directory(bin_dir);
|
|
|
+ output_file const outfile = bin_dir / name_;
|
|
|
+ auto cmd = command_builder(CXX, 1) << vers_ << outfile << objects;
|
|
|
+ return cmd.execute();
|
|
|
+ }
|
|
|
+
|
|
|
+}
|