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/tools.cc | 560 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 519 insertions(+), 41 deletions(-) (limited to 'src/tools.cc') 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)); } -- cgit v1.2.3