summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2022-07-10 17:24:16 +0200
committerBent Bisballe Nyeng <deva@aasimon.org>2022-07-15 10:11:05 +0200
commitae1871ca0ffcac3e8bd337f8d8bb4e7fd6c59295 (patch)
treed15df8a03fab6bdacebb6ba53c8ad30c290781fc
parent2a55edcc40372403fb2de8ed20ed5c44464d416e (diff)
Make tools abstraction around compiler options to better support tool agnostic arguments.
-rw-r--r--ctor.cc1
-rw-r--r--src/bootstrap.cc1
-rw-r--r--src/configure.cc2
-rw-r--r--src/externals_manual.cc17
-rw-r--r--src/externals_manual.h5
-rw-r--r--src/libctor.h1
-rw-r--r--src/rebuild.cc25
-rw-r--r--src/task_cc.cc37
-rw-r--r--src/task_ld.cc16
-rw-r--r--src/task_so.cc15
-rw-r--r--src/tools.cc136
-rw-r--r--src/tools.h52
-rw-r--r--src/util.h6
-rw-r--r--test/ctor.cc18
-rw-r--r--test/tools_test.cc212
15 files changed, 494 insertions, 50 deletions
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<ExternalManual>(ext.external))
{
- if(auto ret = resolv(settings, ext.name,
+ if(auto ret = resolv(settings, ext,
std::get<ExternalManual>(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<std::string, std::string> external_includedir;
extern std::map<std::string, std::string> 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 <string>
-
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<ExternalManual> 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<BuildConfigurationEntry, 1024> 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<std::string>({ "-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<std::string> TaskCC::getCompilerArgs() const
{
+ auto tool_chain = getToolChain(config.system);
+
auto compiler_flags = flags();
std::vector<std::string> 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<std::string> 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<std::string> 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 <filesystem>
+#include <iostream>
+
+#include <cassert>
+
+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<std::string> 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<std::string> 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<opt, std::string> 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<opt, std::string> 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 <vector>
+#include <string>
+
+#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<arg>
+ library_path, // -L<arg>
+ link, // -l<arg>
+ cpp_std, // -std=<arg>
+ build_shared, // -shared
+ threads, // -pthread
+ optimization, // -O<arg>
+ position_independent_code, // -fPIC
+ position_independent_executable, // -fPIE
+ custom, // entire option taken verbatim from <arg>
+};
+
+//! 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<std::string> 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<opt, std::string> 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<std::string> readDeps(const std::string& depFile);
Language languageFromExtension(const std::filesystem::path& file);
std::string cleanUp(const std::string& path);
+
+template<typename T>
+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
@@ -61,6 +61,23 @@ BuildConfigurations ctorTestConfigs(const Settings& settings)
},
},
{
+ .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",
.sources = {
@@ -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 <uunit.h>
+
+#include <initializer_list>
+#include <cassert>
+
+#include <tools.h>
+
+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<std::string>& 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<opt, std::string>& 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<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__);
+ }
+
+ 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__);
+
+ 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;