From 916060cb53fddb94f64b20d3616e7360c5e91f64 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Fri, 13 Jan 2023 19:56:35 +0100 Subject: Capture flags in a class instead of a string and add conversion functions between them. --- src/configure.cc | 44 +++- src/ctor.h | 86 +++++++- src/externals_manual.cc | 8 +- src/rebuild.cc | 20 +- src/task_ar.cc | 13 +- src/task_cc.cc | 116 +++++++--- src/task_ld.cc | 24 ++- src/task_so.cc | 25 ++- src/tools.cc | 560 ++++++++++++++++++++++++++++++++++++++++++++---- src/tools.h | 83 ++++++- src/util.h | 5 + 11 files changed, 867 insertions(+), 117 deletions(-) (limited to 'src') diff --git a/src/configure.cc b/src/configure.cc index deeb6a6..34812fa 100644 --- a/src/configure.cc +++ b/src/configure.cc @@ -191,6 +191,42 @@ std::ostream& operator<<(std::ostream& stream, const ctor::toolchain& toolchain) } 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 @@ -521,7 +557,7 @@ int regenerateCache(ctor::settings& settings, istr << " .cxxflags = {"; for(const auto& flag : resolved_flags.cxxflags) { - istr << "\"" << flag << "\","; + istr << flag << ","; } istr << "},\n"; } @@ -531,7 +567,7 @@ int regenerateCache(ctor::settings& settings, istr << " .cflags = {"; for(const auto& flag : resolved_flags.cflags) { - istr << "\"" << flag << "\","; + istr << flag << ","; } istr << "},\n"; } @@ -541,7 +577,7 @@ int regenerateCache(ctor::settings& settings, istr << " .ldflags = {"; for(const auto& flag : resolved_flags.ldflags) { - istr << "\"" << flag << "\","; + istr << flag << ","; } istr << "},\n"; } @@ -551,7 +587,7 @@ int regenerateCache(ctor::settings& settings, istr << " .asmflags = {"; for(const auto& flag : resolved_flags.asmflags) { - istr << "\"" << flag << "\","; + istr << flag << ","; } istr << "},\n"; } diff --git a/src/ctor.h b/src/ctor.h index 388ec1b..36aa46a 100644 --- a/src/ctor.h +++ b/src/ctor.h @@ -66,34 +66,106 @@ enum class toolchain clang, }; -enum class opt +enum class cxx_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 + cpp_std, // -std= + optimization, // -O + position_independent_code, // -fPIC + position_independent_executable, // -fPIE + custom, // entire option taken verbatim from +}; + +enum class c_opt +{ + // gcc/clang + output, // -o + debug, // -g + warn_all, // -Wall + warnings_as_errors, // -Werror + generate_dep_tree, // -MMD + no_link, // -c + include_path, // -I + c_std, // -std= + optimization, // -O + position_independent_code, // -fPIC + position_independent_executable, // -fPIE + custom, // entire option taken verbatim from +}; + +enum class ld_opt +{ + // gcc/clang + output, // -o + strip, // -s + warn_all, // -Wall + warnings_as_errors, // -Werror 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 }; +enum class ar_opt +{ + // gcc/clang + custom, // entire option taken verbatim from +}; + +enum class asm_opt +{ + // gcc/clang + custom, // entire option taken verbatim from +}; + +template +class flag +{ +public: + flag(const std::string& str); + flag(const char* str); + flag(T opt) : opt(opt) {} + flag(T opt, const std::string& arg) : opt(opt), arg(arg) {} + flag(T opt, const char* arg) : opt(opt), arg(arg) {} + flag(ctor::toolchain toolchain, T opt) : toolchain(toolchain), opt(opt) {} + flag(ctor::toolchain toolchain, T opt, const char* arg) : toolchain(toolchain), opt(opt), arg(arg) {} + flag(ctor::toolchain toolchain, T opt, const std::string& arg) : toolchain(toolchain), opt(opt), arg(arg) {} + + ctor::toolchain toolchain{ctor::toolchain::any}; + T opt; + std::string arg; +}; + +using c_flag = ctor::flag; +using cxx_flag = ctor::flag; +using ld_flag = ctor::flag; +using ar_flag = ctor::flag; +using asm_flag = ctor::flag; + +using c_flags = std::vector; +using cxx_flags = std::vector; +using ld_flags= std::vector; +using ar_flags = std::vector; +using asm_flags = std::vector; + struct flags { - std::vector cxxflags; // flags for c++ compiler - std::vector cflags; // flags for c compiler - std::vector ldflags; // flags for linker - std::vector asmflags; // flags for asm translator + ctor::c_flags cflags; // flags for c compiler + ctor::cxx_flags cxxflags; // flags for c++ compiler + ctor::ld_flags ldflags; // flags for linker + ctor::ar_flags arflags; // flags for archiver + ctor::asm_flags asmflags; // flags for asm translator }; struct settings diff --git a/src/externals_manual.cc b/src/externals_manual.cc index bc8e9d0..3b96263 100644 --- a/src/externals_manual.cc +++ b/src/externals_manual.cc @@ -16,21 +16,19 @@ extern std::map external_libdir; int resolv(const ctor::settings& settings, const ctor::external_configuration& config, const ctor::external_manual& ext, ctor::flags& flags) { - auto toolchain = getToolChain(config.system); - flags = ext.flags; auto inc = external_includedir.find(config.name); if(inc != external_includedir.end()) { - append(flags.cflags, getOption(toolchain, ctor::opt::include_path, inc->second)); - append(flags.cxxflags, getOption(toolchain, ctor::opt::include_path, inc->second)); + flags.cflags.push_back({ctor::c_opt::include_path, inc->second}); + flags.cxxflags.push_back({ctor::cxx_opt::include_path, inc->second}); } auto lib = external_libdir.find(config.name); if(lib != external_libdir.end()) { - append(flags.ldflags, getOption(toolchain, ctor::opt::library_path, lib->second)); + flags.ldflags.push_back({ctor::ld_opt::library_path, lib->second}); } return 0; diff --git a/src/rebuild.cc b/src/rebuild.cc index dec7119..c97452d 100644 --- a/src/rebuild.cc +++ b/src/rebuild.cc @@ -162,27 +162,21 @@ bool recompileCheck(const ctor::settings& global_settings, int argc, char* argv[ config.name = "ctor"; config.system = ctor::output_system::build; - auto toolchain = getToolChain(config.system); + config.flags.cxxflags.push_back({ctor::cxx_opt::optimization, "3"}); + config.flags.cxxflags.push_back({ctor::cxx_opt::cpp_std, "c++20"}); - append(config.flags.cxxflags, - getOption(toolchain, ctor::opt::optimization, "3")); - append(config.flags.cxxflags, - getOption(toolchain, ctor::opt::cpp_std, "c++20")); const auto& c = ctor::get_configuration(); if(c.has(ctor::cfg::ctor_includedir)) { - append(config.flags.cxxflags, - getOption(toolchain, ctor::opt::include_path, - c.get(ctor::cfg::ctor_includedir))); + config.flags.cxxflags.push_back({ctor::cxx_opt::include_path, + c.get(ctor::cfg::ctor_includedir)}); } if(c.has(ctor::cfg::ctor_libdir)) { - append(config.flags.ldflags, - getOption(toolchain, ctor::opt::library_path, - c.get(ctor::cfg::ctor_libdir))); + config.flags.ldflags.push_back({ctor::ld_opt::library_path, c.get(ctor::cfg::ctor_libdir)}); } - append(config.flags.ldflags, getOption(toolchain, ctor::opt::link, "ctor")); - append(config.flags.ldflags, getOption(toolchain, ctor::opt::threads)); + config.flags.ldflags.push_back({ctor::ld_opt::link, "ctor"}); + config.flags.ldflags.push_back({ctor::ld_opt::threads}); ctor::settings settings{global_settings}; settings.verbose = -1; // Make check completely silent. diff --git a/src/task_ar.cc b/src/task_ar.cc index edd60ae..81ced0f 100644 --- a/src/task_ar.cc +++ b/src/task_ar.cc @@ -9,6 +9,7 @@ #include "ctor.h" #include "execute.h" #include "util.h" +#include "tools.h" TaskAR::TaskAR(const ctor::build_configuration& config, const ctor::settings& settings, @@ -160,14 +161,20 @@ bool TaskAR::derived() const std::string TaskAR::flagsString() const { + auto toolchain = getToolChain(config.system); std::string flagsStr; + bool first{true}; for(const auto& flag : config.flags.ldflags) { - if(flag != config.flags.ldflags[0]) + for(const auto& str : to_strings(toolchain, flag)) { - flagsStr += " "; + if(first) + { + flagsStr += " "; + first = false; + } + flagsStr += str; } - flagsStr += flag; } flagsStr += "\n"; diff --git a/src/task_cc.cc b/src/task_cc.cc index c15bd6a..56915f5 100644 --- a/src/task_cc.cc +++ b/src/task_cc.cc @@ -256,12 +256,23 @@ std::string TaskCC::source() const std::vector TaskCC::flags() const { + std::vector flags; + auto toolchain = getToolChain(config.system); + switch(sourceLanguage()) { case ctor::language::c: - return config.flags.cflags; + for(const auto& flag : config.flags.cflags) + { + append(flags, to_strings(toolchain, flag)); + } + return flags; case ctor::language::cpp: - return config.flags.cxxflags; + for(const auto& flag : config.flags.cxxflags) + { + append(flags, to_strings(toolchain, flag)); + } + return flags; default: std::cerr << "Unknown CC target type\n"; exit(1); @@ -285,39 +296,96 @@ std::vector TaskCC::getCompilerArgs() const auto compiler_flags = flags(); std::vector args; - append(args, getOption(toolchain, ctor::opt::generate_dep_tree)); - if(std::filesystem::path(config.target).extension() == ".so") + switch(sourceLanguage()) { - // Add -fPIC arg to all contained object files - append(args, getOption(toolchain, ctor::opt::position_independent_code)); - } + case ctor::language::c: + { + append(args, c_option(toolchain, ctor::c_opt::generate_dep_tree)); - append(args, getOption(toolchain, ctor::opt::no_link)); - args.push_back(sourceFile.string()); - append(args, getOption(toolchain, ctor::opt::output, targetFile().string())); + if(std::filesystem::path(config.target).extension() == ".so") + { + // Add -fPIC arg to all contained object files + append(args, c_option(toolchain, + ctor::c_opt::position_independent_code)); + } - for(const auto& flag : compiler_flags) - { - auto option = getOption(flag); - switch(option.first) + append(args, c_option(toolchain, ctor::c_opt::no_link)); + args.push_back(sourceFile.string()); + append(args, c_option(toolchain, + ctor::c_opt::output, targetFile().string())); + + // Relative include paths has to be altered to be relative to sourceDir + for(const auto& flag : compiler_flags) + { + auto option = c_option(flag, toolchain); + switch(option.opt) + { + case ctor::c_opt::include_path: + { + std::filesystem::path path(option.arg); + if(path.is_relative()) + { + path = (sourceDir / path).lexically_normal(); + append(args, c_option(toolchain, + ctor::c_opt::include_path, path.string())); + } + } + break; + default: + break; + } + + args.push_back(flag); + } + } + break; + + case ctor::language::cpp: { - // Relative include paths has to be altered to be relative to sourceDir - case ctor::opt::include_path: + append(args, cxx_option(toolchain, ctor::cxx_opt::generate_dep_tree)); + + if(std::filesystem::path(config.target).extension() == ".so") { - std::filesystem::path path(option.second); - if(path.is_relative()) + // Add -fPIC arg to all contained object files + append(args, cxx_option(toolchain, + ctor::cxx_opt::position_independent_code)); + } + + append(args, cxx_option(toolchain, ctor::cxx_opt::no_link)); + args.push_back(sourceFile.string()); + append(args, cxx_option(toolchain, + ctor::cxx_opt::output, targetFile().string())); + + // Relative include paths has to be altered to be relative to sourceDir + for(const auto& flag : compiler_flags) + { + auto option = cxx_option(flag, toolchain); + switch(option.opt) { - path = (sourceDir / path).lexically_normal(); - append(args, getOption(toolchain, ctor::opt::include_path, path.string())); + case ctor::cxx_opt::include_path: + { + std::filesystem::path path(option.arg); + if(path.is_relative()) + { + path = (sourceDir / path).lexically_normal(); + append(args, cxx_option(toolchain, + ctor::cxx_opt::include_path, path.string())); + } + } + break; + default: + break; } + + args.push_back(flag); } - continue; - default: - break; + } + break; - args.push_back(flag); + default: + break; } return args; diff --git a/src/task_ld.cc b/src/task_ld.cc index 4915de9..3d917e4 100644 --- a/src/task_ld.cc +++ b/src/task_ld.cc @@ -90,10 +90,10 @@ int TaskLD::runInner() auto depFile = dep->targetFile(); if(depFile.extension() == ".so") { - append(args, getOption(toolchain, ctor::opt::library_path, + append(args, ld_option(toolchain, ctor::ld_opt::library_path, targetFile().parent_path().string())); auto lib = depFile.stem().string().substr(3); // strip 'lib' prefix - append(args, getOption(toolchain, ctor::opt::link, lib)); + append(args, ld_option(toolchain, ctor::ld_opt::link, lib)); } else if(depFile.extension() == ".a" || depFile.extension() == ".o") { @@ -101,8 +101,12 @@ int TaskLD::runInner() } } - append(args, config.flags.ldflags); - append(args, getOption(toolchain, ctor::opt::output, targetFile().string())); + for(const auto& flag : config.flags.ldflags) + { + append(args, to_strings(toolchain, flag)); + } + + append(args, ld_option(toolchain, ctor::ld_opt::output, targetFile().string())); { // Write flags to file. std::ofstream flagsStream(flagsFile); @@ -168,14 +172,20 @@ bool TaskLD::derived() const std::string TaskLD::flagsString() const { + auto toolchain = getToolChain(config.system); std::string flagsStr; + bool first{true}; for(const auto& flag : config.flags.ldflags) { - if(flag != config.flags.ldflags[0]) + for(const auto& str : to_strings(toolchain, flag)) { - flagsStr += " "; + if(first) + { + flagsStr += " "; + first = false; + } + flagsStr += str; } - flagsStr += flag; } flagsStr += "\n"; diff --git a/src/task_so.cc b/src/task_so.cc index 93a5ddb..9061591 100644 --- a/src/task_so.cc +++ b/src/task_so.cc @@ -83,17 +83,20 @@ int TaskSO::runInner() std::vector args; - append(args, getOption(toolchain, ctor::opt::position_independent_code)); - append(args, getOption(toolchain, ctor::opt::build_shared)); + append(args, ld_option(toolchain, ctor::ld_opt::position_independent_code)); + append(args, ld_option(toolchain, ctor::ld_opt::build_shared)); - append(args, getOption(toolchain, ctor::opt::output, targetFile().string())); + append(args, ld_option(toolchain, ctor::ld_opt::output, targetFile().string())); for(const auto& task : getDependsTasks()) { args.push_back(task->targetFile().string()); } - append(args, config.flags.ldflags); + for(const auto& flag : config.flags.ldflags) + { + append(args, to_strings(toolchain, flag)); + } { // Write flags to file. std::ofstream flagsStream(flagsFile); @@ -159,10 +162,20 @@ bool TaskSO::derived() const std::string TaskSO::flagsString() const { - std::string flagsStr = compiler(); + auto toolchain = getToolChain(config.system); + std::string flagsStr; + bool first{true}; for(const auto& flag : config.flags.ldflags) { - flagsStr += " " + flag; + for(const auto& str : to_strings(toolchain, flag)) + { + if(first) + { + flagsStr += " "; + first = false; + } + flagsStr += str; + } } flagsStr += "\n"; diff --git a/src/tools.cc b/src/tools.cc index 610a550..476386b 100644 --- a/src/tools.cc +++ b/src/tools.cc @@ -5,9 +5,98 @@ #include #include +#include #include +std::ostream& operator<<(std::ostream& stream, const ctor::c_opt& opt) +{ + // Adding to this enum should also imply adding to the unit-tests below + switch(opt) + { + case ctor::c_opt::output: stream << "ctor::c_opt::output"; break; + case ctor::c_opt::debug: stream << "ctor::c_opt::debug"; break; + case ctor::c_opt::warn_all: stream << "ctor::c_opt::warn_all"; break; + case ctor::c_opt::warnings_as_errors: stream << "ctor::c_opt::warnings_as_errors"; break; + case ctor::c_opt::generate_dep_tree: stream << "ctor::c_opt::generate_dep_tree"; break; + case ctor::c_opt::no_link: stream << "ctor::c_opt::no_link"; break; + case ctor::c_opt::include_path: stream << "ctor::c_opt::include_path"; break; + case ctor::c_opt::c_std: stream << "ctor::c_opt::c_std"; break; + case ctor::c_opt::optimization: stream << "ctor::c_opt::optimization"; break; + case ctor::c_opt::position_independent_code: stream << "ctor::c_opt::position_independent_code"; break; + case ctor::c_opt::position_independent_executable: stream << "ctor::c_opt::position_independent_executable"; break; + case ctor::c_opt::custom: stream << "ctor::c_opt::custom"; break; + } + + return stream; +} + +std::ostream& operator<<(std::ostream& stream, const ctor::cxx_opt& opt) +{ + // Adding to this enum should also imply adding to the unit-tests below + switch(opt) + { + case ctor::cxx_opt::output: stream << "ctor::cxx_opt::output"; break; + case ctor::cxx_opt::debug: stream << "ctor::cxx_opt::debug"; break; + case ctor::cxx_opt::warn_all: stream << "ctor::cxx_opt::warn_all"; break; + case ctor::cxx_opt::warnings_as_errors: stream << "ctor::cxx_opt::warnings_as_errors"; break; + case ctor::cxx_opt::generate_dep_tree: stream << "ctor::cxx_opt::generate_dep_tree"; break; + case ctor::cxx_opt::no_link: stream << "ctor::cxx_opt::no_link"; break; + case ctor::cxx_opt::include_path: stream << "ctor::cxx_opt::include_path"; break; + case ctor::cxx_opt::cpp_std: stream << "ctor::cxx_opt::cpp_std"; break; + case ctor::cxx_opt::optimization: stream << "ctor::cxx_opt::optimization"; break; + case ctor::cxx_opt::position_independent_code: stream << "ctor::cxx_opt::position_independent_code"; break; + case ctor::cxx_opt::position_independent_executable: stream << "ctor::cxx_opt::position_independent_executable"; break; + case ctor::cxx_opt::custom: stream << "ctor::cxx_opt::custom"; break; + } + + return stream; +} + +std::ostream& operator<<(std::ostream& stream, const ctor::ld_opt& opt) +{ + // Adding to this enum should also imply adding to the unit-tests below + switch(opt) + { + case ctor::ld_opt::output: stream << "ctor::ld_opt::output"; break; + case ctor::ld_opt::strip: stream << "ctor::ld_opt::strip"; break; + case ctor::ld_opt::warn_all: stream << "ctor::ld_opt::warn_all"; break; + case ctor::ld_opt::warnings_as_errors: stream << "ctor::ld_opt::warnings_as_errors"; break; + case ctor::ld_opt::library_path: stream << "ctor::ld_opt::library_path"; break; + case ctor::ld_opt::link: stream << "ctor::ld_opt::link"; break; + case ctor::ld_opt::cpp_std: stream << "ctor::ld_opt::cpp_std"; break; + case ctor::ld_opt::build_shared: stream << "ctor::ld_opt::build_shared"; break; + case ctor::ld_opt::threads: stream << "ctor::ld_opt::threads"; break; + case ctor::ld_opt::position_independent_code: stream << "ctor::ld_opt::position_independent_code"; break; + case ctor::ld_opt::position_independent_executable: stream << "ctor::ld_opt::position_independent_executable"; break; + case ctor::ld_opt::custom: stream << "ctor::ld_opt::custom"; break; + } + + return stream; +} + +std::ostream& operator<<(std::ostream& stream, const ctor::ar_opt& opt) +{ + // Adding to this enum should also imply adding to the unit-tests below + switch(opt) + { + case ctor::ar_opt::custom: stream << "ctor::ar_opt::custom"; break; + } + + return stream; +} + +std::ostream& operator<<(std::ostream& stream, const ctor::asm_opt& opt) +{ + // Adding to this enum should also imply adding to the unit-tests below + switch(opt) + { + case ctor::asm_opt::custom: stream << "ctor::asm_opt::custom"; break; + } + + return stream; +} + ctor::toolchain getToolChain(const std::string& compiler) { std::filesystem::path cc(compiler); @@ -48,63 +137,191 @@ ctor::toolchain getToolChain(ctor::output_system system) } } -namespace +namespace gcc { +ctor::c_flag c_option(const std::string& flag) { -std::vector getOptionGcc(ctor::opt option, const std::string& arg) + if(flag.substr(0, 2) == "-I") + { + std::string path = flag.substr(2); + path.erase(0, path.find_first_not_of(' ')); + return { ctor::c_opt::include_path, path }; + } + + return { ctor::c_opt::custom, flag }; +} + +ctor::cxx_flag cxx_option(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 { ctor::cxx_opt::include_path, path }; + } + + return { ctor::cxx_opt::custom, flag }; +} + +ctor::ld_flag ld_option(const std::string& flag) +{ + if(flag.substr(0, 2) == "-L") + { + std::string path = flag.substr(2); + path.erase(0, path.find_first_not_of(' ')); + return { ctor::ld_opt::library_path, path }; + } + + return { ctor::ld_opt::custom, flag }; +} + +std::vector cxx_option(ctor::cxx_opt opt, const std::string& arg) { - switch(option) + switch(opt) { - case ctor::opt::output: + case ctor::cxx_opt::output: return {"-o", arg}; - case ctor::opt::debug: + case ctor::cxx_opt::debug: return {"-g"}; - case ctor::opt::strip: - return {"-s"}; - case ctor::opt::warn_all: + case ctor::cxx_opt::warn_all: return {"-Wall"}; - case ctor::opt::warnings_as_errors: + case ctor::cxx_opt::warnings_as_errors: return {"-Werror"}; - case ctor::opt::generate_dep_tree: + case ctor::cxx_opt::generate_dep_tree: return {"-MMD"}; - case ctor::opt::no_link: + case ctor::cxx_opt::no_link: return {"-c"}; - case ctor::opt::include_path: + case ctor::cxx_opt::include_path: return {"-I" + arg}; - case ctor::opt::library_path: + case ctor::cxx_opt::cpp_std: + return {"-std=" + arg}; + case ctor::cxx_opt::optimization: + return {"-O" + arg}; + case ctor::cxx_opt::position_independent_code: + return {"-fPIC"}; + case ctor::cxx_opt::position_independent_executable: + return {"-fPIE"}; + case ctor::cxx_opt::custom: + return {arg}; + } + + std::cerr << "Unsupported compiler option.\n"; + return {}; +} + +std::vector c_option(ctor::c_opt opt, const std::string& arg) +{ + switch(opt) + { + case ctor::c_opt::output: + return {"-o", arg}; + case ctor::c_opt::debug: + return {"-g"}; + case ctor::c_opt::warn_all: + return {"-Wall"}; + case ctor::c_opt::warnings_as_errors: + return {"-Werror"}; + case ctor::c_opt::generate_dep_tree: + return {"-MMD"}; + case ctor::c_opt::no_link: + return {"-c"}; + case ctor::c_opt::include_path: + return {"-I" + arg}; + case ctor::c_opt::c_std: + return {"-std=" + arg}; + case ctor::c_opt::optimization: + return {"-O" + arg}; + case ctor::c_opt::position_independent_code: + return {"-fPIC"}; + case ctor::c_opt::position_independent_executable: + return {"-fPIE"}; + case ctor::c_opt::custom: + return {arg}; + } + + std::cerr << "Unsupported compiler option.\n"; + return {}; +} + +std::vector ld_option(ctor::ld_opt opt, const std::string& arg) +{ + switch(opt) + { + case ctor::ld_opt::output: + return {"-o", arg}; + case ctor::ld_opt::strip: + return {"-s"}; + case ctor::ld_opt::warn_all: + return {"-Wall"}; + case ctor::ld_opt::warnings_as_errors: + return {"-Werror"}; + case ctor::ld_opt::library_path: return {"-L" + arg}; - case ctor::opt::link: + case ctor::ld_opt::link: return {"-l" + arg}; - case ctor::opt::cpp_std: + case ctor::ld_opt::cpp_std: return {"-std=" + arg}; - case ctor::opt::build_shared: + case ctor::ld_opt::build_shared: return {"-shared"}; - case ctor::opt::threads: + case ctor::ld_opt::threads: return {"-pthread"}; - case ctor::opt::optimization: - return {"-O" + arg}; - case ctor::opt::position_independent_code: + case ctor::ld_opt::position_independent_code: return {"-fPIC"}; - case ctor::opt::position_independent_executable: + case ctor::ld_opt::position_independent_executable: return {"-fPIE"}; - case ctor::opt::custom: + case ctor::ld_opt::custom: return {arg}; } std::cerr << "Unsupported compiler option.\n"; return {}; } + +std::vector ar_option(ctor::ar_opt opt, const std::string& arg) +{ + switch(opt) + { + case ctor::ar_opt::custom: + return {arg}; + } + + std::cerr << "Unsupported compiler option.\n"; + return {}; } -std::vector getOption(ctor::toolchain toolchain, - ctor::opt option, - const std::string& arg) +std::vector asm_option(ctor::asm_opt opt, const std::string& arg) +{ + switch(opt) + { + case ctor::asm_opt::custom: + return {arg}; + } + + std::cerr << "Unsupported compiler option.\n"; + return {}; +} +} // gcc:: + + +std::vector c_option(ctor::toolchain toolchain, + ctor::c_opt opt, + const std::string& arg) { switch(toolchain) { case ctor::toolchain::gcc: case ctor::toolchain::clang: - return getOptionGcc(option, arg); + return gcc::c_option(opt, arg); case ctor::toolchain::any: + { + std::ostringstream ss; + ss << "{" << opt; + if(!arg.empty()) + { + ss << ", \"" << arg << "\""; + } + ss << "}"; + return { ss.str() }; + } case ctor::toolchain::none: break; } @@ -113,40 +330,301 @@ std::vector getOption(ctor::toolchain toolchain, return {}; } -namespace { -std::pair getOptionGcc(const std::string& flag) +std::vector cxx_option(ctor::toolchain toolchain, + ctor::cxx_opt opt, + const std::string& arg) { - if(flag.substr(0, 2) == "-I") + switch(toolchain) { - std::string path = flag.substr(2); - path.erase(0, path.find_first_not_of(' ')); - return { ctor::opt::include_path, path }; + case ctor::toolchain::gcc: + case ctor::toolchain::clang: + return gcc::cxx_option(opt, arg); + case ctor::toolchain::any: + { + std::ostringstream ss; + ss << "{" << opt; + if(!arg.empty()) + { + ss << ", \"" << arg << "\""; + } + ss << "}"; + return { ss.str() }; + } + case ctor::toolchain::none: + break; } - if(flag.substr(0, 2) == "-L") + std::cerr << "Unsupported tool-chain.\n"; + return {}; +} + +std::vector ld_option(ctor::toolchain toolchain, + ctor::ld_opt opt, + const std::string& arg) +{ + switch(toolchain) { - std::string path = flag.substr(2); - path.erase(0, path.find_first_not_of(' ')); - return { ctor::opt::library_path, path }; + case ctor::toolchain::gcc: + case ctor::toolchain::clang: + return gcc::ld_option(opt, arg); + case ctor::toolchain::any: + { + std::ostringstream ss; + ss << "{" << opt; + if(!arg.empty()) + { + ss << ", \"" << arg << "\""; + } + ss << "}"; + return { ss.str() }; + } + case ctor::toolchain::none: + break; } - return { ctor::opt::custom, flag }; + std::cerr << "Unsupported tool-chain.\n"; + return {}; } + +std::vector ar_option(ctor::toolchain toolchain, + ctor::ar_opt opt, + const std::string& arg) +{ + switch(toolchain) + { + case ctor::toolchain::gcc: + case ctor::toolchain::clang: + return gcc::ar_option(opt, arg); + case ctor::toolchain::any: + { + std::ostringstream ss; + ss << "{" << opt; + if(!arg.empty()) + { + ss << ", \"" << arg << "\""; + } + ss << "}"; + return { ss.str() }; + } + case ctor::toolchain::none: + break; + } + + std::cerr << "Unsupported tool-chain.\n"; + return {}; } -std::pair getOption(const std::string& flag, - ctor::toolchain toolchain) +std::vector asm_option(ctor::toolchain toolchain, + ctor::asm_opt opt, + const std::string& arg) { switch(toolchain) { case ctor::toolchain::gcc: case ctor::toolchain::clang: - return getOptionGcc(flag); + return gcc::asm_option(opt, arg); case ctor::toolchain::any: + { + std::ostringstream ss; + ss << "{" << opt; + if(!arg.empty()) + { + ss << ", \"" << arg << "\""; + } + ss << "}"; + return { ss.str() }; + } case ctor::toolchain::none: break; } std::cerr << "Unsupported tool-chain.\n"; - return { ctor::opt::custom, flag }; + return {}; +} + + +ctor::c_flag c_option(const std::string& flag, ctor::toolchain toolchain) +{ + switch(toolchain) + { + case ctor::toolchain::gcc: + case ctor::toolchain::clang: + return gcc::c_option(flag); + case ctor::toolchain::any: + case ctor::toolchain::none: + break; + } + + return { ctor::c_opt::custom, flag }; +} + +ctor::cxx_flag cxx_option(const std::string& flag, ctor::toolchain toolchain) +{ + switch(toolchain) + { + case ctor::toolchain::gcc: + case ctor::toolchain::clang: + return gcc::cxx_option(flag); + case ctor::toolchain::any: + case ctor::toolchain::none: + break; + } + + return { ctor::cxx_opt::custom, flag }; +} + +ctor::ld_flag ld_option(const std::string& flag, ctor::toolchain toolchain) +{ + switch(toolchain) + { + case ctor::toolchain::gcc: + case ctor::toolchain::clang: + return gcc::ld_option(flag); + case ctor::toolchain::any: + case ctor::toolchain::none: + break; + } + + return { ctor::ld_opt::custom, flag }; +} + +ctor::ar_flag ar_option(const std::string& flag, ctor::toolchain toolchain) +{ + switch(toolchain) + { + case ctor::toolchain::gcc: + case ctor::toolchain::clang: + case ctor::toolchain::any: + case ctor::toolchain::none: + break; + } + + return { ctor::ar_opt::custom, flag }; +} + +ctor::asm_flag asm_option(const std::string& flag, ctor::toolchain toolchain) +{ + switch(toolchain) + { + case ctor::toolchain::gcc: + case ctor::toolchain::clang: + case ctor::toolchain::any: + case ctor::toolchain::none: + break; + } + + return { ctor::asm_opt::custom, flag }; +} + +// Flag to string coversions + +std::vector to_strings(ctor::toolchain toolchain, + const ctor::c_flag& flag) +{ + if(flag.toolchain == ctor::toolchain::any || + flag.toolchain == toolchain) + { + return c_option(toolchain, flag.opt, flag.arg); + } + + return {}; +} + +std::vector to_strings(ctor::toolchain toolchain, + const ctor::cxx_flag& flag) +{ + if(flag.toolchain == ctor::toolchain::any || + flag.toolchain == toolchain) + { + return cxx_option(toolchain, flag.opt, flag.arg); + } + + return {}; +} + +std::vector to_strings(ctor::toolchain toolchain, + const ctor::ld_flag& flag) +{ + if(flag.toolchain == ctor::toolchain::any || + flag.toolchain == toolchain) + { + return ld_option(toolchain, flag.opt, flag.arg); + } + + return {}; +} + +std::vector to_strings(ctor::toolchain toolchain, + const ctor::ar_flag& flag) +{ + if(flag.toolchain == ctor::toolchain::any || + flag.toolchain == toolchain) + { + return ar_option(toolchain, flag.opt, flag.arg); + } + + return {}; +} + +std::vector to_strings(ctor::toolchain toolchain, + const ctor::asm_flag& flag) +{ + if(flag.toolchain == ctor::toolchain::any || + flag.toolchain == toolchain) + { + return asm_option(toolchain, flag.opt, flag.arg); + } + + return {}; +} + +namespace { +ctor::toolchain guess_toolchain(const std::string& opt) +{ + if(opt.empty()) + { + return ctor::toolchain::any; + } + + if(opt[0] == '-') + { + return ctor::toolchain::gcc; + } + + //if(opt[0] == '/') + //{ + // return ctor::toolchain::msvc; + //} + return ctor::toolchain::any; +} +} + +template<> +ctor::flag::flag(const char* str) +{ + *this = c_option(str, guess_toolchain(str)); +} + +template<> +ctor::flag::flag(const char* str) +{ + *this = cxx_option(str, guess_toolchain(str)); +} + +template<> +ctor::flag::flag(const char* str) +{ + *this = ld_option(str, guess_toolchain(str)); +} + +template<> +ctor::flag::flag(const char* str) +{ + *this = ar_option(str, guess_toolchain(str)); +} + +template<> +ctor::flag::flag(const char* str) +{ + *this = asm_option(str, guess_toolchain(str)); } diff --git a/src/tools.h b/src/tools.h index e6c2264..b1285ec 100644 --- a/src/tools.h +++ b/src/tools.h @@ -5,23 +5,92 @@ #include #include +#include #include "ctor.h" + +std::ostream& operator<<(std::ostream& stream, const ctor::c_opt& opt); +std::ostream& operator<<(std::ostream& stream, const ctor::cxx_opt& opt); +std::ostream& operator<<(std::ostream& stream, const ctor::ld_opt& opt); +std::ostream& operator<<(std::ostream& stream, const ctor::ar_opt& opt); +std::ostream& operator<<(std::ostream& stream, const ctor::asm_opt& opt); + + //! Get tool-chain type from compiler path string ctor::toolchain getToolChain(const std::string& compiler); //! Get tool-chain type from output system (via configuration) ctor::toolchain getToolChain(ctor::output_system system); + + +//! Get tool argument(s) for specific option type matching the supplied +//! tool-chain +std::vector c_option(ctor::toolchain toolchain, + ctor::c_opt option, + const std::string& arg = {}); + +//! Get tool argument(s) for specific option type matching the supplied +//! tool-chain +std::vector cxx_option(ctor::toolchain toolchain, + ctor::cxx_opt option, + const std::string& arg = {}); + //! Get tool argument(s) for specific option type matching the supplied //! tool-chain -std::vector getOption(ctor::toolchain toolchain, - ctor::opt option, +std::vector ld_option(ctor::toolchain toolchain, + ctor::ld_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, - ctor::toolchain toolchain = ctor::toolchain::gcc); +//! Get tool argument(s) for specific option type matching the supplied +//! tool-chain +std::vector ar_option(ctor::toolchain toolchain, + ctor::ar_opt option, + const std::string& arg = {}); + +//! Get tool argument(s) for specific option type matching the supplied +//! tool-chain +std::vector asm_option(ctor::toolchain toolchain, + ctor::asm_opt option, + const std::string& arg = {}); + + + +//! Get ctor::c_opt enum value and argument from string, +//! ie. { ctor::c_opt::inlude_path, "foo/bar" } from "-Ifoo/bar" +//! Returns { ctor::c_opt::custom, flag } if unknown. +ctor::c_flag c_option(const std::string& flag, ctor::toolchain toolchain); + +//! Get ctor::cxx_opt enum value and argument from string, +//! ie. { ctor::cxx_opt::inlude_path, "foo/bar" } from "-Ifoo/bar" +//! Returns { ctor::cxx_opt::custom, flag } if unknown. +ctor::cxx_flag cxx_option(const std::string& flag, ctor::toolchain toolchain); + +//! Get ctor::ld_opt enum value and argument from string, +//! ie. { ctor::ld_opt::inlude_path, "foo/bar" } from "-Ifoo/bar" +//! Returns { ctor::ld_opt::custom, flag } if unknown. +ctor::ld_flag ld_option(const std::string& flag, ctor::toolchain toolchain); + +//! Get ctor::ar_opt enum value and argument from string, +//! ie. { ctor::ar_opt::inlude_path, "foo/bar" } from "-Ifoo/bar" +//! Returns { ctor::ar_opt::custom, flag } if unknown. +ctor::ar_flag ar_option(const std::string& flag, ctor::toolchain toolchain); + +//! Get ctor::asm_opt enum value and argument from string, +//! ie. { ctor::asm_opt::inlude_path, "foo/bar" } from "-Ifoo/bar" +//! Returns { ctor::asm_opt::custom, flag } if unknown. +ctor::asm_flag asm_option(const std::string& flag, ctor::toolchain toolchain); + + + +std::vector to_strings(ctor::toolchain toolchain, + const ctor::cxx_flag& flag); +std::vector to_strings(ctor::toolchain toolchain, + const ctor::c_flag& flag); +std::vector to_strings(ctor::toolchain toolchain, + const ctor::ld_flag& flag); +std::vector to_strings(ctor::toolchain toolchain, + const ctor::ar_flag& flag); +std::vector to_strings(ctor::toolchain toolchain, + const ctor::asm_flag& flag); diff --git a/src/util.h b/src/util.h index d5fccc8..c7318aa 100644 --- a/src/util.h +++ b/src/util.h @@ -18,3 +18,8 @@ void append(T& a, const T& b) { a.insert(a.end(), b.begin(), b.end()); } + +//using cxx_flags = std::vector; +//using c_flags = std::vector; +//using ld_flags= std::vector; +//using asm_flags = std::vector; -- cgit v1.2.3