summaryrefslogtreecommitdiff
path: root/src/libcppbuild.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcppbuild.cc')
-rw-r--r--src/libcppbuild.cc316
1 files changed, 316 insertions, 0 deletions
diff --git a/src/libcppbuild.cc b/src/libcppbuild.cc
new file mode 100644
index 0000000..d3d8a51
--- /dev/null
+++ b/src/libcppbuild.cc
@@ -0,0 +1,316 @@
+#include <vector>
+#include <string>
+#include <filesystem>
+#include <iostream>
+#include <utility>
+#include <list>
+#include <thread>
+#include <memory>
+#include <algorithm>
+#include <list>
+#include <array>
+#include <deque>
+#include <fstream>
+#include <cstdlib>
+#include <set>
+
+#include <getoptpp/getoptpp.hpp>
+
+#include "libcppbuild.h"
+#include "settings.h"
+#include "configure.h"
+#include "rebuild.h"
+#include "tasks.h"
+#include "build.h"
+int main(int argc, char* argv[])
+{
+ if(argc > 1 && std::string(argv[1]) == "configure")
+ {
+ return configure(argc, argv);
+ }
+
+ Settings settings{};
+
+ settings.builddir = getConfiguration(cfg::builddir, "build");
+ settings.parallel_processes =
+ std::max(1u, std::thread::hardware_concurrency() * 2 - 1);
+ settings.verbose = 0;
+
+ bool write_compilation_database{false};
+ std::string compilation_database;
+ bool print_configure_cmd{false};
+ bool print_configure_db{false};
+ std::vector<std::string> add_files;
+ std::vector<std::string> remove_files;
+ bool list_files{false};
+ bool list_targets{false};
+ bool no_relaunch{false}; // true means no re-launch after rebuild.
+
+ dg::Options opt;
+ int key{128};
+
+ opt.add("jobs", required_argument, 'j',
+ "Number of parallel jobs. (default: cpucount * 2 - 1)",
+ [&]() {
+ try
+ {
+ settings.parallel_processes = std::stoi(optarg);
+ }
+ catch(...)
+ {
+ std::cerr << "Not a number\n";
+ return 1;
+ }
+ return 0;
+ });
+
+ opt.add("build-dir", required_argument, 'b',
+ "Overload output directory for build files (default: '" +
+ settings.builddir + "').",
+ [&]() {
+ settings.builddir = optarg;
+ return 0;
+ });
+
+ opt.add("verbose", no_argument, 'v',
+ "Be verbose. Add multiple times for more verbosity.",
+ [&]() {
+ settings.verbose++;
+ return 0;
+ });
+
+ opt.add("add", required_argument, 'a',
+ "Add specified file to the build configurations.",
+ [&]() {
+ no_relaunch = true;
+ add_files.push_back(optarg);
+ return 0;
+ });
+
+ opt.add("remove", required_argument, 'r',
+ "Remove specified file from the build configurations.",
+ [&]() {
+ no_relaunch = true;
+ remove_files.push_back(optarg);
+ return 0;
+ });
+
+ opt.add("list-files", no_argument, 'L',
+ "List files in the build configurations.",
+ [&]() {
+ no_relaunch = true;
+ list_files = true;
+ return 0;
+ });
+
+ opt.add("list-targets", no_argument, 'l',
+ "List targets.",
+ [&]() {
+ no_relaunch = true;
+ list_targets = true;
+ return 0;
+ });
+
+ opt.add("configure-cmd", no_argument, key++,
+ "Print commandline for last configure.",
+ [&]() {
+ no_relaunch = true;
+ print_configure_cmd = true;
+ return 0;
+ });
+
+ opt.add("configure-db", no_argument, key++,
+ "Print entire configure parameter database.",
+ [&]() {
+ no_relaunch = true;
+ print_configure_db = true;
+ return 0;
+ });
+
+ opt.add("database", required_argument, 'd',
+ "Write compilation database json file.",
+ [&]() {
+ no_relaunch = true;
+ write_compilation_database = true;
+ compilation_database = optarg;
+ return 0;
+ });
+
+ opt.add("help", no_argument, 'h',
+ "Print this help text.",
+ [&]() {
+ std::cout << "Usage: " << argv[0] << " [options] [target] ...\n";
+ std::cout <<
+R"_( where target can be either:
+ configure - run configuration step (cannot be used with other targets).
+ clean - clean all generated files.
+ all - build all targets (default)
+ or the name of a target which will be built along with its dependencies.
+ Use '-l' to see a list of possible target names.
+
+Options:
+)_";
+ opt.help();
+ exit(0);
+ return 0;
+ });
+
+ opt.process(argc, argv);
+
+ auto verbose_env = std::getenv("V");
+ if(verbose_env)
+ {
+ settings.verbose = std::atoi(verbose_env);
+ }
+
+ if(list_files)
+ {
+ std::set<std::string> files;
+ for(std::size_t i = 0; i < numConfigFiles; ++i)
+ {
+ files.insert(configFiles[i].file);
+ }
+
+ for(const auto& file : files)
+ {
+ std::cout << file << "\n";
+ }
+ }
+
+ if(!add_files.empty() || !remove_files.empty())
+ {
+ for(const auto& add_file : add_files)
+ {
+ reg(add_file.data(), [](){ return std::vector<BuildConfiguration>{};});
+ }
+
+ for(const auto& remove_file : remove_files)
+ {
+ unreg(remove_file.data());
+ }
+
+ // Force rebuild if files were added
+ recompileCheck(settings, 1, argv, true, no_relaunch == false);
+ }
+
+ recompileCheck(settings, argc, argv);
+
+ std::filesystem::path builddir(settings.builddir);
+ std::filesystem::create_directories(builddir);
+
+ auto all_tasks = getTasks(settings);
+
+ if(list_targets)
+ {
+ for(const auto& task : all_tasks)
+ {
+ if(task->targetType() != TargetType::Object)
+ {
+ std::cout << task->name() << "\n";
+ }
+ }
+ }
+
+ if(write_compilation_database)
+ {
+ std::ofstream istr(compilation_database);
+ istr << "[";
+ bool first{true};
+ for(auto task : all_tasks)
+ {
+ auto s = task->toJSON();
+ if(!s.empty())
+ {
+ if(!first)
+ {
+ istr << ",\n";
+ }
+ else
+ {
+ istr << "\n";
+ }
+ first = false;
+ istr << s;
+ }
+ }
+ istr << "\n]\n";
+ }
+
+ if(print_configure_cmd)
+ {
+ std::cout << getConfiguration("cmd") << "\n";
+ }
+
+ if(print_configure_db)
+ {
+ const auto& c = configuration();
+ for(const auto& config : c)
+ {
+ std::cout << config.first << ": " << config.second << "\n";
+ }
+ }
+
+ for(auto task : all_tasks)
+ {
+ if(task->registerDepTasks(all_tasks))
+ {
+ return 1;
+ }
+ }
+
+ bool build_all{true};
+ for(const auto& arg : opt.arguments())
+ {
+ if(arg == "configure")
+ {
+ std::cerr << "The 'configure' target must be the first argument.\n";
+ return 1;
+ }
+
+ if(arg == "clean")
+ {
+ build_all = false;
+
+ std::cout << "Cleaning\n";
+ for(auto& task : all_tasks)
+ {
+ if(task->clean() != 0)
+ {
+ return 1;
+ }
+ }
+ }
+ else
+ {
+ build_all = false;
+
+ if(arg == "all")
+ {
+ auto ret = build(settings, "all", all_tasks, all_tasks);
+ if(ret != 0)
+ {
+ return ret;
+ }
+ }
+ else
+ {
+ auto ret = build(settings, arg, all_tasks);
+ if(ret != 0)
+ {
+ return ret;
+ }
+ }
+ }
+ }
+
+ if(build_all)
+ {
+ auto ret = build(settings, "all", all_tasks, all_tasks);
+ if(ret != 0)
+ {
+ return ret;
+ }
+ }
+
+ return 0;
+}