summaryrefslogtreecommitdiff
path: root/src/tools.cc
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2023-01-13 19:56:35 +0100
committerBent Bisballe Nyeng <deva@aasimon.org>2023-01-13 22:32:09 +0100
commit916060cb53fddb94f64b20d3616e7360c5e91f64 (patch)
tree4a2bcef4672b5e04b106f88cca3bec631b214c00 /src/tools.cc
parentc093758b4688fb5bae2cc7727b6c9b52b824043e (diff)
Capture flags in a class instead of a string and add conversion functions between them.
Diffstat (limited to 'src/tools.cc')
-rw-r--r--src/tools.cc560
1 files changed, 519 insertions, 41 deletions
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 <filesystem>
#include <iostream>
+#include <sstream>
#include <cassert>
+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<std::string> 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<std::string> 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<std::string> 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<std::string> 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<std::string> 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<std::string> getOption(ctor::toolchain toolchain,
- ctor::opt option,
- const std::string& arg)
+std::vector<std::string> 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<std::string> 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<std::string> getOption(ctor::toolchain toolchain,
return {};
}
-namespace {
-std::pair<ctor::opt, std::string> getOptionGcc(const std::string& flag)
+std::vector<std::string> 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<std::string> 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<std::string> 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<ctor::opt, std::string> getOption(const std::string& flag,
- ctor::toolchain toolchain)
+std::vector<std::string> 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<std::string> 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<std::string> 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<std::string> 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<std::string> 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<std::string> 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<ctor::c_opt>::flag(const char* str)
+{
+ *this = c_option(str, guess_toolchain(str));
+}
+
+template<>
+ctor::flag<ctor::cxx_opt>::flag(const char* str)
+{
+ *this = cxx_option(str, guess_toolchain(str));
+}
+
+template<>
+ctor::flag<ctor::ld_opt>::flag(const char* str)
+{
+ *this = ld_option(str, guess_toolchain(str));
+}
+
+template<>
+ctor::flag<ctor::ar_opt>::flag(const char* str)
+{
+ *this = ar_option(str, guess_toolchain(str));
+}
+
+template<>
+ctor::flag<ctor::asm_opt>::flag(const char* str)
+{
+ *this = asm_option(str, guess_toolchain(str));
}