diff options
-rw-r--r-- | src/bootstrap.cc | 11 | ||||
-rw-r--r-- | src/configure.cc | 41 | ||||
-rw-r--r-- | src/ctor.h | 11 | ||||
-rw-r--r-- | src/tools.cc | 63 | ||||
-rw-r--r-- | src/tools.h | 15 | ||||
-rw-r--r-- | test/tools_test.cc | 249 |
6 files changed, 272 insertions, 118 deletions
diff --git a/src/bootstrap.cc b/src/bootstrap.cc index f091849..0604527 100644 --- a/src/bootstrap.cc +++ b/src/bootstrap.cc @@ -22,10 +22,17 @@ std::filesystem::path configurationFile("configuration.cc"); std::filesystem::path configHeaderFile("config.h"); -const ctor::configuration default_configuration{}; const ctor::configuration& 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, "/usr/bin/g++")); + initialised = true; + } + + return cfg; } bool ctor::configuration::has(const std::string& key) const diff --git a/src/configure.cc b/src/configure.cc index f91f0d9..deeb6a6 100644 --- a/src/configure.cc +++ b/src/configure.cc @@ -15,6 +15,7 @@ #include "tasks.h" #include "rebuild.h" #include "externals.h" +#include "tools.h" std::filesystem::path configurationFile("configuration.cc"); std::filesystem::path configHeaderFile("config.h"); @@ -22,10 +23,16 @@ std::filesystem::path configHeaderFile("config.h"); std::map<std::string, std::string> external_includedir; std::map<std::string, std::string> external_libdir; -const ctor::configuration default_configuration{}; 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 { @@ -164,6 +171,28 @@ public: } }; +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; +} +} + // helper constant for the visitor template<class> inline constexpr bool always_false_v = false; @@ -395,6 +424,12 @@ int regenerateCache(ctor::settings& settings, std::string build_ar = locate(build_arch, ar_prog); std::string build_ld = locate(build_arch, ld_prog); + if(!host_cxx.empty()) + { + // 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()) { @@ -419,6 +454,8 @@ int regenerateCache(ctor::settings& settings, istr << "{\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) { @@ -58,6 +58,14 @@ struct source std::string output{}; }; +enum class toolchain +{ + any, + none, + gcc, + clang, +}; + struct flags { std::vector<std::string> cxxflags; // flags for c++ compiler @@ -146,6 +154,9 @@ struct configuration bool has(const std::string& key) const; const std::string& get(const std::string& key, const std::string& default_value = {}) const; + ctor::toolchain host_toolchain{ctor::toolchain::none}; + ctor::toolchain build_toolchain{ctor::toolchain::none}; + std::vector<std::string> args; // vector of arguments used when last calling configure std::map<std::string, std::string> env; // env used when last calling configure diff --git a/src/tools.cc b/src/tools.cc index 4aaa515..ddb1463 100644 --- a/src/tools.cc +++ b/src/tools.cc @@ -8,35 +8,44 @@ #include <cassert> -ToolChain getToolChain(ctor::output_system system) +ctor::toolchain getToolChain(const std::string& compiler) { - const auto& c = ctor::get_configuration(); - std::string compiler; - switch(system) - { - case ctor::output_system::host: - compiler = c.get(ctor::cfg::host_cxx, "g++"); - break; - case ctor::output_system::build: - compiler = c.get(ctor::cfg::build_cxx, "g++"); - break; - } - std::filesystem::path cc(compiler); auto cc_cmd = cc.stem().string(); // Note: "g++" is a substring of "clang++" so "clang++" must be tested first. if(cc_cmd.find("clang++") != std::string::npos) { - return ToolChain::clang; + return ctor::toolchain::clang; } else if(cc_cmd.find("g++") != std::string::npos) { - return ToolChain::gcc; + return ctor::toolchain::gcc; } std::cerr << "Unsupported output system.\n"; - return ToolChain::gcc; + return ctor::toolchain::gcc; +} + +ctor::toolchain getToolChain(ctor::output_system system) +{ + const auto& cfg = ctor::get_configuration(); + if(system == ctor::output_system::host) + { + if(cfg.host_toolchain != ctor::toolchain::none) + { + return cfg.host_toolchain; + } + return getToolChain(cfg.get(ctor::cfg::host_cxx, "g++")); + } + else + { + if(cfg.build_toolchain != ctor::toolchain::none) + { + return cfg.build_toolchain; + } + return getToolChain(cfg.get(ctor::cfg::build_cxx, "g++")); + } } namespace @@ -86,15 +95,18 @@ std::vector<std::string> getOptionGcc(opt option, const std::string& arg) } } -std::vector<std::string> getOption(ToolChain tool_chain, +std::vector<std::string> getOption(ctor::toolchain toolchain, opt option, const std::string& arg) { - switch(tool_chain) + switch(toolchain) { - case ToolChain::gcc: - case ToolChain::clang: + case ctor::toolchain::gcc: + case ctor::toolchain::clang: return getOptionGcc(option, arg); + case ctor::toolchain::any: + case ctor::toolchain::none: + break; } std::cerr << "Unsupported tool-chain.\n"; @@ -123,13 +135,16 @@ std::pair<opt, std::string> getOptionGcc(const std::string& flag) } std::pair<opt, std::string> getOption(const std::string& flag, - ToolChain tool_chain) + ctor::toolchain toolchain) { - switch(tool_chain) + switch(toolchain) { - case ToolChain::gcc: - case ToolChain::clang: + case ctor::toolchain::gcc: + case ctor::toolchain::clang: return getOptionGcc(flag); + case ctor::toolchain::any: + case ctor::toolchain::none: + break; } std::cerr << "Unsupported tool-chain.\n"; diff --git a/src/tools.h b/src/tools.h index 49069d5..bedb708 100644 --- a/src/tools.h +++ b/src/tools.h @@ -8,12 +8,6 @@ #include "ctor.h" -enum class ToolChain -{ - gcc, - clang, -}; - enum class opt { // gcc/clang @@ -36,12 +30,15 @@ enum class opt custom, // entire option taken verbatim from <arg> }; +//! Get tool-chain type from compiler path string +ctor::toolchain getToolChain(const std::string& compiler); + //! Get tool-chain type from output system (via configuration) -ToolChain getToolChain(ctor::output_system system); +ctor::toolchain getToolChain(ctor::output_system system); //! Get tool argument(s) for specific option type matching the supplied //! tool-chain -std::vector<std::string> getOption(ToolChain tool_chain, +std::vector<std::string> getOption(ctor::toolchain toolchain, opt option, const std::string& arg = {}); @@ -49,4 +46,4 @@ std::vector<std::string> getOption(ToolChain tool_chain, //! ie. { opt::InludePath, "foo/bar" } from "-Ifoo/bar" //! Returns { opt::Custom, flag } if unknown. std::pair<opt, std::string> getOption(const std::string& flag, - ToolChain tool_chain = ToolChain::gcc); + ctor::toolchain toolchain = ctor::toolchain::gcc); diff --git a/test/tools_test.cc b/test/tools_test.cc index 5a0e994..4cc9a77 100644 --- a/test/tools_test.cc +++ b/test/tools_test.cc @@ -2,26 +2,33 @@ #include <string> #include <ostream> +#include <tools.h> + std::ostream& operator<<(std::ostream& stream, const std::vector<std::string>& vs); +std::ostream& operator<<(std::ostream& stream, const ctor::toolchain& tool_chain); #include <uunit.h> #include <initializer_list> #include <cassert> -#include <tools.h> - using namespace std::string_literals; -std::ostream& operator<<(std::ostream& stream, const ToolChain& tool_chain) +std::ostream& operator<<(std::ostream& stream, const ctor::toolchain& tool_chain) { switch(tool_chain) { - case ToolChain::gcc: - stream << "ToolChain::gcc"; + case ctor::toolchain::none: + stream << "ctor::toolchain::none"; + break; + case ctor::toolchain::any: + stream << "ctor::toolchain::any"; break; - case ToolChain::clang: - stream << "ToolChain::clang"; + case ctor::toolchain::gcc: + stream << "ctor::toolchain::gcc"; + break; + case ctor::toolchain::clang: + stream << "ctor::toolchain::clang"; break; } return stream; @@ -79,9 +86,7 @@ std::ostream& operator<<(std::ostream& stream, const std::pair<opt, std::string> return stream; } -// Controllable getConfiguration stub: -namespace -{ +namespace { std::string conf_host_cxx{}; std::string conf_build_cxx{}; } @@ -123,94 +128,176 @@ public: void getToolChain_test() { - // host - conf_host_cxx = "/usr/bin/g++"; - uASSERT_EQUAL(ToolChain::gcc, getToolChain(ctor::output_system::host)); + uASSERT_EQUAL(ctor::toolchain::gcc, getToolChain("/usr/bin/g++")); + uASSERT_EQUAL(ctor::toolchain::gcc, getToolChain("/usr/bin/g++-10")); + uASSERT_EQUAL(ctor::toolchain::gcc, getToolChain("/usr/bin/x86_64-pc-linux-gnu-g++-9.3.0")); + uASSERT_EQUAL(ctor::toolchain::clang, getToolChain("/usr/bin/clang++")); + uASSERT_EQUAL(ctor::toolchain::clang, getToolChain("/usr/bin/clang++-10")); + uASSERT_EQUAL(ctor::toolchain::clang, getToolChain("/usr/lib/llvm/12/bin/i686-pc-linux-gnu-clang++-12")); + } + + void getOption_toolchain_test() + { + std::vector<std::string> exp; + std::vector<std::string> act; - conf_host_cxx = "/usr/bin/g++-10"; - uASSERT_EQUAL(ToolChain::gcc, getToolChain(ctor::output_system::host)); + exp = { "-o", "foo" }; + act = getOption(ctor::toolchain::clang, opt::output, "foo"); + uASSERT_EQUAL(exp, act); - conf_host_cxx = "/usr/bin/x86_64-pc-linux-gnu-g++-9.3.0"; - uASSERT_EQUAL(ToolChain::gcc, getToolChain(ctor::output_system::host)); + exp = { "-g" }; + act = getOption(ctor::toolchain::clang, opt::debug); + uASSERT_EQUAL(exp, act); - conf_host_cxx = "/usr/bin/clang++"; - uASSERT_EQUAL(ToolChain::clang, getToolChain(ctor::output_system::host)); + exp = { "-s" }; + act = getOption(ctor::toolchain::clang, opt::strip); + uASSERT_EQUAL(exp, act); - conf_host_cxx = "/usr/bin/clang++-10"; - uASSERT_EQUAL(ToolChain::clang, getToolChain(ctor::output_system::host)); + exp = { "-Wall" }; + act = getOption(ctor::toolchain::clang, opt::warn_all); + uASSERT_EQUAL(exp, act); - conf_host_cxx = "/usr/lib/llvm/12/bin/i686-pc-linux-gnu-clang++-12"; - uASSERT_EQUAL(ToolChain::clang, getToolChain(ctor::output_system::host)); + exp = { "-Werror" }; + act = getOption(ctor::toolchain::clang, opt::warnings_as_errors); + uASSERT_EQUAL(exp, act); - // build - conf_build_cxx = "/usr/bin/g++"; - uASSERT_EQUAL(ToolChain::gcc, getToolChain(ctor::output_system::build)); + exp = { "-MMD" }; + act = getOption(ctor::toolchain::clang, opt::generate_dep_tree); + uASSERT_EQUAL(exp, act); - conf_build_cxx = "/usr/bin/g++-10"; - uASSERT_EQUAL(ToolChain::gcc, getToolChain(ctor::output_system::build)); + exp = { "-c" }; + act = getOption(ctor::toolchain::clang, opt::no_link); + uASSERT_EQUAL(exp, act); - conf_build_cxx = "/usr/bin/x86_64-pc-linux-gnu-g++-9.3.0"; - uASSERT_EQUAL(ToolChain::gcc, getToolChain(ctor::output_system::build)); + exp = { "-Ifoo" }; + act = getOption(ctor::toolchain::clang, opt::include_path, "foo"); + uASSERT_EQUAL(exp, act); - conf_build_cxx = "/usr/bin/clang++"; - uASSERT_EQUAL(ToolChain::clang, getToolChain(ctor::output_system::build)); + exp = { "-Lfoo" }; + act = getOption(ctor::toolchain::clang, opt::library_path, "foo"); + uASSERT_EQUAL(exp, act); - conf_build_cxx = "/usr/bin/clang++-10"; - uASSERT_EQUAL(ToolChain::clang, getToolChain(ctor::output_system::build)); + exp = { "-lfoo" }; + act = getOption(ctor::toolchain::clang, opt::link, "foo"); + uASSERT_EQUAL(exp, act); - conf_build_cxx = "/usr/lib/llvm/12/bin/i686-pc-linux-gnu-clang++-12"; - uASSERT_EQUAL(ToolChain::clang, getToolChain(ctor::output_system::build)); - } + exp = { "-std=foo" }; + act = getOption(ctor::toolchain::clang, opt::cpp_std, "foo"); + uASSERT_EQUAL(exp, act); - void getOption_toolchain_test() - { - using sv = std::vector<std::string>; - - uUnit::assert_equal(sv{ "-o", "foo" }, getOption(ToolChain::clang, opt::output, "foo"), __FILE__, __LINE__); - uUnit::assert_equal(sv{ "-g" }, getOption(ToolChain::clang, opt::debug), __FILE__, __LINE__); - uUnit::assert_equal(sv{ "-s" }, getOption(ToolChain::clang, opt::strip), __FILE__, __LINE__); - uUnit::assert_equal(sv{ "-Wall" }, getOption(ToolChain::clang, opt::warn_all), __FILE__, __LINE__); - uUnit::assert_equal(sv{ "-Werror" }, getOption(ToolChain::clang, opt::warnings_as_errors), __FILE__, __LINE__); - uUnit::assert_equal(sv{ "-MMD" }, getOption(ToolChain::clang, opt::generate_dep_tree), __FILE__, __LINE__); - uUnit::assert_equal(sv{ "-c" }, getOption(ToolChain::clang, opt::no_link), __FILE__, __LINE__); - uUnit::assert_equal(sv{ "-Ifoo" }, getOption(ToolChain::clang, opt::include_path, "foo"), __FILE__, __LINE__); - uUnit::assert_equal(sv{ "-Lfoo" }, getOption(ToolChain::clang, opt::library_path, "foo"), __FILE__, __LINE__); - uUnit::assert_equal(sv{ "-lfoo" }, getOption(ToolChain::clang, opt::link, "foo"), __FILE__, __LINE__); - uUnit::assert_equal(sv{ "-std=foo" }, getOption(ToolChain::clang, opt::cpp_std, "foo"), __FILE__, __LINE__); - uUnit::assert_equal(sv{ "-shared" }, getOption(ToolChain::clang, opt::build_shared), __FILE__, __LINE__); - uUnit::assert_equal(sv{ "-pthread" }, getOption(ToolChain::clang, opt::threads), __FILE__, __LINE__); - uUnit::assert_equal(sv{ "-Ofoo" }, getOption(ToolChain::clang, opt::optimization, "foo"), __FILE__, __LINE__); - uUnit::assert_equal(sv{ "-fPIC" }, getOption(ToolChain::clang, opt::position_independent_code), __FILE__, __LINE__); - uUnit::assert_equal(sv{ "-fPIE" }, getOption(ToolChain::clang, opt::position_independent_executable), __FILE__, __LINE__); - uUnit::assert_equal(sv{ "-foo" }, getOption(ToolChain::clang, opt::custom, "-foo"), __FILE__, __LINE__); - - uUnit::assert_equal(sv{ "-o", "foo" }, getOption(ToolChain::gcc, opt::output, "foo"), __FILE__, __LINE__); - uUnit::assert_equal(sv{ "-g" }, getOption(ToolChain::gcc, opt::debug), __FILE__, __LINE__); - uUnit::assert_equal(sv{ "-s" }, getOption(ToolChain::gcc, opt::strip), __FILE__, __LINE__); - uUnit::assert_equal(sv{ "-Wall" }, getOption(ToolChain::gcc, opt::warn_all), __FILE__, __LINE__); - uUnit::assert_equal(sv{ "-Werror" }, getOption(ToolChain::gcc, opt::warnings_as_errors), __FILE__, __LINE__); - uUnit::assert_equal(sv{ "-MMD" }, getOption(ToolChain::gcc, opt::generate_dep_tree), __FILE__, __LINE__); - uUnit::assert_equal(sv{ "-c" }, getOption(ToolChain::gcc, opt::no_link), __FILE__, __LINE__); - uUnit::assert_equal(sv{ "-Ifoo" }, getOption(ToolChain::gcc, opt::include_path, "foo"), __FILE__, __LINE__); - uUnit::assert_equal(sv{ "-Lfoo" }, getOption(ToolChain::gcc, opt::library_path, "foo"), __FILE__, __LINE__); - uUnit::assert_equal(sv{ "-lfoo" }, getOption(ToolChain::gcc, opt::link, "foo"), __FILE__, __LINE__); - uUnit::assert_equal(sv{ "-std=foo" }, getOption(ToolChain::gcc, opt::cpp_std, "foo"), __FILE__, __LINE__); - uUnit::assert_equal(sv{ "-shared" }, getOption(ToolChain::gcc, opt::build_shared), __FILE__, __LINE__); - uUnit::assert_equal(sv{ "-pthread" }, getOption(ToolChain::gcc, opt::threads), __FILE__, __LINE__); - uUnit::assert_equal(sv{ "-Ofoo" }, getOption(ToolChain::gcc, opt::optimization, "foo"), __FILE__, __LINE__); - uUnit::assert_equal(sv{ "-fPIC" }, getOption(ToolChain::gcc, opt::position_independent_code), __FILE__, __LINE__); - uUnit::assert_equal(sv{ "-fPIE" }, getOption(ToolChain::gcc, opt::position_independent_executable), __FILE__, __LINE__); - uUnit::assert_equal(sv{ "-foo" }, getOption(ToolChain::gcc, opt::custom, "-foo"), __FILE__, __LINE__); + exp = { "-shared" }; + act = getOption(ctor::toolchain::clang, opt::build_shared); + uASSERT_EQUAL(exp, act); + + exp = { "-pthread" }; + act = getOption(ctor::toolchain::clang, opt::threads); + uASSERT_EQUAL(exp, act); + + exp = { "-Ofoo" }; + act = getOption(ctor::toolchain::clang, opt::optimization, "foo"); + uASSERT_EQUAL(exp, act); + + exp = { "-fPIC" }; + act = getOption(ctor::toolchain::clang, opt::position_independent_code); + uASSERT_EQUAL(exp, act); + + exp = { "-fPIE" }; + act = getOption(ctor::toolchain::clang, opt::position_independent_executable); + uASSERT_EQUAL(exp, act); + + exp = { "-foo" }; + act = getOption(ctor::toolchain::clang, opt::custom, "-foo"); + uASSERT_EQUAL(exp, act); + + exp = { "-o", "foo" }; + act = getOption(ctor::toolchain::gcc, opt::output, "foo"); + uASSERT_EQUAL(exp, act); + + exp = { "-g" }; + act = getOption(ctor::toolchain::gcc, opt::debug); + uASSERT_EQUAL(exp, act); + + exp = { "-s" }; + act = getOption(ctor::toolchain::gcc, opt::strip); + uASSERT_EQUAL(exp, act); + + exp = { "-Wall" }; + act = getOption(ctor::toolchain::gcc, opt::warn_all); + uASSERT_EQUAL(exp, act); + + exp = { "-Werror" }; + act = getOption(ctor::toolchain::gcc, opt::warnings_as_errors); + uASSERT_EQUAL(exp, act); + + exp = { "-MMD" }; + act = getOption(ctor::toolchain::gcc, opt::generate_dep_tree); + uASSERT_EQUAL(exp, act); + + exp = { "-c" }; + act = getOption(ctor::toolchain::gcc, opt::no_link); + uASSERT_EQUAL(exp, act); + + exp = { "-Ifoo" }; + act = getOption(ctor::toolchain::gcc, opt::include_path, "foo"); + uASSERT_EQUAL(exp, act); + + exp = { "-Lfoo" }; + act = getOption(ctor::toolchain::gcc, opt::library_path, "foo"); + uASSERT_EQUAL(exp, act); + + exp = { "-lfoo" }; + act = getOption(ctor::toolchain::gcc, opt::link, "foo"); + uASSERT_EQUAL(exp, act); + + exp = { "-std=foo" }; + act = getOption(ctor::toolchain::gcc, opt::cpp_std, "foo"); + uASSERT_EQUAL(exp, act); + + exp = { "-shared" }; + act = getOption(ctor::toolchain::gcc, opt::build_shared); + uASSERT_EQUAL(exp, act); + + exp = { "-pthread" }; + act = getOption(ctor::toolchain::gcc, opt::threads); + uASSERT_EQUAL(exp, act); + + exp = { "-Ofoo" }; + act = getOption(ctor::toolchain::gcc, opt::optimization, "foo"); + uASSERT_EQUAL(exp, act); + + exp = { "-fPIC" }; + act = getOption(ctor::toolchain::gcc, opt::position_independent_code); + uASSERT_EQUAL(exp, act); + + exp = { "-fPIE" }; + act = getOption(ctor::toolchain::gcc, opt::position_independent_executable); + uASSERT_EQUAL(exp, act); + + exp = { "-foo" }; + act = getOption(ctor::toolchain::gcc, opt::custom, "-foo"); + uASSERT_EQUAL(exp, act); } void getOption_str_test() { - using p = std::pair<opt, std::string>; - uUnit::assert_equal(p{ opt::include_path, "foo" }, getOption("-Ifoo", ToolChain::gcc), __FILE__, __LINE__); - uUnit::assert_equal(p{ opt::library_path, "foo" }, getOption("-Lfoo", ToolChain::gcc), __FILE__, __LINE__); + std::pair<opt, std::string> exp; + std::pair<opt, std::string> act; + + exp = { opt::include_path, "foo" }; + act = getOption("-Ifoo", ctor::toolchain::gcc); + uASSERT_EQUAL(exp, act); + + exp = { opt::library_path, "foo" }; + act = getOption("-Lfoo", ctor::toolchain::gcc); + uASSERT_EQUAL(exp, act); + + exp = { opt::include_path, "foo" }; + act = getOption("-Ifoo", ctor::toolchain::clang); + uASSERT_EQUAL(exp, act); - uUnit::assert_equal(p{ opt::include_path, "foo" }, getOption("-Ifoo", ToolChain::clang), __FILE__, __LINE__); - uUnit::assert_equal(p{ opt::library_path, "foo" }, getOption("-Lfoo", ToolChain::clang), __FILE__, __LINE__); + exp = { opt::library_path, "foo" }; + act = getOption("-Lfoo", ctor::toolchain::clang); + uASSERT_EQUAL(exp, act); } |