summaryrefslogtreecommitdiff
path: root/src/rebuild.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/rebuild.cc')
-rw-r--r--src/rebuild.cc251
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;
}