opt_string archive_suffix; | opt_string archive_suffix; | ||||
opt_string object_suffix; | opt_string object_suffix; | ||||
opt_string exe_suffix; | |||||
auto require_key = [](auto k, auto& opt) { | auto require_key = [](auto k, auto& opt) { | ||||
if (!opt.has_value()) { | if (!opt.has_value()) { | ||||
|| try_single("Compile-C-Template", c_compile_template) | || try_single("Compile-C-Template", c_compile_template) | ||||
|| try_single("Compile-C++-Template", cxx_compile_template) | || try_single("Compile-C++-Template", cxx_compile_template) | ||||
|| try_single("Create-Archive-Template", create_archive_template) | || try_single("Create-Archive-Template", create_archive_template) | ||||
|| try_single("Link-Executable-Template", link_exe_template) | |||||
|| try_single("Warning-Flags", warning_flags) | || try_single("Warning-Flags", warning_flags) | ||||
|| try_single("Archive-Suffix", archive_suffix) | || try_single("Archive-Suffix", archive_suffix) | ||||
|| try_single("Object-Suffix", object_suffix) | || try_single("Object-Suffix", object_suffix) | ||||
|| try_single("Link-Executable-Template", link_exe_template) | |||||
|| try_single("Executable-Suffix", exe_suffix) | |||||
|| false; | || false; | ||||
// clang-format on | // clang-format on | ||||
require_key("Archive-Suffix", archive_suffix); | require_key("Archive-Suffix", archive_suffix); | ||||
require_key("Object-Suffix", object_suffix); | require_key("Object-Suffix", object_suffix); | ||||
require_key("Executable-Suffix", exe_suffix); | |||||
return toolchain{ | return toolchain{ | ||||
c_compile_template.value(), | c_compile_template.value(), | ||||
warning_flags.value_or(""), | warning_flags.value_or(""), | ||||
archive_suffix.value(), | archive_suffix.value(), | ||||
object_suffix.value(), | object_suffix.value(), | ||||
exe_suffix.value(), | |||||
}; | }; | ||||
} | } | ||||
return cmd; | return cmd; | ||||
} | } | ||||
vector<string> toolchain::create_link_executable_command(const link_exe_spec& spec) const noexcept { | |||||
vector<string> cmd; | |||||
for (auto& arg : _link_exe_template) { | |||||
if (arg == "<INPUTS>") { | |||||
std::transform(spec.inputs.begin(), | |||||
spec.inputs.end(), | |||||
std::back_inserter(cmd), | |||||
[](auto&& p) { return p.string(); }); | |||||
} else { | |||||
cmd.push_back(replace(arg, "<OUT>", spec.output.string())); | |||||
} | |||||
} | |||||
return cmd; | |||||
} | |||||
std::optional<toolchain> toolchain::get_builtin(std::string_view s) noexcept { | std::optional<toolchain> toolchain::get_builtin(std::string_view s) noexcept { | ||||
toolchain ret; | toolchain ret; | ||||
extend(ret._cxx_compile, common_flags); | extend(ret._cxx_compile, common_flags); | ||||
ret._archive_suffix = ".lib"; | ret._archive_suffix = ".lib"; | ||||
ret._object_suffix = ".obj"; | ret._object_suffix = ".obj"; | ||||
ret._exe_suffix = ".exe"; | |||||
ret._archive_template = {"lib", "/nologo", "/OUT:<ARCHIVE>", "<OBJECTS>"}; | ret._archive_template = {"lib", "/nologo", "/OUT:<ARCHIVE>", "<OBJECTS>"}; | ||||
ret._link_exe_template | ret._link_exe_template | ||||
= {"cl.exe", "/nologo", "/std:c++latest", "/EHsc", "<INPUTS>", "/Fe<OUT>"}; | = {"cl.exe", "/nologo", "/std:c++latest", "/EHsc", "<INPUTS>", "/Fe<OUT>"}; |
fs::path out_path; | fs::path out_path; | ||||
}; | }; | ||||
struct link_exe_spec { | |||||
std::vector<fs::path> inputs; | |||||
fs::path output; | |||||
}; | |||||
class toolchain { | class toolchain { | ||||
using string_seq = std::vector<std::string>; | using string_seq = std::vector<std::string>; | ||||
string_seq _warning_flags; | string_seq _warning_flags; | ||||
std::string _archive_suffix; | std::string _archive_suffix; | ||||
std::string _object_suffix; | std::string _object_suffix; | ||||
std::string _exe_suffix; | |||||
public: | public: | ||||
toolchain() = default; | toolchain() = default; | ||||
std::string_view link_exe_template, | std::string_view link_exe_template, | ||||
std::string_view warning_flags, | std::string_view warning_flags, | ||||
std::string_view archive_suffix, | std::string_view archive_suffix, | ||||
std::string_view object_suffix) | |||||
std::string_view object_suffix, | |||||
std::string_view exe_suffix) | |||||
: _c_compile(split_shell_string(c_compile)) | : _c_compile(split_shell_string(c_compile)) | ||||
, _cxx_compile(split_shell_string(cxx_compile)) | , _cxx_compile(split_shell_string(cxx_compile)) | ||||
, _inc_template(split_shell_string(inc_template)) | , _inc_template(split_shell_string(inc_template)) | ||||
, _link_exe_template(split_shell_string(link_exe_template)) | , _link_exe_template(split_shell_string(link_exe_template)) | ||||
, _warning_flags(split_shell_string(warning_flags)) | , _warning_flags(split_shell_string(warning_flags)) | ||||
, _archive_suffix(archive_suffix) | , _archive_suffix(archive_suffix) | ||||
, _object_suffix(object_suffix) {} | |||||
, _object_suffix(object_suffix) | |||||
, _exe_suffix(exe_suffix) {} | |||||
static toolchain load_from_file(fs::path); | static toolchain load_from_file(fs::path); | ||||
auto& archive_suffix() const noexcept { return _archive_suffix; } | auto& archive_suffix() const noexcept { return _archive_suffix; } | ||||
auto& object_suffix() const noexcept { return _object_suffix; } | auto& object_suffix() const noexcept { return _object_suffix; } | ||||
auto& executable_suffix() const noexcept { return _exe_suffix; } | |||||
std::vector<std::string> definition_args(std::string_view s) const noexcept; | std::vector<std::string> definition_args(std::string_view s) const noexcept; | ||||
std::vector<std::string> include_args(const fs::path& p) const noexcept; | std::vector<std::string> include_args(const fs::path& p) const noexcept; | ||||
std::vector<std::string> create_compile_command(const compile_file_spec&) const noexcept; | std::vector<std::string> create_compile_command(const compile_file_spec&) const noexcept; | ||||
std::vector<std::string> create_archive_command(const archive_spec&) const noexcept; | std::vector<std::string> create_archive_command(const archive_spec&) const noexcept; | ||||
std::vector<std::string> create_link_executable_command(const link_exe_spec&) const noexcept; | |||||
static std::optional<toolchain> get_builtin(std::string_view key) noexcept; | static std::optional<toolchain> get_builtin(std::string_view key) noexcept; | ||||
}; | }; |