summaryrefslogtreecommitdiff
path: root/src/configure.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/configure.cc')
-rw-r--r--src/configure.cc215
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, {});
}