summaryrefslogtreecommitdiff
path: root/src/configure.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/configure.cc')
-rw-r--r--src/configure.cc388
1 files changed, 337 insertions, 51 deletions
diff --git a/src/configure.cc b/src/configure.cc
index b3517dc..a81f8ad 100644
--- a/src/configure.cc
+++ b/src/configure.cc
@@ -6,36 +6,67 @@
#include <iostream>
#include <filesystem>
#include <fstream>
+#include <optional>
#include <getoptpp/getoptpp.hpp>
-#include "settings.h"
#include "execute.h"
#include "libctor.h"
#include "tasks.h"
+#include "rebuild.h"
+#include "externals.h"
std::filesystem::path configurationFile("configuration.cc");
std::filesystem::path configHeaderFile("config.h");
-const std::map<std::string, std::string> default_configuration{};
-const std::map<std::string, std::string>& __attribute__((weak)) configuration()
+std::map<std::string, std::string> external_includedir;
+std::map<std::string, std::string> external_libdir;
+
+const Configuration default_configuration{};
+const Configuration& __attribute__((weak)) configuration()
{
return default_configuration;
}
+namespace ctor
+{
+std::optional<std::string> includedir;
+std::optional<std::string> libdir;
+}
+
bool hasConfiguration(const std::string& key)
{
+ if(key == cfg::ctor_includedir && ctor::includedir)
+ {
+ return true;
+ }
+
+ if(key == cfg::ctor_libdir && ctor::libdir)
+ {
+ return true;
+ }
+
const auto& c = configuration();
- return c.find(key) != c.end();
+ return c.tools.find(key) != c.tools.end();
}
const std::string& getConfiguration(const std::string& key,
const std::string& defaultValue)
{
+ if(key == cfg::ctor_includedir && ctor::includedir)
+ {
+ return *ctor::includedir;
+ }
+
+ if(key == cfg::ctor_libdir && ctor::libdir)
+ {
+ return *ctor::libdir;
+ }
+
const auto& c = configuration();
if(hasConfiguration(key))
{
- return c.at(key);
+ return c.tools.at(key);
}
return defaultValue;
@@ -44,7 +75,7 @@ const std::string& getConfiguration(const std::string& key,
std::string locate(const std::string& arch, const std::string& app)
{
std::string path_env = std::getenv("PATH");
- std::cout << path_env << "\n";
+ //std::cout << path_env << "\n";
std::string program = app;
if(!arch.empty())
@@ -72,15 +103,15 @@ std::string locate(const std::string& arch, const std::string& app)
auto perms = std::filesystem::status(prog_path).permissions();
if((perms & std::filesystem::perms::owner_exec) != std::filesystem::perms::none)
{
- std::cout << " - executable by owner\n";
+ //std::cout << " - executable by owner\n";
}
if((perms & std::filesystem::perms::group_exec) != std::filesystem::perms::none)
{
- std::cout << " - executable by group\n";
+ //std::cout << " - executable by group\n";
}
if((perms & std::filesystem::perms::others_exec) != std::filesystem::perms::none)
{
- std::cout << " - executable by others\n";
+ //std::cout << " - executable by others\n";
}
return prog_path.string();
@@ -92,21 +123,38 @@ std::string locate(const std::string& arch, const std::string& app)
return {};
}
-int configure(int argc, char* argv[])
+class Args
+ : public std::vector<char*>
{
- Settings settings;
-
- settings.builddir = "build";
+public:
+ Args(const std::vector<std::string>& args)
+ {
+ resize(args.size() + 1);
+ (*this)[0] = strdup("./ctor");
+ for(std::size_t i = 0; i < size() - 1; ++i)
+ {
+ (*this)[i + 1] = strdup(args[i].data());
+ }
+ }
- std::string cmd_str;
- for(int i = 0; i < argc; ++i)
+ ~Args()
{
- if(i > 0)
+ for(std::size_t i = 0; i < size(); ++i)
{
- cmd_str += " ";
+ free((*this)[i]);
}
- cmd_str += argv[i];
}
+};
+
+// helper constant for the visitor
+template<class> inline constexpr bool always_false_v = false;
+
+int regenerateCache(const Settings& default_settings,
+ const std::vector<std::string>& args,
+ const std::map<std::string, std::string>& env)
+{
+ Settings settings{default_settings};
+ Args vargs(args);
dg::Options opt;
int key{128};
@@ -119,6 +167,8 @@ int configure(int argc, char* argv[])
std::string cxx_prog = "g++";
std::string ar_prog = "ar";
std::string ld_prog = "ld";
+ std::string ctor_includedir;
+ std::string ctor_libdir;
opt.add("build-dir", required_argument, 'b',
"Set output directory for build files (default: '" +
@@ -191,6 +241,65 @@ int configure(int argc, char* argv[])
return 0;
});
+ opt.add("ctor-includedir", required_argument, key++,
+ "Set path to ctor header file, used for re-compiling.",
+ [&]() {
+ ctor_includedir = optarg;
+ return 0;
+ });
+
+ opt.add("ctor-libdir", required_argument, key++,
+ "Set path to ctor library file, used for re-compiling.",
+ [&]() {
+ ctor_libdir = optarg;
+ return 0;
+ });
+
+ // Resolv externals
+ ExternalConfigurations externalConfigs;
+ for(std::size_t i = 0; i < numExternalConfigFiles; ++i)
+ {
+ auto newExternalConfigs = externalConfigFiles[i].cb(settings);
+ externalConfigs.insert(externalConfigs.end(),
+ newExternalConfigs.begin(),
+ newExternalConfigs.end());
+ }
+
+ auto add_path_args =
+ [&](const std::string& name)
+ {
+ opt.add(name + "-includedir", required_argument, key++,
+ "Set path to " + name + " header file.",
+ [&]() {
+ external_includedir[name] = optarg;
+ return 0;
+ });
+
+ opt.add(name + "-libdir", required_argument, key++,
+ "Set path to " + name + " libraries.",
+ [&]() {
+ external_libdir[name] = optarg;
+ return 0;
+ });
+ };
+
+ for(const auto& ext : externalConfigs)
+ {
+ std::visit([&](auto&& arg)
+ {
+ using T = std::decay_t<decltype(arg)>;
+ if constexpr (std::is_same_v<T, ExternalManual>)
+ {
+ add_path_args(ext.name);
+ }
+ else
+ {
+ static_assert(always_false_v<T>, "non-exhaustive visitor!");
+ }
+ }, ext.external);
+
+ }
+
opt.add("help", no_argument, 'h',
"Print this help text.",
[&]() {
@@ -200,14 +309,14 @@ int configure(int argc, char* argv[])
return 0;
});
- opt.process(argc, argv);
+ opt.process(vargs.size(), vargs.data());
if(host_arch.empty())
{
host_arch = build_arch;
}
- auto tasks = getTasks(settings);
+ auto tasks = getTasks(settings, {}, false);
/*
bool needs_cpp{false};
bool needs_c{false};
@@ -233,32 +342,29 @@ int configure(int argc, char* argv[])
}
}
*/
- auto cc_env = getenv("CC");
- if(cc_env)
+
+ auto cc_env = env.find("CC");
+ if(cc_env != env.end())
{
- cmd_str = std::string("CC=") + cc_env + " " + cmd_str;
- cc_prog = cc_env;
+ cc_prog = cc_env->second;
}
- auto cxx_env = getenv("CXX");
- if(cxx_env)
+ auto cxx_env = env.find("CXX");
+ if(cxx_env != env.end())
{
- cmd_str = std::string("CXX=") + cxx_env + " " + cmd_str;
- cxx_prog = cxx_env;
+ cxx_prog = cxx_env->second;
}
- auto ar_env = getenv("AR");
- if(ar_env)
+ auto ar_env = env.find("AR");
+ if(ar_env != env.end())
{
- cmd_str = std::string("AR=") + ar_env + " " + cmd_str;
- ar_prog = ar_env;
+ ar_prog = ar_env->second;
}
- auto ld_env = getenv("LD");
- if(ld_env)
+ auto ld_env = env.find("LD");
+ if(ld_env != env.end())
{
- cmd_str = std::string("LD=") + ld_env + " " + cmd_str;
- ld_prog = ld_env;
+ ld_prog = ld_env->second;
}
std::string host_cc = locate(host_arch, cc_prog);
@@ -273,24 +379,113 @@ int configure(int argc, char* argv[])
std::cout << "Writing results to: " << configurationFile.string() << "\n";
{
std::ofstream istr(configurationFile);
- istr << "#include \"libctor.h\"\n\n";
- istr << "const std::map<std::string, std::string>& configuration()\n";
+ istr << "#include <libctor.h>\n\n";
+ istr << "const Configuration& configuration()\n";
istr << "{\n";
- istr << " static std::map<std::string, std::string> c =\n";
+ istr << " static Configuration cfg =\n";
istr << " {\n";
- istr << " { \"cmd\", \"" << cmd_str << "\" },\n";
- istr << " { \"" << cfg::builddir << "\", \"" << settings.builddir << "\" },\n";
- istr << " { \"" << cfg::host_cc << "\", \"" << host_cc << "\" },\n";
- istr << " { \"" << cfg::host_cxx << "\", \"" << host_cxx << "\" },\n";
- istr << " { \"" << cfg::host_ar << "\", \"" << host_ar << "\" },\n";
- istr << " { \"" << cfg::host_ld << "\", \"" << host_ld << "\" },\n";
- istr << " { \"" << cfg::build_cc << "\", \"" << build_cc << "\" },\n";
- istr << " { \"" << cfg::build_cxx << "\", \"" << build_cxx << "\" },\n";
- istr << " { \"" << cfg::build_ar << "\", \"" << build_ar << "\" },\n";
- istr << " { \"" << cfg::build_ld << "\", \"" << build_ld << "\" },\n";
+ istr << " .args = {";
+ for(const auto& arg : args)
+ {
+ istr << "\"" << arg << "\",";
+ }
+ istr << "},\n";
+ istr << " .env = {";
+ for(const auto& e : env)
+ {
+ istr << "{\"" << e.first << "\", \"" << e.second << "\"}, ";
+ }
+ istr << "},\n";
+
+ istr << " .tools = {\n";
+ istr << " { \"" << cfg::builddir << "\", \"" << settings.builddir << "\" },\n";
+ istr << " { \"" << cfg::host_cc << "\", \"" << host_cc << "\" },\n";
+ istr << " { \"" << cfg::host_cxx << "\", \"" << host_cxx << "\" },\n";
+ istr << " { \"" << cfg::host_ar << "\", \"" << host_ar << "\" },\n";
+ istr << " { \"" << cfg::host_ld << "\", \"" << host_ld << "\" },\n";
+ istr << " { \"" << cfg::build_cc << "\", \"" << build_cc << "\" },\n";
+ istr << " { \"" << cfg::build_cxx << "\", \"" << build_cxx << "\" },\n";
+ istr << " { \"" << cfg::build_ar << "\", \"" << build_ar << "\" },\n";
+ istr << " { \"" << cfg::build_ld << "\", \"" << build_ld << "\" },\n";
+ if(!ctor_includedir.empty())
+ {
+ istr << " { \"" << cfg::ctor_includedir << "\", \"" << ctor_includedir << "\" },\n";
+ ctor::includedir = ctor_includedir;
+ }
+ if(!ctor_libdir.empty())
+ {
+ istr << " { \"" << cfg::ctor_libdir << "\", \"" << ctor_libdir << "\" },\n";
+ ctor::libdir = ctor_libdir;
+ }
+
+ istr << " },\n";
+ istr << " .externals = {\n";
+
+ for(const auto& ext : externalConfigs)
+ {
+ istr << " { \"" << ext.name << "\", {\n";
+ Flags resolved_flags;
+ if(std::holds_alternative<ExternalManual>(ext.external))
+ {
+ if(auto ret = resolv(settings, ext,
+ std::get<ExternalManual>(ext.external),
+ resolved_flags))
+ {
+ return ret;
+ }
+ }
+ else
+ {
+ std::cout << "Unknown external type\n";
+ return 1;
+ }
+
+ if(!resolved_flags.cxxflags.empty())
+ {
+ istr << " .cxxflags = {";
+ for(const auto& flag : resolved_flags.cxxflags)
+ {
+ istr << "\"" << flag << "\",";
+ }
+ istr << "},\n";
+ }
+
+ if(!resolved_flags.cflags.empty())
+ {
+ istr << " .cflags = {";
+ for(const auto& flag : resolved_flags.cflags)
+ {
+ istr << "\"" << flag << "\",";
+ }
+ istr << "},\n";
+ }
+
+ if(!resolved_flags.ldflags.empty())
+ {
+ istr << " .ldflags = {";
+ for(const auto& flag : resolved_flags.ldflags)
+ {
+ istr << "\"" << flag << "\",";
+ }
+ istr << "},\n";
+ }
+
+ if(!resolved_flags.asmflags.empty())
+ {
+ istr << " .asmflags = {";
+ for(const auto& flag : resolved_flags.asmflags)
+ {
+ istr << "\"" << flag << "\",";
+ }
+ istr << "},\n";
+ }
+ istr << " }},\n";
+ }
+
+ istr << " },\n";
istr << " };\n";
- istr << " return c;\n";
- istr << "}\n";
+ istr << " return cfg;\n";
+ istr << "}\n\n";
}
{
@@ -302,3 +497,94 @@ int configure(int argc, char* argv[])
return 0;
}
+
+int configure(const Settings& global_settings, int argc, char* argv[])
+{
+ Settings settings{global_settings};
+
+ std::vector<std::string> args;
+ for(int i = 2; i < argc; ++i) // skip command and the first 'configure' arg
+ {
+ args.push_back(argv[i]);
+ }
+
+ std::map<std::string, std::string> env;
+ auto cc_env = getenv("CC");
+ if(cc_env)
+ {
+ env["CC"] = cc_env;
+ }
+
+ auto cxx_env = getenv("CXX");
+ if(cxx_env)
+ {
+ env["CXX"] = cxx_env;
+ }
+
+ auto ar_env = getenv("AR");
+ if(ar_env)
+ {
+ env["AR"] = ar_env;
+ }
+
+ auto ld_env = getenv("LD");
+ if(ld_env)
+ {
+ env["LD"] = ld_env;
+ }
+
+ auto ret = regenerateCache(settings, args, env);
+ if(ret != 0)
+ {
+ return ret;
+ }
+
+ recompileCheck(settings, argc, argv, false);
+
+ return 0;
+}
+
+int reconfigure(const Settings& settings, int argc, char* argv[])
+{
+ bool no_rerun{false};
+
+ std::vector<std::string> args;
+ for(int i = 2; i < argc; ++i) // skip executable name and 'reconfigure' arg
+ {
+ if(i == 2 && std::string(argv[i]) == "--no-rerun")
+ {
+ no_rerun = true;
+ continue;
+ }
+ args.push_back(argv[i]);
+ }
+
+ const auto& cfg = configuration();
+
+ std::cout << "Re-running configure:\n";
+ for(const auto& e : cfg.env)
+ {
+ std::cout << e.first << "=\"" << e.second << "\" ";
+ }
+ std::cout << argv[0] << " configure ";
+ for(const auto& arg : cfg.args)
+ {
+ std::cout << arg << " ";
+ }
+ std::cout << "\n";
+
+ auto ret = regenerateCache(settings, cfg.args, cfg.env);
+ if(ret != 0)
+ {
+ return ret;
+ }
+
+ recompileCheck(settings, 1, argv, false);
+
+ if(no_rerun)
+ {
+ return 0; // this was originally invoked by configure, don't loop
+ }
+
+ return execute(argv[0], args);
+}