diff options
Diffstat (limited to 'src/configure.cc')
-rw-r--r-- | src/configure.cc | 300 |
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) |