diff options
Diffstat (limited to 'src/configure.cc')
-rw-r--r-- | src/configure.cc | 215 |
1 files changed, 189 insertions, 26 deletions
diff --git a/src/configure.cc b/src/configure.cc index a81f8ad..bb94202 100644 --- a/src/configure.cc +++ b/src/configure.cc @@ -23,15 +23,73 @@ std::map<std::string, std::string> external_includedir; std::map<std::string, std::string> external_libdir; const Configuration default_configuration{}; +#if !defined(_WIN32) const Configuration& __attribute__((weak)) configuration() { return default_configuration; } +#else +//extern const char * pWeakValue; +//extern const char * pDefaultWeakValue = NULL; +// +//#pragma comment(linker, "/alternatename:_pWeakValue=_pDefaultWeakValue") +const Configuration& defConfiguration() +{ + return default_configuration; +} +#pragma comment(linker, "/alternatename:?configuration@@YAABUConfiguration@@XZ=?defConfiguration@@YAABUConfiguration@@XZ") +//https://stackoverflow.com/questions/2290587/gcc-style-weak-linking-in-visual-studio +//https://devblogs.microsoft.com/oldnewthing/20200731-00/?p=104024 + +//extern "C" +//{ +//void default_error_log() { /* do nothing */ } +//} +//// For expository simplification: assume x86 cdecl +//#pragma comment(linker, "/alternatename:_error_log=_default_error_log") + + +#endif + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#endif + +void _copyAndRelaunch(int argc, char* argv[], + const std::string& copy_src, + const std::string& copy_tar, + const std::string& compilation_name) +{ +#ifdef _WIN32 + CopyFile(copy_src.data(), copy_tar.data(), false); + SetFileAttributes(copy_tar.data(), FILE_ATTRIBUTE_HIDDEN); + auto t = std::filesystem::last_write_time(copy_src); + std::filesystem::last_write_time(copy_tar, t); + + STARTUPINFO si{}; + PROCESS_INFORMATION pi{}; + si.cb = sizeof(pi); + + std::string args = copy_tar + " configure"; + for(int i = 1; i < argc; ++i) + { + args += " "; + args += argv[i]; + } + args += " --name "; + args += compilation_name; + + CreateProcess(nullptr, args.data(), 0,0,0,0,0,0,&si,&pi); + exit(1); +#endif // _WIN32 +} namespace ctor { std::optional<std::string> includedir; std::optional<std::string> libdir; +std::map<std::string, std::string> conf_values; } bool hasConfiguration(const std::string& key) @@ -46,6 +104,11 @@ bool hasConfiguration(const std::string& key) return true; } + if(ctor::conf_values.find(key) != ctor::conf_values.end()) + { + return true; + } + const auto& c = configuration(); return c.tools.find(key) != c.tools.end(); } @@ -63,6 +126,11 @@ const std::string& getConfiguration(const std::string& key, return *ctor::libdir; } + if(ctor::conf_values.find(key) != ctor::conf_values.end()) + { + return ctor::conf_values[key]; + } + const auto& c = configuration(); if(hasConfiguration(key)) { @@ -88,11 +156,24 @@ std::string locate(const std::string& arch, const std::string& app) { std::stringstream ss(path_env); std::string path; - while (std::getline(ss, path, ':')) + while (std::getline(ss, path, ';')) { paths.push_back(path); } } + { + const auto& cfg = configuration(); + auto it = cfg.env.find("ctorPATH"); + if(it != cfg.env.end()) + { + std::stringstream ss(it->second); + std::string path; + while (std::getline(ss, path, ';')) + { + paths.push_back(path); + } + } + } for(const auto& path_str : paths) { std::filesystem::path path(path_str); @@ -127,10 +208,10 @@ class Args : public std::vector<char*> { public: - Args(const std::vector<std::string>& args) + Args(const std::string& name, const std::vector<std::string>& args) { resize(args.size() + 1); - (*this)[0] = strdup("./ctor"); + (*this)[0] = strdup(name.data()); for(std::size_t i = 0; i < size() - 1; ++i) { (*this)[i + 1] = strdup(args[i].data()); @@ -146,15 +227,32 @@ public: } }; +std::string esc(const std::string& in) +{ + std::string out; + for(auto c : in) + { + switch(c) + { + case '\\': out += "\\\\"; break; + case '"': out += "\\\""; break; + default: + out += c; + break; + } + } + return out; +} + // helper constant for the visitor template<class> inline constexpr bool always_false_v = false; -int regenerateCache(const Settings& default_settings, +int regenerateCache(Settings& settings, + const std::string& name, const std::vector<std::string>& args, const std::map<std::string, std::string>& env) { - Settings settings{default_settings}; - Args vargs(args); + Args vargs(name, args); dg::Options opt; int key{128}; @@ -185,6 +283,13 @@ int regenerateCache(const Settings& default_settings, return 0; }); + opt.add("name", required_argument, 'n', + "Set the output name of the ctor command to override the current one.", + [&]() { + settings.name = optarg; + return 0; + }); + opt.add("cc", required_argument, key++, "Use specified c-compiler instead of gcc.", [&]() { @@ -311,6 +416,24 @@ int regenerateCache(const Settings& default_settings, opt.process(vargs.size(), vargs.data()); + std::filesystem::path settings_file(settings.name); + std::filesystem::path argv0_file(vargs[0]); + + if(settings_file.is_relative()) + { + settings_file = std::filesystem::current_path() / settings_file; + } + if(argv0_file.is_relative()) + { + argv0_file = std::filesystem::current_path() / argv0_file; + } + + if(settings_file.string() == argv0_file.string()) + { + _copyAndRelaunch(vargs.size(), vargs.data(), vargs[0], "ctor-configure-tmp.exe", settings.name); + exit(0); + } + if(host_arch.empty()) { host_arch = build_arch; @@ -376,6 +499,20 @@ int regenerateCache(const Settings& default_settings, std::string build_ar = locate(build_arch, ar_prog); std::string build_ld = locate(build_arch, ld_prog); + // Store current values for execution in this execution context. + if(!ctor_includedir.empty()) + { + ctor::conf_values[cfg::ctor_includedir] = ctor_includedir; + } + if(!ctor_libdir.empty()) + { + ctor::conf_values[cfg::ctor_libdir] = ctor_libdir; + } + ctor::conf_values[cfg::host_cxx] = host_cxx; + ctor::conf_values[cfg::build_cxx] = build_cxx; + ctor::conf_values[cfg::host_ld] = host_ld; + ctor::conf_values[cfg::build_ld] = build_ld; + std::cout << "Writing results to: " << configurationFile.string() << "\n"; { std::ofstream istr(configurationFile); @@ -387,34 +524,34 @@ int regenerateCache(const Settings& default_settings, istr << " .args = {"; for(const auto& arg : args) { - istr << "\"" << arg << "\","; + istr << "\"" << esc(arg) << "\","; } istr << "},\n"; - istr << " .env = {"; + istr << " .env = {\n"; for(const auto& e : env) { - istr << "{\"" << e.first << "\", \"" << e.second << "\"}, "; + istr << " {\"" << e.first << "\", \"" << esc(e.second) << "\"},\n"; } - istr << "},\n"; + 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"; + istr << " { \"" << cfg::builddir << "\", \"" << esc(settings.builddir) << "\" },\n"; + istr << " { \"" << cfg::host_cc << "\", \"" << esc(host_cc) << "\" },\n"; + istr << " { \"" << cfg::host_cxx << "\", \"" << esc(host_cxx) << "\" },\n"; + istr << " { \"" << cfg::host_ar << "\", \"" << esc(host_ar) << "\" },\n"; + istr << " { \"" << cfg::host_ld << "\", \"" << esc(host_ld) << "\" },\n"; + istr << " { \"" << cfg::build_cc << "\", \"" << esc(build_cc) << "\" },\n"; + istr << " { \"" << cfg::build_cxx << "\", \"" << esc(build_cxx) << "\" },\n"; + istr << " { \"" << cfg::build_ar << "\", \"" << esc(build_ar) << "\" },\n"; + istr << " { \"" << cfg::build_ld << "\", \"" << esc(build_ld) << "\" },\n"; if(!ctor_includedir.empty()) { - istr << " { \"" << cfg::ctor_includedir << "\", \"" << ctor_includedir << "\" },\n"; + istr << " { \"" << cfg::ctor_includedir << "\", \"" << esc(ctor_includedir) << "\" },\n"; ctor::includedir = ctor_includedir; } if(!ctor_libdir.empty()) { - istr << " { \"" << cfg::ctor_libdir << "\", \"" << ctor_libdir << "\" },\n"; + istr << " { \"" << cfg::ctor_libdir << "\", \"" << esc(ctor_libdir) << "\" },\n"; ctor::libdir = ctor_libdir; } @@ -508,7 +645,7 @@ int configure(const Settings& global_settings, int argc, char* argv[]) args.push_back(argv[i]); } - std::map<std::string, std::string> env; + auto env = configuration().env; auto cc_env = getenv("CC"); if(cc_env) { @@ -533,7 +670,32 @@ int configure(const Settings& global_settings, int argc, char* argv[]) env["LD"] = ld_env; } - auto ret = regenerateCache(settings, args, env); + // Env vars for msvc + auto cl_env = getenv("CL"); + if(cl_env) + { + env["CL"] = cl_env; + } + + auto lib_env = getenv("LIB"); + if(lib_env) + { + env["LIB"] = lib_env; + } + + auto link_env = getenv("LINK"); + if(link_env) + { + env["LINK"] = link_env; + } + + auto path_env = getenv("PATH"); + if(path_env) + { + env["ctorPATH"] = path_env; + } + + auto ret = regenerateCache(settings, argv[0], args, env); if(ret != 0) { return ret; @@ -544,8 +706,9 @@ int configure(const Settings& global_settings, int argc, char* argv[]) return 0; } -int reconfigure(const Settings& settings, int argc, char* argv[]) +int reconfigure(const Settings& global_settings, int argc, char* argv[]) { + Settings settings{global_settings}; bool no_rerun{false}; std::vector<std::string> args; @@ -573,7 +736,7 @@ int reconfigure(const Settings& settings, int argc, char* argv[]) } std::cout << "\n"; - auto ret = regenerateCache(settings, cfg.args, cfg.env); + auto ret = regenerateCache(settings, argv[0], cfg.args, cfg.env); if(ret != 0) { return ret; @@ -586,5 +749,5 @@ int reconfigure(const Settings& settings, int argc, char* argv[]) return 0; // this was originally invoked by configure, don't loop } - return execute(argv[0], args); + return execute(argv[0], args, {}); } |