diff options
Diffstat (limited to 'src/rebuild.cc')
-rw-r--r-- | src/rebuild.cc | 251 |
1 files changed, 194 insertions, 57 deletions
diff --git a/src/rebuild.cc b/src/rebuild.cc index 353beb0..9ddf5ba 100644 --- a/src/rebuild.cc +++ b/src/rebuild.cc @@ -6,18 +6,22 @@ #include <iostream> #include <filesystem> #include <algorithm> +#include <source_location> +#include <cstring> -#include "execute.h" #include "configure.h" -#include "settings.h" #include "libctor.h" +#include "tasks.h" +#include "build.h" +#include "execute.h" +#include "tools.h" +#include "util.h" std::array<BuildConfigurationEntry, 1024> configFiles; std::size_t numConfigFiles{0}; -// TODO: Use c++20 when ready, somehing like this: -//int reg(const std::source_location location = std::source_location::current()) -int reg(const char* location, std::vector<BuildConfiguration> (*cb)()) +int reg(BuildConfigurations (*cb)(const Settings&), + const std::source_location location) { // NOTE: std::cout cannot be used here if(numConfigFiles >= configFiles.size()) @@ -27,13 +31,41 @@ int reg(const char* location, std::vector<BuildConfiguration> (*cb)()) exit(1); } - configFiles[numConfigFiles].file = location; + auto loc = std::filesystem::path(location.file_name()); + if(loc.is_absolute()) + { + auto pwd = std::filesystem::current_path(); + auto rel = std::filesystem::relative(loc, pwd); + configFiles[numConfigFiles].file = strdup(rel.string().data()); // NOTE: This intentionally leaks memory + } + else + { + configFiles[numConfigFiles].file = location.file_name(); + } configFiles[numConfigFiles].cb = cb; ++numConfigFiles; return 0; } +int reg(const char* location) +{ + // NOTE: std::cout cannot be used here + if(numConfigFiles >= configFiles.size()) + { + fprintf(stderr, "Max %d build configurations currently supported.\n", + (int)configFiles.size()); + exit(1); + } + + configFiles[numConfigFiles].file = location; + configFiles[numConfigFiles].cb = + [](const Settings&){ return std::vector<BuildConfiguration>{}; }; + ++numConfigFiles; + + return 0; +} + int unreg(const char* location) { std::size_t found{0}; @@ -54,91 +86,196 @@ int unreg(const char* location) } } + for(std::size_t i = 0; i < numExternalConfigFiles;) + { + if(std::string(location) == externalConfigFiles[i].file) + { + ++found; + for(std::size_t j = i; j < numExternalConfigFiles; ++j) + { + externalConfigFiles[j] = externalConfigFiles[j + 1]; + } + --numExternalConfigFiles; + } + else + { + ++i; + } + } + return found; } -void recompileCheck(const Settings& settings, int argc, char* argv[], - bool force, bool relaunch_allowed) +std::array<ExternalConfigurationEntry, 1024> externalConfigFiles; +std::size_t numExternalConfigFiles{0}; + +int reg(ExternalConfigurations (*cb)(const Settings&), + const std::source_location location) { - bool dirty{force}; + // NOTE: std::cout cannot be used here + if(numExternalConfigFiles >= externalConfigFiles.size()) + { + fprintf(stderr, "Max %d external configurations currently supported.\n", + (int)externalConfigFiles.size()); + exit(1); + } - std::vector<std::string> args; - args.push_back("-s"); - args.push_back("-O3"); - args.push_back("-std=c++17"); - args.push_back("-pthread"); + externalConfigFiles[numExternalConfigFiles].file = location.file_name(); + externalConfigFiles[numExternalConfigFiles].cb = cb; + ++numExternalConfigFiles; - std::filesystem::path binFile(argv[0]); + return 0; +} - if(std::filesystem::exists(configurationFile)) +namespace +{ +bool contains(const std::vector<Source>& sources, const std::string& file) +{ + for(const auto& source : sources) { - args.push_back(configurationFile.string()); - - if(std::filesystem::last_write_time(binFile) <= - std::filesystem::last_write_time(configurationFile)) - { - dirty = true; - } - - const auto& c = configuration(); - if(&c == &default_configuration) + if(source.file == file) { - // configuration.cc exists, but currently compiled with the default one. - dirty = true; + return true; } } - if(settings.verbose > 1) + return false; +} +} + +bool recompileCheck(const Settings& global_settings, int argc, char* argv[], + bool relaunch_allowed) +{ + using namespace std::string_literals; + + if(global_settings.verbose > 1) { std::cout << "Recompile check (" << numConfigFiles << "):\n"; } + BuildConfiguration config; + + config.name = "ctor"; + config.system = OutputSystem::Build; + + auto tool_chain = getToolChain(config.system); + + append(config.flags.cxxflags, + getOption(tool_chain, opt::optimization, "3")); + append(config.flags.cxxflags, + getOption(tool_chain, opt::cpp_std, "c++20")); + if(hasConfiguration(cfg::ctor_includedir)) + { + append(config.flags.cxxflags, + getOption(tool_chain, opt::include_path, + getConfiguration(cfg::ctor_includedir))); + } + if(hasConfiguration(cfg::ctor_libdir)) + { + append(config.flags.ldflags, + getOption(tool_chain, opt::library_path, + getConfiguration(cfg::ctor_libdir))); + } + append(config.flags.ldflags, getOption(tool_chain, opt::link, "ctor")); + append(config.flags.ldflags, getOption(tool_chain, opt::threads)); + + Settings settings{global_settings}; + settings.verbose = -1; // Make check completely silent. + settings.builddir += "/ctor"; // override builddir to use ctor subdir + + { + std::filesystem::path buildfile = settings.builddir; + std::filesystem::path currentfile = argv[0]; + config.target = std::filesystem::relative(currentfile, buildfile).string(); + } + + if(std::filesystem::exists(configurationFile)) + { + config.sources.push_back(configurationFile.string()); + } + for(std::size_t i = 0; i < numConfigFiles; ++i) { std::string location = configFiles[i].file; - if(settings.verbose > 1) + if(global_settings.verbose > 1) { std::cout << " - " << location << "\n"; } - std::filesystem::path configFile(location); - if(std::filesystem::last_write_time(binFile) <= - std::filesystem::last_write_time(configFile)) + + // Ensure that files containing multiple configurations are only added once. + if(!contains(config.sources, location)) { - dirty = true; + config.sources.push_back(location); } + } - // Support adding multiple config functions from the same file - if(std::find(args.begin(), args.end(), location) == std::end(args)) + for(std::size_t i = 0; i < numExternalConfigFiles; ++i) + { + std::string location = externalConfigFiles[i].file; + if(global_settings.verbose > 1) { - args.push_back(location); + std::cout << " - " << location << "\n"; + } + + // Ensure that files containing multiple configurations are only added once. + if(!contains(config.sources, location)) + { + config.sources.push_back(location); + } + } + + auto tasks = taskFactory({config}, settings, {}); + + for(auto task : tasks) + { + if(task->registerDepTasks(tasks)) + { + return false; + } + } + + // Find out if reconfigure is needed + bool reconfigure{false}; + for(auto task : tasks) + { + if(task->dirty() && + task->source() != "" && // only look at source files + task->source() != "configuration.cc") // don't reconfigure if only configuration.cc is changed. + { + reconfigure |= true; } } - args.push_back("libctor.a"); - args.push_back("-o"); - args.push_back(binFile.string()); - if(dirty) + auto dirty_tasks = build(settings, "ctor", tasks, true); // dryrun + if(dirty_tasks) { - std::cout << "Rebuilding config\n"; - auto tool = getConfiguration(cfg::build_cxx, "/usr/bin/g++"); - auto ret = execute(tool, args, settings.verbose > 0); + std::cout << "Rebuilding config.\n"; + auto ret = build(settings, "ctor", tasks); // run for real if(ret != 0) { - std::cerr << "Failed: ." << ret << "\n"; - exit(1); + return ret; } - else + } + + if(reconfigure) + { + std::vector<std::string> args; + args.push_back("reconfigure"); + if(!relaunch_allowed) { - if(relaunch_allowed) - { - std::cout << "Re-launch\n"; - std::vector<std::string> args; - for(int i = 1; i < argc; ++i) - { - args.push_back(argv[i]); - } - exit(execute(argv[0], args, settings.verbose > 0)); - } + args.push_back("--no-rerun"); } + for(int i = 1; i < argc; ++i) + { + args.push_back(argv[i]); + } + auto ret = execute(argv[0], args); + //if(ret != 0) + { + exit(ret); + } + } + + return dirty_tasks; } |