diff options
author | Bent Bisballe Nyeng <deva@aasimon.org> | 2021-08-28 18:59:29 +0200 |
---|---|---|
committer | Bent Bisballe Nyeng <deva@aasimon.org> | 2021-08-28 18:59:29 +0200 |
commit | 5da56616cccf4e595ec6a556cf1aef40b37746e3 (patch) | |
tree | 8142e294a251ca2ab1697f7541fe67dfd31622e0 /src/libcppbuild.cc | |
parent | 0597cb9854d66d918762ff167148516b69c02e9a (diff) |
Move sources to ... well, src ;)
Diffstat (limited to 'src/libcppbuild.cc')
-rw-r--r-- | src/libcppbuild.cc | 316 |
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; +} |