summaryrefslogtreecommitdiff
path: root/src/configure.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/configure.cc')
-rw-r--r--src/configure.cc929
1 files changed, 683 insertions, 246 deletions
diff --git a/src/configure.cc b/src/configure.cc
index bc7d3e8..910b878 100644
--- a/src/configure.cc
+++ b/src/configure.cc
@@ -7,119 +7,137 @@
#include <filesystem>
#include <fstream>
#include <optional>
-
-#include <getoptpp/getoptpp.hpp>
+#include <span>
+#include <cstring>
#include "execute.h"
-#include "libctor.h"
+#include "ctor.h"
#include "tasks.h"
#include "rebuild.h"
#include "externals.h"
+#include "tools.h"
+#include "util.h"
+#include "argparser.h"
-std::filesystem::path configurationFile("configuration.cc");
-std::filesystem::path configHeaderFile("config.h");
+const std::filesystem::path configurationFile("configuration.cc");
+const std::filesystem::path configHeaderFile("config.h");
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()
+const ctor::configuration& __attribute__((weak)) ctor::get_configuration()
{
- return default_configuration;
+ static ctor::configuration cfg;
+ static bool initialised{false};
+ if(!initialised)
+ {
+ std::string cxx_prog{"c++"};
+ get_env("CXX", cxx_prog);
+
+ cfg.build_toolchain = getToolChain(cfg.get(ctor::cfg::build_cxx, cxx_prog));
+
+ 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 == ctor::cfg::ctor_libdir && ctor::libdir)
+ {
+ return true;
+ }
+
+ if(key == ctor::cfg::builddir && ctor::builddir)
{
return true;
}
- if(key == cfg::ctor_libdir && ctor::libdir)
+ if(ctor::conf_values.find(key) != ctor::conf_values.end())
{
return true;
}
- const auto& c = configuration();
- return c.tools.find(key) != c.tools.end();
+ return tools.find(key) != tools.end();
}
-const std::string& getConfiguration(const std::string& key,
- const std::string& defaultValue)
+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 c.tools.at(key);
+ return *ctor::builddir;
}
- return defaultValue;
-}
+ if(ctor::conf_values.find(key) != ctor::conf_values.end())
+ {
+ return ctor::conf_values[key];
+ }
-std::string locate(const std::string& arch, const std::string& app)
-{
- std::string path_env = std::getenv("PATH");
- //std::cout << path_env << "\n";
+ if(tools.find(key) != tools.end())
+ {
+ return tools.at(key);
+ }
- std::string program = app;
- if(!arch.empty())
+ std::string value;
+ if(key == ctor::cfg::build_cxx && get_env("CXX", value))
{
- program = arch + "-" + app;
+ return value;
}
- std::cout << "Looking for: " << program << "\n";
- std::vector<std::string> paths;
+ if(key == ctor::cfg::build_cc && get_env("CC", value))
{
- std::stringstream ss(path_env);
- std::string path;
- while (std::getline(ss, path, ':'))
- {
- paths.push_back(path);
- }
+ return value;
}
- for(const auto& path_str : paths)
+
+ if(key == ctor::cfg::build_ld && get_env("LD", value))
{
- std::filesystem::path path(path_str);
- auto prog_path = path / program;
- if(std::filesystem::exists(prog_path))
- {
- std::cout << "Found file " << app << " in path: " << path << "\n";
- 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";
- }
- if((perms & std::filesystem::perms::group_exec) != std::filesystem::perms::none)
- {
- //std::cout << " - executable by group\n";
- }
- if((perms & std::filesystem::perms::others_exec) != std::filesystem::perms::none)
- {
- //std::cout << " - executable by others\n";
- }
+ return value;
+ }
- return prog_path.string();
- }
+ if(key == ctor::cfg::build_ar && get_env("AR", value))
+ {
+ return value;
+ }
+
+ return default_value;
+}
+
+std::string ctor::configuration::getenv(const std::string& key) const
+{
+ auto envit = env.find(key);
+ if(envit != env.end())
+ {
+ return envit->second;
+ }
+
+ if(std::string value; get_env(key.data(), value))
+ {
+ return value;
}
- std::cerr << "Could not locate " << app << " for the " << arch << " architecture\n";
- exit(1);
return {};
}
@@ -130,38 +148,111 @@ public:
Args(const std::vector<std::string>& args)
{
resize(args.size() + 1);
- (*this)[0] = strdup("./ctor");
+ owning_container.push_back("./ctor");
+ (*this)[0] = owning_container.back().data();
for(std::size_t i = 0; i < size() - 1; ++i)
{
- (*this)[i + 1] = strdup(args[i].data());
+ owning_container.push_back(args[i]);
+ (*this)[i + 1] = owning_container.back().data();
}
}
- ~Args()
+ std::deque<std::string> owning_container;
+};
+
+namespace {
+std::ostream& operator<<(std::ostream& stream, const ctor::toolchain& toolchain)
+{
+ switch(toolchain)
{
- for(std::size_t i = 0; i < size(); ++i)
- {
- free((*this)[i]);
- }
+ 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& stream, const ctor::arch& arch)
+{
+ switch(arch)
+ {
+ case ctor::arch::unix:
+ stream << "ctor::arch::unix";
+ break;
+ case ctor::arch::apple:
+ stream << "ctor::arch::apple";
+ break;
+ case ctor::arch::windows:
+ stream << "ctor::arch::windows";
+ break;
+ case ctor::arch::unknown:
+ stream << "ctor::arch::unknown";
+ 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(const Settings& default_settings,
+int regenerateCache(ctor::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);
- dg::Options opt;
- int key{128};
+ arg::Parser<std::string> opt(static_cast<int>(vargs.size()), vargs.data());
- std::string build_arch;
+ std::string build_arch_prefix;
std::string build_path;
- std::string host_arch;
+ std::string host_arch_prefix;
std::string host_path;
std::string cc_prog = "gcc";
std::string cxx_prog = "g++";
@@ -169,118 +260,135 @@ 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;
+ opt.add('b', "--build-dir",
+ std::function([&](std::string arg)
+ {
+ settings.builddir = arg;
+ builddir = arg;
return 0;
- });
+ }),
+ "Set output directory for build files (default: '" +
+ settings.builddir + "').");
- opt.add("verbose", no_argument, 'v',
- "Be verbose. Add multiple times for more verbosity.",
- [&]() {
+ opt.add('v', "--verbose",
+ std::function([&]()
+ {
settings.verbose++;
return 0;
- });
+ }),
+ "Be verbose. Add multiple times for more verbosity.");
- opt.add("cc", required_argument, key++,
- "Use specified c-compiler instead of gcc.",
- [&]() {
- cc_prog = optarg;
+ opt.add({}, "--cc",
+ std::function([&](std::string arg)
+ {
+ cc_prog = arg;
return 0;
- });
+ }),
+ "Use specified c-compiler instead of gcc.");
- opt.add("cxx", required_argument, key++,
- "Use specified c++-compiler instead of g++.",
- [&]() {
- cxx_prog = optarg;
+ opt.add({}, "--cxx",
+ std::function([&](std::string arg)
+ {
+ cxx_prog = arg;
return 0;
- });
+ }),
+ "Use specified c++-compiler instead of g++.");
- opt.add("ar", required_argument, key++,
- "Use specified archiver instead of ar.",
- [&]() {
- ar_prog = optarg;
+ opt.add({}, "--ar",
+ std::function([&](std::string arg)
+ {
+ ar_prog = arg;
return 0;
- });
+ }),
+ "Use specified archiver instead of ar.");
- opt.add("ld", required_argument, key++,
- "Use specified linker instead of ld.",
- [&]() {
- ld_prog = optarg;
+ opt.add({}, "--ld",
+ std::function([&](std::string arg)
+ {
+ ld_prog = arg;
return 0;
- });
+ }),
+ "Use specified linker instead of ld.");
- opt.add("build", required_argument, key++,
- "Configure for building on specified architecture.",
- [&]() {
- build_arch = optarg;
+ opt.add({}, "--build",
+ std::function([&](std::string arg)
+ {
+ build_arch_prefix = arg;
return 0;
- });
+ }),
+ "Configure for building on specified architecture.");
- opt.add("build-path", required_argument, key++,
- "Set path to build tool-chain.",
- [&]() {
- build_path = optarg;
+ opt.add({}, "--build-path",
+ std::function([&](std::string arg)
+ {
+ build_path = arg;
return 0;
- });
+ }),
+ "Set path to build tool-chain.");
- opt.add("host", required_argument, key++,
- "Cross-compile to build programs to run on specified architecture.",
- [&]() {
- host_arch = optarg;
+ opt.add({}, "--host",
+ std::function([&](std::string arg)
+ {
+ host_arch_prefix = arg;
return 0;
- });
+ }),
+ "Cross-compile to build programs to run on specified architecture.");
- opt.add("host-path", required_argument, key++,
- "Set path to cross-compile tool-chain.",
- [&]() {
- host_path = optarg;
+ opt.add({}, "--host-path",
+ std::function([&](std::string arg)
+ {
+ host_path = arg;
return 0;
- });
+ }),
+ "Set path to cross-compile tool-chain.");
- opt.add("ctor-includedir", required_argument, key++,
- "Set path to ctor header file, used for re-compiling.",
- [&]() {
- ctor_includedir = optarg;
+ opt.add({}, "--ctor-includedir",
+ std::function([&](std::string arg)
+ {
+ ctor_includedir = arg;
return 0;
- });
+ }),
+ "Set path to ctor header file, used for re-compiling.");
- opt.add("ctor-libdir", required_argument, key++,
- "Set path to ctor library file, used for re-compiling.",
- [&]() {
- ctor_libdir = optarg;
+ opt.add({}, "--ctor-libdir",
+ std::function([&](std::string arg)
+ {
+ ctor_libdir = arg;
return 0;
- });
+ }),
+ "Set path to ctor library file, used for re-compiling.");
// Resolv externals
- ExternalConfigurations externalConfigs;
- for(std::size_t i = 0; i < numExternalConfigFiles; ++i)
+ ctor::external_configurations externalConfigs;
+ const auto& externalConfigFiles = getExternalConfigFileList();
+ for(const auto& externalConfigFile : externalConfigFiles)
{
- auto newExternalConfigs = externalConfigFiles[i].cb(settings);
+ auto newExternalConfigs = externalConfigFile.cb(settings);
externalConfigs.insert(externalConfigs.end(),
newExternalConfigs.begin(),
newExternalConfigs.end());
}
auto add_path_args =
- [&](const std::string& name)
+ [&](const std::string& arg_name)
{
- opt.add(name + "-includedir", required_argument, key++,
- "Set path to " + name + " header file.",
- [&]() {
- external_includedir[name] = optarg;
+ opt.add({}, "--" + arg_name + "-includedir",
+ std::function([&](std::string arg)
+ {
+ external_includedir[arg_name] = arg;
return 0;
- });
+ }),
+ "Set path to " + arg_name + " header file.");
- opt.add(name + "-libdir", required_argument, key++,
- "Set path to " + name + " libraries.",
- [&]() {
- external_libdir[name] = optarg;
+ opt.add({}, "--" + arg_name + "-libdir",
+ std::function([&](std::string arg)
+ {
+ external_libdir[arg_name] = arg;
return 0;
- });
+ }),
+ "Set path to " + arg_name + " libraries.");
};
for(const auto& ext : externalConfigs)
@@ -288,7 +396,7 @@ int regenerateCache(const Settings& default_settings,
std::visit([&](auto&& arg)
{
using T = std::decay_t<decltype(arg)>;
- if constexpr (std::is_same_v<T, ExternalManual>)
+ if constexpr (std::is_same_v<T, ctor::external_manual>)
{
add_path_args(ext.name);
}
@@ -300,48 +408,159 @@ int regenerateCache(const Settings& default_settings,
}
- opt.add("help", no_argument, 'h',
- "Print this help text.",
- [&]() {
- std::cout << "configure usage stuff\n";
+ opt.add('h', "--help",
+ std::function([&]() -> int
+ {
+ std::cout << "Configure how to build with " << name << "\n";
+ std::cout << "Usage: " << name << " configure [options]\n\n";
+ std::cout << "Options:\n";
opt.help();
exit(0);
- return 0;
- });
+ }),
+ "Print this help text.");
- opt.process(vargs.size(), vargs.data());
+ opt.set_err_cb(
+ [&](arg::error err, std::string_view arg)
+ {
+ switch(err)
+ {
+ case arg::error::invalid_arg:
+ std::cerr << opt.prog_name() <<
+ ": invalid argument for option '" << arg << "'\n";
+ std::cerr << "Type '" << opt.prog_name() <<
+ " -h' for more information.\n";
+ break;
+
+ case arg::error::missing_arg:
+ std::cerr << opt.prog_name() << ": option requires and argument '" <<
+ arg << "'\n";
+ std::cerr << "Type '" << opt.prog_name() <<
+ " -h' for more information.\n";
+ break;
+
+ case arg::error::invalid_opt:
+ std::cerr << opt.prog_name() << ": invalid option '" << arg << "'\n";
+ std::cerr << "Type '" << opt.prog_name() <<
+ " -h' for more information.\n";
+ break;
+ }
+ });
- if(host_arch.empty())
+ opt.set_pos_cb(
+ [&](std::string_view)
+ {
+ std::cerr <<
+ "The configure subcommand doesn't use positional arguments.\n";
+ return 1;
+ });
+
+ auto res = opt.parse();
+ if(res != 0)
{
- host_arch = build_arch;
+ return res;
+ }
+
+ if(host_arch_prefix.empty())
+ {
+ host_arch_prefix = build_arch_prefix;
}
auto tasks = getTasks(settings, {}, false);
-/*
- bool needs_cpp{false};
- bool needs_c{false};
- bool needs_ar{false};
- bool needs_asm{false};
+
+ bool needs_build{true}; // we always need to compile ctor itself
+ bool needs_build_c{false};
+ bool needs_build_cxx{true}; // we always need to compile ctor itself
+ bool needs_build_ld{true}; // we always need to compile ctor itself
+ bool needs_build_ar{false};
+ bool needs_build_asm{false};
+
+ bool needs_host_c{false};
+ bool needs_host{false};
+ bool needs_host_cxx{false};
+ bool needs_host_ld{false};
+ bool needs_host_ar{false};
+ bool needs_host_asm{false};
+
for(const auto& task :tasks)
{
- switch(task->sourceLanguage())
+ switch(task->outputSystem())
{
- case Language::Auto:
- std::cerr << "TargetLanguage not deduced!\n";
- exit(1);
- break;
- case Language::C:
- needs_cpp = false;
- break;
- case Language::Cpp:
- needs_c = true;
+ case ctor::output_system::build:
+ needs_build = true;
+ switch(task->targetType())
+ {
+ case ctor::target_type::executable:
+ case ctor::target_type::unit_test:
+ case ctor::target_type::dynamic_library:
+ needs_build_ld = true;
+ break;
+ case ctor::target_type::static_library:
+ case ctor::target_type::unit_test_library:
+ needs_build_ar = true;
+ break;
+ case ctor::target_type::object:
+ switch(task->sourceLanguage())
+ {
+ case ctor::language::automatic:
+ std::cerr << "TargetLanguage not deduced!\n";
+ exit(1);
+ break;
+ case ctor::language::c:
+ needs_build_c = true;
+ break;
+ case ctor::language::cpp:
+ needs_build_cxx = true;
+ break;
+ case ctor::language::assembler:
+ needs_build_asm = true;
+ break;
+ }
+ break;
+ case ctor::target_type::function:
+ case ctor::target_type::automatic:
+ case ctor::target_type::unknown:
+ break;
+ }
break;
- case Language::Asm:
- needs_asm = true;
+ case ctor::output_system::host:
+ needs_host = true;
+ switch(task->targetType())
+ {
+ case ctor::target_type::executable:
+ case ctor::target_type::unit_test:
+ case ctor::target_type::dynamic_library:
+ needs_host_ld = true;
+ break;
+ case ctor::target_type::static_library:
+ case ctor::target_type::unit_test_library:
+ needs_host_ar = true;
+ break;
+ case ctor::target_type::object:
+ switch(task->sourceLanguage())
+ {
+ case ctor::language::automatic:
+ std::cerr << "TargetLanguage not deduced!\n";
+ exit(1);
+ break;
+ case ctor::language::c:
+ needs_host_c = true;
+ break;
+ case ctor::language::cpp:
+ needs_host_cxx = true;
+ break;
+ case ctor::language::assembler:
+ needs_host_asm = true;
+ break;
+ }
+ break;
+ case ctor::target_type::function:
+ case ctor::target_type::automatic:
+ case ctor::target_type::unknown:
+ break;
+ }
break;
}
}
-*/
auto cc_env = env.find("CC");
if(cc_env != env.end())
@@ -367,54 +586,249 @@ int regenerateCache(const Settings& default_settings,
ld_prog = ld_env->second;
}
- std::string host_cc = locate(host_arch, cc_prog);
- std::string host_cxx = locate(host_arch, cxx_prog);
- std::string host_ar = locate(host_arch, ar_prog);
- std::string host_ld = locate(host_arch, ld_prog);
- std::string build_cc = locate(build_arch, cc_prog);
- std::string build_cxx = locate(build_arch, cxx_prog);
- std::string build_ar = locate(build_arch, ar_prog);
- std::string build_ld = locate(build_arch, ld_prog);
+ auto paths = get_paths();
+
+ auto path_env = env.find("PATH");
+ if(path_env != env.end())
+ {
+ paths = get_paths(path_env->second);
+ }
+
+ std::string host_cc;
+ std::string host_cxx;
+ std::string host_ld;
+ std::string host_ar;
+ ctor::toolchain host_toolchain{ctor::toolchain::none};
+ ctor::arch host_arch{ctor::arch::unknown};
+ if(needs_host)
+ {
+ // Host detection
+ if(needs_host_c)
+ {
+ host_cc = locate(cc_prog, paths, host_arch_prefix);
+ if(host_cc.empty())
+ {
+ std::cerr << "Could not locate host_cc prog" << std::endl;
+ return 1;
+ }
+ }
+
+ if(needs_host_cxx)
+ {
+ host_cxx = locate(cxx_prog, paths, host_arch_prefix);
+ if(host_cxx.empty())
+ {
+ std::cerr << "Could not locate host_cxx prog" << std::endl;
+ return 1;
+ }
+ }
+
+ if(needs_host_ar)
+ {
+ host_ar = locate(ar_prog, paths, host_arch_prefix);
+ if(host_ar.empty())
+ {
+ std::cerr << "Could not locate host_ar prog" << std::endl;
+ return 1;
+ }
+ }
+
+ if(needs_host_ld)
+ {
+ host_ld = locate(ld_prog, paths, host_arch_prefix);
+ if(host_ld.empty())
+ {
+ std::cerr << "Could not locate host_ld prog" << std::endl;
+ return 1;
+ }
+ }
+
+ if(needs_host_asm)
+ {
+ // TODO
+ }
+
+ host_toolchain = getToolChain(host_cxx);
+ auto host_arch_str = get_arch(ctor::output_system::host);
+ host_arch = get_arch(ctor::output_system::host, host_arch_str);
+
+ std::cout << "** Host architecture '" << host_arch_str << "': " << host_arch << std::endl;
+
+ if(host_arch == ctor::arch::unknown)
+ {
+ std::cerr << "Could not detect host architecture" << std::endl;
+ return 1;
+ }
+ }
+
+ std::string build_cc;
+ std::string build_cxx;
+ std::string build_ld;
+ std::string build_ar;
+ ctor::toolchain build_toolchain{ctor::toolchain::none};
+ ctor::arch build_arch{ctor::arch::unknown};
+ if(needs_build)
+ {
+ // Build detection
+ if(needs_build_c)
+ {
+ build_cc = locate(cc_prog, paths, build_arch_prefix);
+ if(build_cc.empty())
+ {
+ std::cerr << "Could not locate build_cc prog" << std::endl;
+ return 1;
+ }
+ }
+
+ if(needs_build_cxx)
+ {
+ build_cxx = locate(cxx_prog, paths, build_arch_prefix);
+ if(build_cxx.empty())
+ {
+ std::cerr << "Could not locate build_cxx prog" << std::endl;
+ return 1;
+ }
+ }
+
+ if(needs_build_ar)
+ {
+ build_ar = locate(ar_prog, paths, build_arch_prefix);
+ if(build_ar.empty())
+ {
+ std::cerr << "Could not locate build_ar prog" << std::endl;
+ return 1;
+ }
+ }
+
+ if(needs_build_ld)
+ {
+ build_ld = locate(ld_prog, paths, build_arch_prefix);
+ if(build_ld.empty())
+ {
+ std::cerr << "Could not locate build_ld prog" << std::endl;
+ return 1;
+ }
+ }
+
+ if(needs_build_asm)
+ {
+ // TODO
+ }
+
+ build_toolchain = getToolChain(build_cxx);
+ auto build_arch_str = get_arch(ctor::output_system::build);
+ build_arch = get_arch(ctor::output_system::build, build_arch_str);
+
+ std::cout << "** Build architecture '" << build_arch_str << "': " << build_arch << std::endl;
+
+ if(build_arch == ctor::arch::unknown)
+ {
+ std::cerr << "Could not detect build architecture" << std::endl;
+ return 1;
+ }
+ }
+
+
+ // 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";
+ if(needs_host)
+ {
+ istr << " .host_toolchain = " << host_toolchain << ",\n";
+ istr << " .host_arch = " << host_arch << ",\n";
+ }
+ if(needs_build)
+ {
+ istr << " .build_toolchain = " << build_toolchain << ",\n";
+ istr << " .build_arch = " << build_arch << ",\n";
+ }
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 << " {\"" << esc(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";
+ if(!builddir.empty())
+ {
+ istr << " { \"" << ctor::cfg::builddir << "\", \"" << esc(builddir) << "\" },\n";
+ ctor::builddir = builddir;
+ }
+ if(needs_host)
+ {
+ if(needs_host_c)
+ {
+ istr << " { \"" << ctor::cfg::host_cc << "\", \"" << esc(host_cc) << "\" },\n";
+ }
+ if(needs_host_cxx)
+ {
+ istr << " { \"" << ctor::cfg::host_cxx << "\", \"" << esc(host_cxx) << "\" },\n";
+ }
+ if(needs_host_ar)
+ {
+ istr << " { \"" << ctor::cfg::host_ar << "\", \"" << esc(host_ar) << "\" },\n";
+ }
+ if(needs_host_ld)
+ {
+ istr << " { \"" << ctor::cfg::host_ld << "\", \"" << esc(host_ld) << "\" },\n";
+ }
+ }
+ if(needs_build)
+ {
+ if(needs_build_c)
+ {
+ istr << " { \"" << ctor::cfg::build_cc << "\", \"" << esc(build_cc) << "\" },\n";
+ }
+ if(needs_build_cxx)
+ {
+ istr << " { \"" << ctor::cfg::build_cxx << "\", \"" << esc(build_cxx) << "\" },\n";
+ }
+ if(needs_build_ar)
+ {
+ istr << " { \"" << ctor::cfg::build_ar << "\", \"" << esc(build_ar) << "\" },\n";
+ }
+ if(needs_build_ld)
+ {
+ istr << " { \"" << ctor::cfg::build_ld << "\", \"" << esc(build_ld) << "\" },\n";
+ }
+ }
if(!ctor_includedir.empty())
{
- istr << " { \"" << cfg::ctor_includedir << "\", \"" << ctor_includedir << "\" },\n";
+ istr << " { \"" << ctor::cfg::ctor_includedir << "\", \"" << esc(ctor_includedir) << "\" },\n";
ctor::includedir = ctor_includedir;
}
if(!ctor_libdir.empty())
{
- istr << " { \"" << cfg::ctor_libdir << "\", \"" << ctor_libdir << "\" },\n";
+ istr << " { \"" << ctor::cfg::ctor_libdir << "\", \"" << esc(ctor_libdir) << "\" },\n";
ctor::libdir = ctor_libdir;
}
@@ -423,12 +837,12 @@ int regenerateCache(const Settings& default_settings,
for(const auto& ext : externalConfigs)
{
- istr << " { \"" << ext.name << "\", {\n";
- Flags resolved_flags;
- if(std::holds_alternative<ExternalManual>(ext.external))
+ istr << " { \"" << esc(ext.name) << "\", {\n";
+ ctor::flags resolved_flags;
+ if(std::holds_alternative<ctor::external_manual>(ext.external))
{
- if(auto ret = resolv(settings, ext.name,
- std::get<ExternalManual>(ext.external),
+ if(auto ret = resolv(settings, ext,
+ std::get<ctor::external_manual>(ext.external),
resolved_flags))
{
return ret;
@@ -440,22 +854,22 @@ int regenerateCache(const Settings& default_settings,
return 1;
}
- if(!resolved_flags.cxxflags.empty())
+ if(!resolved_flags.cflags.empty())
{
- istr << " .cxxflags = {";
- for(const auto& flag : resolved_flags.cxxflags)
+ istr << " .cflags = {";
+ for(const auto& flag : resolved_flags.cflags)
{
- istr << "\"" << flag << "\",";
+ istr << flag << ",";
}
istr << "},\n";
}
- if(!resolved_flags.cflags.empty())
+ if(!resolved_flags.cxxflags.empty())
{
- istr << " .cflags = {";
- for(const auto& flag : resolved_flags.cflags)
+ istr << " .cxxflags = {";
+ for(const auto& flag : resolved_flags.cxxflags)
{
- istr << "\"" << flag << "\",";
+ istr << flag << ",";
}
istr << "},\n";
}
@@ -465,7 +879,7 @@ int regenerateCache(const Settings& default_settings,
istr << " .ldflags = {";
for(const auto& flag : resolved_flags.ldflags)
{
- istr << "\"" << flag << "\",";
+ istr << flag << ",";
}
istr << "},\n";
}
@@ -475,7 +889,7 @@ int regenerateCache(const Settings& default_settings,
istr << " .asmflags = {";
for(const auto& flag : resolved_flags.asmflags)
{
- istr << "\"" << flag << "\",";
+ istr << flag << ",";
}
istr << "},\n";
}
@@ -485,7 +899,7 @@ int regenerateCache(const Settings& default_settings,
istr << " },\n";
istr << " };\n";
istr << " return cfg;\n";
- istr << "}\n\n";
+ istr << "}\n";
}
{
@@ -498,42 +912,61 @@ 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};
+ auto args_span = std::span(argv, static_cast<std::size_t>(argc));
+
+ ctor::settings settings{global_settings};
std::vector<std::string> args;
- for(int i = 2; i < argc; ++i) // skip command and the first 'configure' arg
+ for(std::size_t i = 2; i < args_span.size(); ++i) // skip command and the first 'configure' arg
{
- args.push_back(argv[i]);
+ args.emplace_back(args_span[i]);
}
std::map<std::string, std::string> env;
- auto cc_env = getenv("CC");
- if(cc_env)
+ std::string value;
+ if(get_env("CC", value))
{
- env["CC"] = cc_env;
+ env["CC"] = value;
}
- auto cxx_env = getenv("CXX");
- if(cxx_env)
+ if(get_env("CFLAGS", value))
{
- env["CXX"] = cxx_env;
+ env["CFLAGS"] = value;
}
- auto ar_env = getenv("AR");
- if(ar_env)
+ if(get_env("CXX", value))
{
- env["AR"] = ar_env;
+ env["CXX"] = value;
}
- auto ld_env = getenv("LD");
- if(ld_env)
+ if(get_env("CXXFLAGS", value))
{
- env["LD"] = ld_env;
+ env["CXXFLAGS"] = value;
}
- auto ret = regenerateCache(settings, args, env);
+ if(get_env("AR", value))
+ {
+ env["AR"] = value;
+ }
+
+ if(get_env("LD", value))
+ {
+ env["LD"] = value;
+ }
+
+ if(get_env("LDFLAGS", value))
+ {
+ env["LDFLAGS"] = value;
+ }
+
+ if(get_env("PATH", value))
+ {
+ env["PATH"] = value;
+ }
+
+ auto ret = regenerateCache(settings, args_span[0], args, env);
if(ret != 0)
{
return ret;
@@ -544,36 +977,40 @@ 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[])
{
+ auto args_span = std::span(argv, static_cast<std::size_t>(argc));
+
+ ctor::settings settings{global_settings};
+
bool no_rerun{false};
std::vector<std::string> args;
- for(int i = 2; i < argc; ++i) // skip executable name and 'reconfigure' arg
+ for(std::size_t i = 2; i < args_span.size(); ++i) // skip executable name and 'reconfigure' arg
{
- if(i == 2 && std::string(argv[i]) == "--no-rerun")
+ if(i == 2 && std::string(args_span[i]) == "--no-rerun")
{
no_rerun = true;
continue;
}
- args.push_back(argv[i]);
+ args.emplace_back(args_span[i]);
}
- const auto& cfg = configuration();
+ const auto& cfg = ctor::get_configuration();
std::cout << "Re-running configure:\n";
for(const auto& e : cfg.env)
{
std::cout << e.first << "=\"" << e.second << "\" ";
}
- std::cout << argv[0] << " configure ";
+ std::cout << args_span[0] << " configure ";
for(const auto& arg : cfg.args)
{
std::cout << arg << " ";
}
std::cout << "\n";
- auto ret = regenerateCache(settings, cfg.args, cfg.env);
+ auto ret = regenerateCache(settings, args_span[0], cfg.args, cfg.env);
if(ret != 0)
{
return ret;
@@ -586,5 +1023,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(settings, args_span[0], args);
}