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