summaryrefslogtreecommitdiff
path: root/src/configure.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/configure.cc')
-rw-r--r--src/configure.cc300
1 files changed, 235 insertions, 65 deletions
diff --git a/src/configure.cc b/src/configure.cc
index 4df6026..8e88092 100644
--- a/src/configure.cc
+++ b/src/configure.cc
@@ -10,63 +10,91 @@
#include <getoptpp/getoptpp.hpp>
-#include "settings.h"
#include "execute.h"
-#include "libctor.h"
+#include "ctor.h"
#include "tasks.h"
#include "rebuild.h"
+#include "externals.h"
+#include "tools.h"
std::filesystem::path configurationFile("configuration.cc");
std::filesystem::path configHeaderFile("config.h");
-const Configuration default_configuration{};
-const Configuration& __attribute__((weak)) configuration()
+std::map<std::string, std::string> external_includedir;
+std::map<std::string, std::string> external_libdir;
+
+const ctor::configuration& __attribute__((weak)) ctor::get_configuration()
{
- return default_configuration;
+ static ctor::configuration cfg;
+ static bool initialised{false};
+ if(!initialised)
+ {
+ cfg.host_toolchain = getToolChain(cfg.get(ctor::cfg::host_cxx, "g++"));
+ initialised = true;
+ }
+ return cfg;
}
-namespace ctor
-{
+namespace ctor {
std::optional<std::string> includedir;
std::optional<std::string> libdir;
-}
+std::optional<std::string> builddir;
+std::map<std::string, std::string> conf_values;
+} // ctor::
-bool hasConfiguration(const std::string& key)
+bool ctor::configuration::has(const std::string& key) const
{
- if(key == cfg::ctor_includedir && ctor::includedir)
+ if(key == ctor::cfg::ctor_includedir && ctor::includedir)
{
return true;
}
- if(key == cfg::ctor_libdir && ctor::libdir)
+ if(key == ctor::cfg::ctor_libdir && ctor::libdir)
{
return true;
}
- const auto& c = configuration();
- return c.tools.find(key) != c.tools.end();
+ if(key == ctor::cfg::builddir && ctor::builddir)
+ {
+ return true;
+ }
+
+ if(ctor::conf_values.find(key) != ctor::conf_values.end())
+ {
+ return true;
+ }
+
+ return tools.find(key) != tools.end();
}
-const std::string& getConfiguration(const std::string& key,
- const std::string& defaultValue)
+const std::string& ctor::configuration::get(const std::string& key, const std::string& default_value) const
{
- if(key == cfg::ctor_includedir && ctor::includedir)
+ if(key == ctor::cfg::ctor_includedir && ctor::includedir)
{
return *ctor::includedir;
}
- if(key == cfg::ctor_libdir && ctor::libdir)
+ if(key == ctor::cfg::ctor_libdir && ctor::libdir)
{
return *ctor::libdir;
}
- const auto& c = configuration();
- if(hasConfiguration(key))
+ if(key == ctor::cfg::builddir && ctor::builddir)
+ {
+ return *ctor::builddir;
+ }
+
+ if(ctor::conf_values.find(key) != ctor::conf_values.end())
{
- return c.tools.at(key);
+ return ctor::conf_values[key];
}
- return defaultValue;
+ if(has(key))
+ {
+ return tools.at(key);
+ }
+
+ return default_value;
}
std::string locate(const std::string& arch, const std::string& app)
@@ -143,11 +171,71 @@ public:
}
};
-int regenerateCache(const Settings& default_settings,
+namespace {
+std::ostream& operator<<(std::ostream& stream, const ctor::toolchain& toolchain)
+{
+ switch(toolchain)
+ {
+ case ctor::toolchain::any:
+ stream << "ctor::toolchain::any";
+ break;
+ case ctor::toolchain::none:
+ stream << "ctor::toolchain::none";
+ break;
+ case ctor::toolchain::gcc:
+ stream << "ctor::toolchain::gcc";
+ break;
+ case ctor::toolchain::clang:
+ stream << "ctor::toolchain::clang";
+ break;
+ }
+ return stream;
+}
+
+std::ostream& operator<<(std::ostream& ostr, const ctor::c_flag& flag)
+{
+ for(const auto& s : to_strings(ctor::toolchain::any, flag))
+ {
+ ostr << s;
+ }
+ return ostr;
+}
+
+std::ostream& operator<<(std::ostream& ostr, const ctor::cxx_flag& flag)
+{
+ for(const auto& s : to_strings(ctor::toolchain::any, flag))
+ {
+ ostr << s;
+ }
+ return ostr;
+}
+
+std::ostream& operator<<(std::ostream& ostr, const ctor::ld_flag& flag)
+{
+ for(const auto& s : to_strings(ctor::toolchain::any, flag))
+ {
+ ostr << s;
+ }
+ return ostr;
+}
+
+std::ostream& operator<<(std::ostream& ostr, const ctor::asm_flag& flag)
+{
+ for(const auto& s : to_strings(ctor::toolchain::any, flag))
+ {
+ ostr << s;
+ }
+ return ostr;
+}
+}
+
+// helper constant for the visitor
+template<class> inline constexpr bool always_false_v = false;
+
+int regenerateCache(ctor::settings& 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;
@@ -163,12 +251,14 @@ int regenerateCache(const Settings& default_settings,
std::string ld_prog = "ld";
std::string ctor_includedir;
std::string ctor_libdir;
+ std::string builddir;
opt.add("build-dir", required_argument, 'b',
"Set output directory for build files (default: '" +
settings.builddir + "').",
[&]() {
settings.builddir = optarg;
+ builddir = optarg;
return 0;
});
@@ -249,6 +339,51 @@ int regenerateCache(const Settings& default_settings,
return 0;
});
+ // Resolv externals
+ ctor::external_configurations 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, ctor::external_manual>)
+ {
+ 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.",
[&]() {
@@ -325,24 +460,38 @@ int regenerateCache(const Settings& default_settings,
std::string build_ar = locate(build_arch, ar_prog);
std::string build_ld = locate(build_arch, ld_prog);
- // Resolv externals
- ExternalConfigurations externalConfigs;
- for(std::size_t i = 0; i < numExternalConfigFiles; ++i)
+ if(!host_cxx.empty())
{
- auto newExternalConfigs = externalConfigFiles[i].cb();
- externalConfigs.insert(externalConfigs.end(),
- newExternalConfigs.begin(),
- newExternalConfigs.end());
+ // This is needed for bootstrapping (when running configure for the first time)
+ ctor::conf_values[ctor::cfg::host_cxx] = host_cxx;
}
+ // Store current values for execution in this execution context.
+ if(!ctor_includedir.empty())
+ {
+ ctor::conf_values[ctor::cfg::ctor_includedir] = ctor_includedir;
+ }
+ if(!ctor_libdir.empty())
+ {
+ ctor::conf_values[ctor::cfg::ctor_libdir] = ctor_libdir;
+ }
+ if(!builddir.empty())
+ {
+ ctor::conf_values[ctor::cfg::builddir] = builddir;
+ }
+ ctor::conf_values[ctor::cfg::host_cxx] = host_cxx;
+ ctor::conf_values[ctor::cfg::build_cxx] = build_cxx;
+
std::cout << "Writing results to: " << configurationFile.string() << "\n";
{
std::ofstream istr(configurationFile);
- istr << "#include <libctor.h>\n\n";
- istr << "const Configuration& configuration()\n";
+ istr << "#include <ctor.h>\n\n";
+ istr << "const ctor::configuration& ctor::get_configuration()\n";
istr << "{\n";
- istr << " static Configuration cfg =\n";
+ istr << " static ctor::configuration cfg =\n";
istr << " {\n";
+ istr << " .host_toolchain = " << getToolChain(host_cxx) << ",\n";
+ istr << " .build_toolchain = " << getToolChain(build_cxx) << ",\n";
istr << " .args = {";
for(const auto& arg : args)
{
@@ -357,69 +506,88 @@ int regenerateCache(const Settings& default_settings,
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(!builddir.empty())
+ {
+ istr << " { \"" << ctor::cfg::builddir << "\", \"" << builddir << "\" },\n";
+ ctor::builddir = builddir;
+ }
+ istr << " { \"" << ctor::cfg::host_cc << "\", \"" << host_cc << "\" },\n";
+ istr << " { \"" << ctor::cfg::host_cxx << "\", \"" << host_cxx << "\" },\n";
+ istr << " { \"" << ctor::cfg::host_ar << "\", \"" << host_ar << "\" },\n";
+ istr << " { \"" << ctor::cfg::host_ld << "\", \"" << host_ld << "\" },\n";
+ istr << " { \"" << ctor::cfg::build_cc << "\", \"" << build_cc << "\" },\n";
+ istr << " { \"" << ctor::cfg::build_cxx << "\", \"" << build_cxx << "\" },\n";
+ istr << " { \"" << ctor::cfg::build_ar << "\", \"" << build_ar << "\" },\n";
+ istr << " { \"" << ctor::cfg::build_ld << "\", \"" << build_ld << "\" },\n";
if(!ctor_includedir.empty())
{
- istr << " { \"" << cfg::ctor_includedir << "\", \"" << ctor_includedir << "\" },\n";
+ istr << " { \"" << ctor::cfg::ctor_includedir << "\", \"" << ctor_includedir << "\" },\n";
ctor::includedir = ctor_includedir;
}
if(!ctor_libdir.empty())
{
- istr << " { \"" << cfg::ctor_libdir << "\", \"" << ctor_libdir << "\" },\n";
+ istr << " { \"" << ctor::cfg::ctor_libdir << "\", \"" << ctor_libdir << "\" },\n";
ctor::libdir = ctor_libdir;
}
istr << " },\n";
istr << " .externals = {\n";
- for(const auto& externalConfig : externalConfigs)
+ for(const auto& ext : externalConfigs)
{
- istr << " { \"" << externalConfig.name << "\", {\n";
+ istr << " { \"" << ext.name << "\", {\n";
+ ctor::flags resolved_flags;
+ if(std::holds_alternative<ctor::external_manual>(ext.external))
+ {
+ if(auto ret = resolv(settings, ext,
+ std::get<ctor::external_manual>(ext.external),
+ resolved_flags))
+ {
+ return ret;
+ }
+ }
+ else
+ {
+ std::cout << "Unknown external type\n";
+ return 1;
+ }
- if(!externalConfig.flags.cxxflags.empty())
+ if(!resolved_flags.cflags.empty())
{
- istr << " .cxxflags = {";
- for(const auto& flag : externalConfig.flags.cxxflags)
+ istr << " .cflags = {";
+ for(const auto& flag : resolved_flags.cflags)
{
- istr << "\"" << flag << "\",";
+ istr << flag << ",";
}
istr << "},\n";
}
- if(!externalConfig.flags.cflags.empty())
+ if(!resolved_flags.cxxflags.empty())
{
- istr << " .cflags = {";
- for(const auto& flag : externalConfig.flags.cflags)
+ istr << " .cxxflags = {";
+ for(const auto& flag : resolved_flags.cxxflags)
{
- istr << "\"" << flag << "\",";
+ istr << flag << ",";
}
istr << "},\n";
}
- if(!externalConfig.flags.ldflags.empty())
+ if(!resolved_flags.ldflags.empty())
{
istr << " .ldflags = {";
- for(const auto& flag : externalConfig.flags.ldflags)
+ for(const auto& flag : resolved_flags.ldflags)
{
- istr << "\"" << flag << "\",";
+ istr << flag << ",";
}
istr << "},\n";
}
- if(!externalConfig.flags.asmflags.empty())
+ if(!resolved_flags.asmflags.empty())
{
istr << " .asmflags = {";
- for(const auto& flag : externalConfig.flags.asmflags)
+ for(const auto& flag : resolved_flags.asmflags)
{
- istr << "\"" << flag << "\",";
+ istr << flag << ",";
}
istr << "},\n";
}
@@ -429,7 +597,7 @@ int regenerateCache(const Settings& default_settings,
istr << " },\n";
istr << " };\n";
istr << " return cfg;\n";
- istr << "}\n\n";
+ istr << "}\n";
}
{
@@ -442,9 +610,9 @@ int regenerateCache(const Settings& default_settings,
return 0;
}
-int configure(const Settings& global_settings, int argc, char* argv[])
+int configure(const ctor::settings& global_settings, int argc, char* argv[])
{
- Settings settings{global_settings};
+ ctor::settings settings{global_settings};
std::vector<std::string> args;
for(int i = 2; i < argc; ++i) // skip command and the first 'configure' arg
@@ -488,8 +656,10 @@ int configure(const Settings& global_settings, int argc, char* argv[])
return 0;
}
-int reconfigure(const Settings& settings, int argc, char* argv[])
+int reconfigure(const ctor::settings& global_settings, int argc, char* argv[])
{
+ ctor::settings settings{global_settings};
+
bool no_rerun{false};
std::vector<std::string> args;
@@ -503,7 +673,7 @@ int reconfigure(const Settings& settings, int argc, char* argv[])
args.push_back(argv[i]);
}
- const auto& cfg = configuration();
+ const auto& cfg = ctor::get_configuration();
std::cout << "Re-running configure:\n";
for(const auto& e : cfg.env)