From ae1871ca0ffcac3e8bd337f8d8bb4e7fd6c59295 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Sun, 10 Jul 2022 17:24:16 +0200 Subject: Make tools abstraction around compiler options to better support tool agnostic arguments. --- ctor.cc | 1 + src/bootstrap.cc | 1 + src/configure.cc | 2 +- src/externals_manual.cc | 17 ++-- src/externals_manual.h | 5 +- src/libctor.h | 1 + src/rebuild.cc | 25 ++++-- src/task_cc.cc | 37 +++++---- src/task_ld.cc | 16 ++-- src/task_so.cc | 15 ++-- src/tools.cc | 136 +++++++++++++++++++++++++++++++ src/tools.h | 52 ++++++++++++ src/util.h | 6 ++ test/ctor.cc | 18 ++++ test/tools_test.cc | 212 ++++++++++++++++++++++++++++++++++++++++++++++++ 15 files changed, 494 insertions(+), 50 deletions(-) create mode 100644 src/tools.cc create mode 100644 src/tools.h create mode 100644 test/tools_test.cc diff --git a/ctor.cc b/ctor.cc index d795ff9..445f18a 100644 --- a/ctor.cc +++ b/ctor.cc @@ -26,6 +26,7 @@ BuildConfigurations ctorConfigs(const Settings& settings) "src/task_ld.cc", "src/task_so.cc", "src/tasks.cc", + "src/tools.cc", "src/util.cc", "src/unittest.cc", }, diff --git a/src/bootstrap.cc b/src/bootstrap.cc index 6e4ef19..9a3c321 100644 --- a/src/bootstrap.cc +++ b/src/bootstrap.cc @@ -16,6 +16,7 @@ #include "execute.cc" #include "tasks.cc" #include "build.cc" +#include "tools.cc" std::filesystem::path configurationFile("configuration.cc"); std::filesystem::path configHeaderFile("config.h"); diff --git a/src/configure.cc b/src/configure.cc index bc7d3e8..a81f8ad 100644 --- a/src/configure.cc +++ b/src/configure.cc @@ -427,7 +427,7 @@ int regenerateCache(const Settings& default_settings, Flags resolved_flags; if(std::holds_alternative(ext.external)) { - if(auto ret = resolv(settings, ext.name, + if(auto ret = resolv(settings, ext, std::get(ext.external), resolved_flags)) { diff --git a/src/externals_manual.cc b/src/externals_manual.cc index 79c9be3..0e3cdfd 100644 --- a/src/externals_manual.cc +++ b/src/externals_manual.cc @@ -7,25 +7,30 @@ #include "libctor.h" +#include "util.h" +#include "tools.h" + extern std::map external_includedir; extern std::map external_libdir; -int resolv(const Settings& settings, const std::string& name, +int resolv(const Settings& settings, const ExternalConfiguration& config, const ExternalManual& ext, Flags& flags) { + auto tool_chain = getToolChain(config.system); + flags = ext.flags; - auto inc = external_includedir.find(name); + auto inc = external_includedir.find(config.name); if(inc != external_includedir.end()) { - flags.cflags.push_back("-I" + inc->second); - flags.cxxflags.push_back("-I" + inc->second); + append(flags.cflags, getOption(tool_chain, opt::include_path, inc->second)); + append(flags.cxxflags, getOption(tool_chain, opt::include_path, inc->second)); } - auto lib = external_libdir.find(name); + auto lib = external_libdir.find(config.name); if(lib != external_libdir.end()) { - flags.ldflags.push_back("-L" + lib->second); + append(flags.ldflags, getOption(tool_chain, opt::library_path, lib->second)); } return 0; diff --git a/src/externals_manual.h b/src/externals_manual.h index c7e3b9a..7bd968d 100644 --- a/src/externals_manual.h +++ b/src/externals_manual.h @@ -3,11 +3,10 @@ // See accompanying file LICENSE for details. #pragma once -#include - struct Settings; +struct ExternalConfiguration; struct ExternalManual; struct Flags; -int resolv(const Settings& settings, const std::string& name, +int resolv(const Settings& settings, const ExternalConfiguration& name, const ExternalManual& ext, Flags& flags); diff --git a/src/libctor.h b/src/libctor.h index 14fdf1d..96e1115 100644 --- a/src/libctor.h +++ b/src/libctor.h @@ -105,6 +105,7 @@ struct ExternalManual struct ExternalConfiguration { std::string name; // Name for configuration + OutputSystem system{OutputSystem::Host}; std::variant external; }; diff --git a/src/rebuild.cc b/src/rebuild.cc index 3e0e78d..a82e0cc 100644 --- a/src/rebuild.cc +++ b/src/rebuild.cc @@ -13,6 +13,8 @@ #include "tasks.h" #include "build.h" #include "execute.h" +#include "tools.h" +#include "util.h" std::array configFiles; std::size_t numConfigFiles{0}; @@ -143,19 +145,28 @@ bool recompileCheck(const Settings& global_settings, int argc, char* argv[], BuildConfiguration config; config.name = "ctor"; - config.flags.cxxflags = - std::vector({ "-s", "-O3", "-std=c++20" }); + config.system = OutputSystem::Build; + + auto tool_chain = getToolChain(config.system); + + append(config.flags.cxxflags, + getOption(tool_chain, opt::optimization, "3")); + append(config.flags.cxxflags, + getOption(tool_chain, opt::cpp_std, "c++20")); if(hasConfiguration(cfg::ctor_includedir)) { - config.flags.cxxflags.push_back("-I"s + getConfiguration(cfg::ctor_includedir)); + append(config.flags.cxxflags, + getOption(tool_chain, opt::include_path, + getConfiguration(cfg::ctor_includedir))); } if(hasConfiguration(cfg::ctor_libdir)) { - config.flags.ldflags.push_back("-L"s + getConfiguration(cfg::ctor_libdir)); + append(config.flags.ldflags, + getOption(tool_chain, opt::library_path, + getConfiguration(cfg::ctor_libdir))); } - config.flags.ldflags.push_back("-lctor"); - config.flags.ldflags.push_back("-pthread"); - + append(config.flags.ldflags, getOption(tool_chain, opt::link, "ctor")); + append(config.flags.ldflags, getOption(tool_chain, opt::threads)); Settings settings{global_settings}; settings.verbose = -1; // Make check completely silent. diff --git a/src/task_cc.cc b/src/task_cc.cc index a55a619..c2dd5d6 100644 --- a/src/task_cc.cc +++ b/src/task_cc.cc @@ -10,6 +10,7 @@ #include "libctor.h" #include "execute.h" #include "util.h" +#include "tools.h" TaskCC::TaskCC(const BuildConfiguration& config, const Settings& settings, const std::string& sourceDir, const Source& source) @@ -267,39 +268,41 @@ std::string TaskCC::flagsString() const std::vector TaskCC::getCompilerArgs() const { + auto tool_chain = getToolChain(config.system); + auto compiler_flags = flags(); std::vector args; - args.push_back("-MMD"); + append(args, getOption(tool_chain, opt::generate_dep_tree)); if(std::filesystem::path(config.target).extension() == ".so") { // Add -fPIC arg to all contained object files - args.push_back("-fPIC"); + append(args, getOption(tool_chain, opt::position_independent_code)); } - args.push_back("-c"); + append(args, getOption(tool_chain, opt::no_link)); args.push_back(sourceFile.string()); - args.push_back("-o"); - args.push_back(targetFile().string()); + append(args, getOption(tool_chain, opt::output, targetFile().string())); for(const auto& flag : compiler_flags) { - // Is arg an added include path? - if(flag.substr(0, 2) == "-I") + auto option = getOption(flag); + switch(option.first) { - std::string include_path = flag.substr(2); - include_path.erase(0, include_path.find_first_not_of(' ')); - std::filesystem::path path(include_path); - - // Is it relative? - if(path.is_relative()) + // Relative include paths has to be altered to be relative to sourceDir + case opt::include_path: { - path = (sourceDir / path).lexically_normal(); - std::string new_include_path = "-I" + path.string(); - args.push_back(new_include_path); - continue; + std::filesystem::path path(option.second); + if(path.is_relative()) + { + path = (sourceDir / path).lexically_normal(); + append(args, getOption(tool_chain, opt::include_path, path.string())); + } } + continue; + default: + break; } args.push_back(flag); diff --git a/src/task_ld.cc b/src/task_ld.cc index df50001..20e823d 100644 --- a/src/task_ld.cc +++ b/src/task_ld.cc @@ -9,6 +9,7 @@ #include "libctor.h" #include "execute.h" #include "util.h" +#include "tools.h" TaskLD::TaskLD(const BuildConfiguration& config, const Settings& settings, @@ -81,15 +82,18 @@ bool TaskLD::dirtyInner() int TaskLD::runInner() { + auto tool_chain = getToolChain(config.system); + std::vector args; for(const auto& dep : getDependsTasks()) { auto depFile = dep->targetFile(); if(depFile.extension() == ".so") { - args.push_back(std::string("-L") + targetFile().parent_path().string()); + append(args, getOption(tool_chain, opt::library_path, + targetFile().parent_path().string())); auto lib = depFile.stem().string().substr(3); // strip 'lib' prefix - args.push_back(std::string("-l") + lib); + append(args, getOption(tool_chain, opt::link, lib)); } else if(depFile.extension() == ".a" || depFile.extension() == ".o") { @@ -97,12 +101,8 @@ int TaskLD::runInner() } } - for(const auto& flag : config.flags.ldflags) - { - args.push_back(flag); - } - args.push_back("-o"); - args.push_back(targetFile().string()); + append(args, config.flags.ldflags); + append(args, getOption(tool_chain, opt::output, targetFile().string())); { // Write flags to file. std::ofstream flagsStream(flagsFile); diff --git a/src/task_so.cc b/src/task_so.cc index 2bd27c4..8c6dbd4 100644 --- a/src/task_so.cc +++ b/src/task_so.cc @@ -9,6 +9,7 @@ #include "libctor.h" #include "execute.h" #include "util.h" +#include "tools.h" TaskSO::TaskSO(const BuildConfiguration& config, const Settings& settings, @@ -78,23 +79,21 @@ bool TaskSO::dirtyInner() int TaskSO::runInner() { + auto tool_chain = getToolChain(config.system); + std::vector args; - args.push_back("-fPIC"); - args.push_back("-shared"); + append(args, getOption(tool_chain, opt::position_independent_code)); + append(args, getOption(tool_chain, opt::build_shared)); - args.push_back("-o"); - args.push_back(targetFile().string()); + append(args, getOption(tool_chain, opt::output, targetFile().string())); for(const auto& task : getDependsTasks()) { args.push_back(task->targetFile().string()); } - for(const auto& flag : config.flags.ldflags) - { - args.push_back(flag); - } + append(args, config.flags.ldflags); { // Write flags to file. std::ofstream flagsStream(flagsFile); diff --git a/src/tools.cc b/src/tools.cc new file mode 100644 index 0000000..7e8ac78 --- /dev/null +++ b/src/tools.cc @@ -0,0 +1,136 @@ +// -*- c++ -*- +// Distributed under the BSD 2-Clause License. +// See accompanying file LICENSE for details. +#include "tools.h" + +#include +#include + +#include + +ToolChain getToolChain(OutputSystem system) +{ + std::string compiler; + switch(system) + { + case OutputSystem::Host: + compiler = getConfiguration(cfg::host_cxx, "g++"); + break; + case OutputSystem::Build: + compiler = getConfiguration(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; + } + else if(cc_cmd.find("g++") != std::string::npos) + { + return ToolChain::gcc; + } + + std::cerr << "Unsupported output system.\n"; + return ToolChain::gcc; +} + +namespace +{ +std::vector getOptionGcc(opt option, const std::string& arg) +{ + switch(option) + { + case opt::output: + return {"-o", arg}; + case opt::debug: + return {"-g"}; + case opt::strip: + return {"-s"}; + case opt::warn_all: + return {"-Wall"}; + case opt::warnings_as_errors: + return {"-Werror"}; + case opt::generate_dep_tree: + return {"-MMD"}; + case opt::no_link: + return {"-c"}; + case opt::include_path: + return {"-I" + arg}; + case opt::library_path: + return {"-L" + arg}; + case opt::link: + return {"-l" + arg}; + case opt::cpp_std: + return {"-std=" + arg}; + case opt::build_shared: + return {"-shared"}; + case opt::threads: + return {"-pthread"}; + case opt::optimization: + return {"-O" + arg}; + case opt::position_independent_code: + return {"-fPIC"}; + case opt::position_independent_executable: + return {"-fPIE"}; + case opt::custom: + return {arg}; + } + + std::cerr << "Unsupported compiler option.\n"; + return {}; +} +} + +std::vector getOption(ToolChain tool_chain, + opt option, + const std::string& arg) +{ + switch(tool_chain) + { + case ToolChain::gcc: + case ToolChain::clang: + return getOptionGcc(option, arg); + } + + std::cerr << "Unsupported tool-chain.\n"; + return {}; +} + +namespace { +std::pair getOptionGcc(const std::string& flag) +{ + if(flag.substr(0, 2) == "-I") + { + std::string path = flag.substr(2); + path.erase(0, path.find_first_not_of(' ')); + return { opt::include_path, path }; + } + + if(flag.substr(0, 2) == "-L") + { + std::string path = flag.substr(2); + path.erase(0, path.find_first_not_of(' ')); + return { opt::library_path, path }; + } + + return { opt::custom, flag }; +} +} + +std::pair getOption(const std::string& flag, + ToolChain tool_chain) +{ + switch(tool_chain) + { + case ToolChain::gcc: + case ToolChain::clang: + return getOptionGcc(flag); + } + + std::cerr << "Unsupported tool-chain.\n"; + return { opt::custom, flag }; +} diff --git a/src/tools.h b/src/tools.h new file mode 100644 index 0000000..39118d2 --- /dev/null +++ b/src/tools.h @@ -0,0 +1,52 @@ +// -*- c++ -*- +// Distributed under the BSD 2-Clause License. +// See accompanying file LICENSE for details. +#pragma once + +#include +#include + +#include "libctor.h" + +enum class ToolChain +{ + gcc, + clang, +}; + +enum class opt +{ + // gcc/clang + output, // -o + debug, // -g + strip, // -s + warn_all, // -Wall + warnings_as_errors, // -Werror + generate_dep_tree, // -MMD + no_link, // -c + include_path, // -I + library_path, // -L + link, // -l + cpp_std, // -std= + build_shared, // -shared + threads, // -pthread + optimization, // -O + position_independent_code, // -fPIC + position_independent_executable, // -fPIE + custom, // entire option taken verbatim from +}; + +//! Get tool-chain type from output system (via configuration) +ToolChain getToolChain(OutputSystem system); + +//! Get tool argument(s) for specific option type matching the supplied +//! tool-chain +std::vector getOption(ToolChain tool_chain, + opt option, + const std::string& arg = {}); + +//! Get opt enum value and argument from string, +//! ie. { opt::InludePath, "foo/bar" } from "-Ifoo/bar" +//! Returns { opt::Custom, flag } if unknown. +std::pair getOption(const std::string& flag, + ToolChain tool_chain = ToolChain::gcc); diff --git a/src/util.h b/src/util.h index d164fbf..c8b591a 100644 --- a/src/util.h +++ b/src/util.h @@ -12,3 +12,9 @@ std::string readFile(const std::string& fileName); std::vector readDeps(const std::string& depFile); Language languageFromExtension(const std::filesystem::path& file); std::string cleanUp(const std::string& path); + +template +void append(T& a, const T& b) +{ + a.insert(a.end(), b.begin(), b.end()); +} diff --git a/test/ctor.cc b/test/ctor.cc index c24ded7..9b690a2 100644 --- a/test/ctor.cc +++ b/test/ctor.cc @@ -60,6 +60,23 @@ BuildConfigurations ctorTestConfigs(const Settings& settings) .ldflags = { "-pthread" }, }, }, + { + .type = TargetType::UnitTest, + .target = "tools_test", + .sources = { + "tools_test.cc", + "testmain.cc", + "../src/tools.cc", + }, + //.depends = { "libctor_nomain.a" }, + .flags = { + .cxxflags = { + "-std=c++20", "-O3", "-Wall", "-Werror", + "-I../src", "-Iuunit", + "-DOUTPUT=\"tools\"", + }, + }, + }, { .type = TargetType::UnitTestLib, .target = "libctor_nomain.a", @@ -75,6 +92,7 @@ BuildConfigurations ctorTestConfigs(const Settings& settings) "../src/task_fn.cc", "../src/task_ld.cc", "../src/task_so.cc", + "../src/tools.cc", "../src/util.cc", "../src/externals_manual.cc", }, diff --git a/test/tools_test.cc b/test/tools_test.cc new file mode 100644 index 0000000..3e9de1b --- /dev/null +++ b/test/tools_test.cc @@ -0,0 +1,212 @@ +#include + +#include +#include + +#include + +using namespace std::string_literals; + +namespace +{ +std::ostream& operator<<(std::ostream& stream, const ToolChain& tool_chain) +{ + switch(tool_chain) + { + case ToolChain::gcc: + stream << "ToolChain::gcc"; + break; + case ToolChain::clang: + stream << "ToolChain::clang"; + break; + } + return stream; +} + +std::ostream& operator<<(std::ostream& stream, const std::vector& vs) +{ + bool first{true}; + stream << "{ "; + for(const auto& v : vs) + { + if(!first) + { + stream << ", "; + } + stream << "'" << v << "'"; + first = false; + } + stream << " }"; + + return stream; +} + +std::ostream& operator<<(std::ostream& stream, opt o) +{ + // Adding to this enum should also imply adding to the unit-tests below + switch(o) + { + case opt::output: stream << "opt::output"; break; + case opt::debug: stream << "opt::debug"; break; + case opt::strip: stream << "opt::strip"; break; + case opt::warn_all: stream << "opt::warn_all"; break; + case opt::warnings_as_errors: stream << "opt::warnings_as_errors"; break; + case opt::generate_dep_tree: stream << "opt::generate_dep_tree"; break; + case opt::no_link: stream << "opt::no_link"; break; + case opt::include_path: stream << "opt::include_path"; break; + case opt::library_path: stream << "opt::library_path"; break; + case opt::link: stream << "opt::link"; break; + case opt::cpp_std: stream << "opt::cpp_std"; break; + case opt::build_shared: stream << "opt::build_shared"; break; + case opt::threads: stream << "opt::threads"; break; + case opt::optimization: stream << "opt::optimization"; break; + case opt::position_independent_code: stream << "opt::position_independent_code"; break; + case opt::position_independent_executable: stream << "opt::position_independent_executable"; break; + case opt::custom: stream << "opt::custom"; break; + } + + return stream; +} + +std::ostream& operator<<(std::ostream& stream, const std::pair& vs) +{ + stream << "{ " << vs.first << ", " << vs.second << " }"; + + return stream; +} +} + +// Controllable getConfiguration stub: +namespace +{ +std::string conf_host_cxx{}; +std::string conf_build_cxx{}; +} +const std::string& getConfiguration(const std::string& key, + const std::string& defval) +{ + if(key == cfg::host_cxx) + { + return conf_host_cxx; + } + + if(key == cfg::build_cxx) + { + return conf_build_cxx; + } + + assert(false); // bad key + + static std::string res{}; + return res; +} + +class ToolsTest + : public uUnit +{ +public: + ToolsTest() + { + uTEST(ToolsTest::getToolChain_test); + uTEST(ToolsTest::getOption_toolchain_test); + uTEST(ToolsTest::getOption_str_test); + } + + void getToolChain_test() + { + // host + conf_host_cxx = "/usr/bin/g++"; + uASSERT_EQUAL(ToolChain::gcc, getToolChain(OutputSystem::Host)); + + conf_host_cxx = "/usr/bin/g++-10"; + uASSERT_EQUAL(ToolChain::gcc, getToolChain(OutputSystem::Host)); + + conf_host_cxx = "/usr/bin/x86_64-pc-linux-gnu-g++-9.3.0"; + uASSERT_EQUAL(ToolChain::gcc, getToolChain(OutputSystem::Host)); + + conf_host_cxx = "/usr/bin/clang++"; + uASSERT_EQUAL(ToolChain::clang, getToolChain(OutputSystem::Host)); + + conf_host_cxx = "/usr/bin/clang++-10"; + uASSERT_EQUAL(ToolChain::clang, getToolChain(OutputSystem::Host)); + + conf_host_cxx = "/usr/lib/llvm/12/bin/i686-pc-linux-gnu-clang++-12"; + uASSERT_EQUAL(ToolChain::clang, getToolChain(OutputSystem::Host)); + + // build + conf_build_cxx = "/usr/bin/g++"; + uASSERT_EQUAL(ToolChain::gcc, getToolChain(OutputSystem::Build)); + + conf_build_cxx = "/usr/bin/g++-10"; + uASSERT_EQUAL(ToolChain::gcc, getToolChain(OutputSystem::Build)); + + conf_build_cxx = "/usr/bin/x86_64-pc-linux-gnu-g++-9.3.0"; + uASSERT_EQUAL(ToolChain::gcc, getToolChain(OutputSystem::Build)); + + conf_build_cxx = "/usr/bin/clang++"; + uASSERT_EQUAL(ToolChain::clang, getToolChain(OutputSystem::Build)); + + conf_build_cxx = "/usr/bin/clang++-10"; + uASSERT_EQUAL(ToolChain::clang, getToolChain(OutputSystem::Build)); + + conf_build_cxx = "/usr/lib/llvm/12/bin/i686-pc-linux-gnu-clang++-12"; + uASSERT_EQUAL(ToolChain::clang, getToolChain(OutputSystem::Build)); + } + + void getOption_toolchain_test() + { + using sv = std::vector; + + 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__); + } + + void getOption_str_test() + { + using p = std::pair; + 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__); + + 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__); + } + + + +}; + +// Registers the fixture into the 'registry' +static ToolsTest test; -- cgit v1.2.3