| using namespace dds; | using namespace dds; | ||||
| std::vector<std::string> compile_file_plan::generate_compile_command(build_env_ref env) const | |||||
| noexcept { | |||||
| compile_command_info compile_file_plan::generate_compile_command(build_env_ref env) const noexcept { | |||||
| compile_file_spec spec{_source.path, calc_object_file_path(env)}; | compile_file_spec spec{_source.path, calc_object_file_path(env)}; | ||||
| spec.enable_warnings = _rules.enable_warnings(); | spec.enable_warnings = _rules.enable_warnings(); | ||||
| extend(spec.include_dirs, _rules.include_dirs()); | extend(spec.include_dirs, _rules.include_dirs()); | ||||
| return env.toolchain.create_compile_command(spec); | return env.toolchain.create_compile_command(spec); | ||||
| } | } | ||||
| void compile_file_plan::compile(const build_env& env) const { | |||||
| std::optional<deps_info> compile_file_plan::compile(const build_env& env) const { | |||||
| const auto obj_path = calc_object_file_path(env); | const auto obj_path = calc_object_file_path(env); | ||||
| fs::create_directories(obj_path.parent_path()); | fs::create_directories(obj_path.parent_path()); | ||||
| fs::relative(_source.path, _source.basis_path).string()); | fs::relative(_source.path, _source.basis_path).string()); | ||||
| spdlog::info(msg); | spdlog::info(msg); | ||||
| auto cmd = generate_compile_command(env); | |||||
| auto&& [dur_ms, compile_res] = timed<std::chrono::milliseconds>([&] { return run_proc(cmd); }); | |||||
| auto cmd = generate_compile_command(env); | |||||
| auto&& [dur_ms, compile_res] | |||||
| = timed<std::chrono::milliseconds>([&] { return run_proc(cmd.command); }); | |||||
| spdlog::info("{} - {:>7n}ms", msg, dur_ms.count()); | spdlog::info("{} - {:>7n}ms", msg, dur_ms.count()); | ||||
| if (!compile_res.okay()) { | if (!compile_res.okay()) { | ||||
| spdlog::error("Compilation failed: {}", _source.path.string()); | spdlog::error("Compilation failed: {}", _source.path.string()); | ||||
| spdlog::error("Subcommand FAILED: {}\n{}", quote_command(cmd), compile_res.output); | |||||
| spdlog::error("Subcommand FAILED: {}\n{}", quote_command(cmd.command), compile_res.output); | |||||
| throw compile_failure(fmt::format("Compilation failed for {}", _source.path.string())); | throw compile_failure(fmt::format("Compilation failed for {}", _source.path.string())); | ||||
| } | } | ||||
| if (!compile_res.output.empty()) { | if (!compile_res.output.empty()) { | ||||
| spdlog::warn("While compiling file {} [{}]:\n{}", | spdlog::warn("While compiling file {} [{}]:\n{}", | ||||
| _source.path.string(), | _source.path.string(), | ||||
| quote_command(cmd), | |||||
| quote_command(cmd.command), | |||||
| compile_res.output); | compile_res.output); | ||||
| } | } | ||||
| return std::nullopt; | |||||
| } | } | ||||
| fs::path compile_file_plan::calc_object_file_path(const build_env& env) const noexcept { | fs::path compile_file_plan::calc_object_file_path(const build_env& env) const noexcept { |
| #include <dds/build/plan/base.hpp> | #include <dds/build/plan/base.hpp> | ||||
| #include <dds/source.hpp> | #include <dds/source.hpp> | ||||
| #include <dds/toolchain/deps.hpp> | |||||
| #include <memory> | #include <memory> | ||||
| , _qualifier(qual) | , _qualifier(qual) | ||||
| , _subdir(subdir) {} | , _subdir(subdir) {} | ||||
| std::vector<std::string> generate_compile_command(build_env_ref) const noexcept; | |||||
| compile_command_info generate_compile_command(build_env_ref) const noexcept; | |||||
| const source_file& source() const noexcept { return _source; } | const source_file& source() const noexcept { return _source; } | ||||
| path_ref source_path() const noexcept { return _source.path; } | path_ref source_path() const noexcept { return _source.path; } | ||||
| fs::path calc_object_file_path(build_env_ref env) const noexcept; | |||||
| void compile(build_env_ref) const; | |||||
| fs::path calc_object_file_path(build_env_ref env) const noexcept; | |||||
| std::optional<deps_info> compile(build_env_ref) const; | |||||
| }; | }; | ||||
| } // namespace dds | } // namespace dds |
| auto compdb = nlohmann::json::array(); | auto compdb = nlohmann::json::array(); | ||||
| for (const compile_file_plan& cf : iter_compilations(plan)) { | for (const compile_file_plan& cf : iter_compilations(plan)) { | ||||
| auto command = cf.generate_compile_command(env); | |||||
| auto cmd_info = cf.generate_compile_command(env); | |||||
| auto entry = nlohmann::json::object({ | auto entry = nlohmann::json::object({ | ||||
| {"directory", env.output_root.string()}, | {"directory", env.output_root.string()}, | ||||
| {"arguments", command}, | |||||
| {"arguments", cmd_info.command}, | |||||
| {"file", cf.source_path().string()}, | {"file", cf.source_path().string()}, | ||||
| }); | }); | ||||
| compdb.push_back(std::move(entry)); | compdb.push_back(std::move(entry)); |
| #pragma once | |||||
| #include <dds/util/fs.hpp> | |||||
| #include <vector> | |||||
| namespace dds { | |||||
| enum class deps_mode { | |||||
| none, | |||||
| msvc, | |||||
| gnu, | |||||
| }; | |||||
| struct deps_info { | |||||
| fs::path output; | |||||
| std::vector<fs::path> inputs; | |||||
| std::vector<std::string> command; | |||||
| }; | |||||
| } // namespace dds |
| opt_string obj_suffix; | opt_string obj_suffix; | ||||
| opt_string exe_prefix; | opt_string exe_prefix; | ||||
| opt_string exe_suffix; | opt_string exe_suffix; | ||||
| opt_string deps_mode_str; | |||||
| optional<bool> do_debug; | optional<bool> do_debug; | ||||
| optional<bool> do_optimize; | optional<bool> do_optimize; | ||||
| opt_str_seq include_template; | opt_str_seq include_template; | ||||
| lm::read_bool("Debug", do_debug), | lm::read_bool("Debug", do_debug), | ||||
| // Miscellaneous | // Miscellaneous | ||||
| read_argv{"Compiler-Launcher", compile_launcher}, | read_argv{"Compiler-Launcher", compile_launcher}, | ||||
| lm::read_opt("Deps-Mode", deps_mode_str), | |||||
| // Command templates | // Command templates | ||||
| read_argv{"C-Compile-File", c_compile_file}, | read_argv{"C-Compile-File", c_compile_file}, | ||||
| read_argv{"C++-Compile-File", cxx_compile_file}, | read_argv{"C++-Compile-File", cxx_compile_file}, | ||||
| bool is_msvc = compiler_id_e == msvc; | bool is_msvc = compiler_id_e == msvc; | ||||
| bool is_gnu_like = is_gnu || is_clang; | bool is_gnu_like = is_gnu || is_clang; | ||||
| const enum deps_mode deps_mode = [&] { | |||||
| if (!deps_mode_str.has_value()) { | |||||
| if (is_gnu_like) { | |||||
| return deps_mode::gnu; | |||||
| } else if (is_msvc) { | |||||
| return deps_mode::msvc; | |||||
| } else { | |||||
| return deps_mode::none; | |||||
| } | |||||
| } else if (deps_mode_str == "GNU") { | |||||
| return deps_mode::gnu; | |||||
| } else if (deps_mode_str == "MSVC") { | |||||
| return deps_mode::msvc; | |||||
| } else if (deps_mode_str == "None") { | |||||
| return deps_mode::none; | |||||
| } else { | |||||
| fail(context, "Unknown Deps-Mode '{}'", *deps_mode_str); | |||||
| } | |||||
| }(); | |||||
| // Now convert the flags we've been given into a real toolchain | // Now convert the flags we've been given into a real toolchain | ||||
| auto get_compiler = [&](language lang) -> string { | auto get_compiler = [&](language lang) -> string { | ||||
| if (lang == language::cxx && cxx_compiler_fpath) { | if (lang == language::cxx && cxx_compiler_fpath) { | ||||
| rt_lib = "/MTd"; | rt_lib = "/MTd"; | ||||
| } | } | ||||
| ret.emplace_back(rt_lib); | ret.emplace_back(rt_lib); | ||||
| extend(ret, {"/nologo", "<FLAGS>", "/permissive-", "/c", "<IN>", "/Fo<OUT>"}); | |||||
| if (lang == language::cxx) { | if (lang == language::cxx) { | ||||
| extend(ret, {"/EHsc"}); | extend(ret, {"/EHsc"}); | ||||
| } | } | ||||
| extend(ret, {"/nologo", "/permissive-", "<FLAGS>", "/c", "<IN>", "/Fo<OUT>"}); | |||||
| } else if (is_gnu_like) { | } else if (is_gnu_like) { | ||||
| if (do_optimize.has_value() && *do_optimize) { | if (do_optimize.has_value() && *do_optimize) { | ||||
| extend(ret, {"-O2"}); | extend(ret, {"-O2"}); | ||||
| return ret; | return ret; | ||||
| }; | }; | ||||
| tc.deps_mode = deps_mode; | |||||
| tc.c_compile = read_opt(c_compile_file, [&] { | tc.c_compile = read_opt(c_compile_file, [&] { | ||||
| string_seq c; | string_seq c; | ||||
| if (compile_launcher) { | if (compile_launcher) { | ||||
| } | } | ||||
| if (is_gnu_like) { | if (is_gnu_like) { | ||||
| return {"-I", "<PATH>"}; | return {"-I", "<PATH>"}; | ||||
| } else if (compiler_id == "MSVC") { | |||||
| } else if (is_msvc) { | |||||
| return {"/I", "<PATH>"}; | return {"/I", "<PATH>"}; | ||||
| } | } | ||||
| assert(false && "Include-Template deduction failed"); | assert(false && "Include-Template deduction failed"); | ||||
| } | } | ||||
| if (is_gnu_like) { | if (is_gnu_like) { | ||||
| return {"-D", "<DEF>"}; | return {"-D", "<DEF>"}; | ||||
| } else if (compiler_id == "MSVC") { | |||||
| } else if (is_msvc) { | |||||
| return {"/D", "<DEF>"}; | return {"/D", "<DEF>"}; | ||||
| } | } | ||||
| assert(false && "Define-Template deduction failed"); | assert(false && "Define-Template deduction failed"); |
| cf.source_path = "foo.cpp"; | cf.source_path = "foo.cpp"; | ||||
| cf.out_path = "foo.o"; | cf.out_path = "foo.o"; | ||||
| auto cf_cmd = tc.create_compile_command(cf); | auto cf_cmd = tc.create_compile_command(cf); | ||||
| auto cf_cmd_str = dds::quote_command(cf_cmd); | |||||
| auto cf_cmd_str = dds::quote_command(cf_cmd.command); | |||||
| CHECK(cf_cmd_str == expected_compile); | CHECK(cf_cmd_str == expected_compile); | ||||
| cf.enable_warnings = true; | cf.enable_warnings = true; | ||||
| cf_cmd = tc.create_compile_command(cf); | cf_cmd = tc.create_compile_command(cf); | ||||
| cf_cmd_str = dds::quote_command(cf_cmd); | |||||
| cf_cmd_str = dds::quote_command(cf_cmd.command); | |||||
| CHECK(cf_cmd_str == expected_compile_warnings); | CHECK(cf_cmd_str == expected_compile_warnings); | ||||
| dds::archive_spec ar_spec; | dds::archive_spec ar_spec; | ||||
| TEST_CASE("Generating toolchain commands") { | TEST_CASE("Generating toolchain commands") { | ||||
| check_tc_compile("Compiler-ID: GNU", | check_tc_compile("Compiler-ID: GNU", | ||||
| "g++ -fPIC -fdiagnostics-color -pthread -c foo.cpp -ofoo.o", | |||||
| "g++ -fPIC -fdiagnostics-color -pthread -MD -MF foo.o.d -c foo.cpp -ofoo.o", | |||||
| "g++ -fPIC -fdiagnostics-color -pthread -Wall -Wextra -Wpedantic -Wconversion " | "g++ -fPIC -fdiagnostics-color -pthread -Wall -Wextra -Wpedantic -Wconversion " | ||||
| "-c foo.cpp -ofoo.o", | |||||
| "-MD -MF foo.o.d -c foo.cpp -ofoo.o", | |||||
| "ar rcs stuff.a foo.o bar.o", | "ar rcs stuff.a foo.o bar.o", | ||||
| "g++ -fPIC -fdiagnostics-color foo.o bar.a -pthread -lstdc++fs -omeow.exe"); | "g++ -fPIC -fdiagnostics-color foo.o bar.a -pthread -lstdc++fs -omeow.exe"); | ||||
| check_tc_compile( | check_tc_compile( | ||||
| "Compiler-ID: GNU\nDebug: True", | "Compiler-ID: GNU\nDebug: True", | ||||
| "g++ -g -fPIC -fdiagnostics-color -pthread -c foo.cpp -ofoo.o", | |||||
| "g++ -g -fPIC -fdiagnostics-color -pthread -MD -MF foo.o.d -c foo.cpp -ofoo.o", | |||||
| "g++ -g -fPIC -fdiagnostics-color -pthread -Wall -Wextra -Wpedantic -Wconversion " | "g++ -g -fPIC -fdiagnostics-color -pthread -Wall -Wextra -Wpedantic -Wconversion " | ||||
| "-c foo.cpp -ofoo.o", | |||||
| "-MD -MF foo.o.d -c foo.cpp -ofoo.o", | |||||
| "ar rcs stuff.a foo.o bar.o", | "ar rcs stuff.a foo.o bar.o", | ||||
| "g++ -fPIC -fdiagnostics-color foo.o bar.a -pthread -lstdc++fs -omeow.exe -g"); | "g++ -fPIC -fdiagnostics-color foo.o bar.a -pthread -lstdc++fs -omeow.exe -g"); | ||||
| check_tc_compile( | check_tc_compile( | ||||
| "Compiler-ID: GNU\nDebug: True\nOptimize: True", | "Compiler-ID: GNU\nDebug: True\nOptimize: True", | ||||
| "g++ -O2 -g -fPIC -fdiagnostics-color -pthread -c foo.cpp -ofoo.o", | |||||
| "g++ -O2 -g -fPIC -fdiagnostics-color -pthread -MD -MF foo.o.d -c foo.cpp -ofoo.o", | |||||
| "g++ -O2 -g -fPIC -fdiagnostics-color -pthread -Wall -Wextra -Wpedantic -Wconversion " | "g++ -O2 -g -fPIC -fdiagnostics-color -pthread -Wall -Wextra -Wpedantic -Wconversion " | ||||
| "-c foo.cpp -ofoo.o", | |||||
| "-MD -MF foo.o.d -c foo.cpp -ofoo.o", | |||||
| "ar rcs stuff.a foo.o bar.o", | "ar rcs stuff.a foo.o bar.o", | ||||
| "g++ -fPIC -fdiagnostics-color foo.o bar.a -pthread -lstdc++fs -omeow.exe -O2 -g"); | "g++ -fPIC -fdiagnostics-color foo.o bar.a -pthread -lstdc++fs -omeow.exe -O2 -g"); | ||||
| check_tc_compile("Compiler-ID: MSVC", | check_tc_compile("Compiler-ID: MSVC", | ||||
| "cl.exe /MT /nologo /permissive- /c foo.cpp /Fofoo.o /EHsc", | |||||
| "cl.exe /MT /nologo /W4 /permissive- /c foo.cpp /Fofoo.o /EHsc", | |||||
| "cl.exe /MT /EHsc /nologo /permissive- /showIncludes /c foo.cpp /Fofoo.o", | |||||
| "cl.exe /MT /EHsc /nologo /permissive- /W4 /showIncludes /c foo.cpp /Fofoo.o", | |||||
| "lib /nologo /OUT:stuff.a foo.o bar.o", | "lib /nologo /OUT:stuff.a foo.o bar.o", | ||||
| "cl.exe /nologo /EHsc foo.o bar.a /Femeow.exe /MT"); | "cl.exe /nologo /EHsc foo.o bar.a /Femeow.exe /MT"); | ||||
| check_tc_compile("Compiler-ID: MSVC\nDebug: True", | check_tc_compile("Compiler-ID: MSVC\nDebug: True", | ||||
| "cl.exe /Z7 /DEBUG /MTd /nologo /permissive- /c foo.cpp /Fofoo.o /EHsc", | |||||
| "cl.exe /Z7 /DEBUG /MTd /nologo /W4 /permissive- /c foo.cpp /Fofoo.o /EHsc", | |||||
| "cl.exe /Z7 /DEBUG /MTd /EHsc /nologo /permissive- /showIncludes /c foo.cpp /Fofoo.o", | |||||
| "cl.exe /Z7 /DEBUG /MTd /EHsc /nologo /permissive- /W4 /showIncludes /c foo.cpp /Fofoo.o", | |||||
| "lib /nologo /OUT:stuff.a foo.o bar.o", | "lib /nologo /OUT:stuff.a foo.o bar.o", | ||||
| "cl.exe /nologo /EHsc foo.o bar.a /Femeow.exe /Z7 /DEBUG /MTd"); | "cl.exe /nologo /EHsc foo.o bar.a /Femeow.exe /Z7 /DEBUG /MTd"); | ||||
| cfs.source_path = "foo.cpp"; | cfs.source_path = "foo.cpp"; | ||||
| cfs.out_path = "foo.o"; | cfs.out_path = "foo.o"; | ||||
| auto cmd = tc.create_compile_command(cfs); | auto cmd = tc.create_compile_command(cfs); | ||||
| CHECK(cmd | |||||
| CHECK(cmd.command | |||||
| == std::vector<std::string>{"g++", | == std::vector<std::string>{"g++", | ||||
| "-fPIC", | "-fPIC", | ||||
| "-fdiagnostics-color", | "-fdiagnostics-color", | ||||
| "-pthread", | "-pthread", | ||||
| "-MD", | |||||
| "-MF", | |||||
| "foo.o.d", | |||||
| "-c", | "-c", | ||||
| "foo.cpp", | "foo.cpp", | ||||
| "-ofoo.o"}); | "-ofoo.o"}); | ||||
| cfs.definitions.push_back("FOO=BAR"); | cfs.definitions.push_back("FOO=BAR"); | ||||
| cmd = tc.create_compile_command(cfs); | cmd = tc.create_compile_command(cfs); | ||||
| CHECK(cmd | |||||
| CHECK(cmd.command | |||||
| == std::vector<std::string>{"g++", | == std::vector<std::string>{"g++", | ||||
| "-fPIC", | "-fPIC", | ||||
| "-fdiagnostics-color", | "-fdiagnostics-color", | ||||
| "-pthread", | "-pthread", | ||||
| "-D", | "-D", | ||||
| "FOO=BAR", | "FOO=BAR", | ||||
| "-MD", | |||||
| "-MF", | |||||
| "foo.o.d", | |||||
| "-c", | "-c", | ||||
| "foo.cpp", | "foo.cpp", | ||||
| "-ofoo.o"}); | "-ofoo.o"}); | ||||
| cfs.include_dirs.push_back("fake-dir"); | cfs.include_dirs.push_back("fake-dir"); | ||||
| cmd = tc.create_compile_command(cfs); | cmd = tc.create_compile_command(cfs); | ||||
| CHECK(cmd | |||||
| CHECK(cmd.command | |||||
| == std::vector<std::string>{"g++", | == std::vector<std::string>{"g++", | ||||
| "-fPIC", | "-fPIC", | ||||
| "-fdiagnostics-color", | "-fdiagnostics-color", | ||||
| "fake-dir", | "fake-dir", | ||||
| "-D", | "-D", | ||||
| "FOO=BAR", | "FOO=BAR", | ||||
| "-MD", | |||||
| "-MF", | |||||
| "foo.o.d", | |||||
| "-c", | "-c", | ||||
| "foo.cpp", | "foo.cpp", | ||||
| "-ofoo.o"}); | "-ofoo.o"}); |
| #pragma once | #pragma once | ||||
| #include <dds/toolchain/deps.hpp> | |||||
| #include <string> | #include <string> | ||||
| #include <vector> | #include <vector> | ||||
| std::string exe_prefix; | std::string exe_prefix; | ||||
| std::string exe_suffix; | std::string exe_suffix; | ||||
| enum deps_mode deps_mode; | |||||
| toolchain realize() const; | toolchain realize() const; | ||||
| }; | }; | ||||
| ret._object_suffix = prep.object_suffix; | ret._object_suffix = prep.object_suffix; | ||||
| ret._exe_prefix = prep.exe_prefix; | ret._exe_prefix = prep.exe_prefix; | ||||
| ret._exe_suffix = prep.exe_suffix; | ret._exe_suffix = prep.exe_suffix; | ||||
| ret._deps_mode = prep.deps_mode; | |||||
| return ret; | return ret; | ||||
| } | } | ||||
| return replace(_def_template, "<DEF>", s); | return replace(_def_template, "<DEF>", s); | ||||
| } | } | ||||
| vector<string> toolchain::create_compile_command(const compile_file_spec& spec) const noexcept { | |||||
| compile_command_info toolchain::create_compile_command(const compile_file_spec& spec) const | |||||
| noexcept { | |||||
| vector<string> flags; | vector<string> flags; | ||||
| using namespace std::literals; | |||||
| language lang = spec.lang; | language lang = spec.lang; | ||||
| if (lang == language::automatic) { | if (lang == language::automatic) { | ||||
| if (spec.source_path.extension() == ".c" || spec.source_path.extension() == ".C") { | if (spec.source_path.extension() == ".c" || spec.source_path.extension() == ".C") { | ||||
| extend(flags, _warning_flags); | extend(flags, _warning_flags); | ||||
| } | } | ||||
| std::optional<fs::path> gnu_depfile_path; | |||||
| if (_deps_mode == deps_mode::gnu) { | |||||
| gnu_depfile_path = spec.out_path; | |||||
| gnu_depfile_path->replace_extension(gnu_depfile_path->extension().string() + ".d"); | |||||
| extend(flags, {"-MD"sv, "-MF"sv, std::string_view(gnu_depfile_path->string())}); | |||||
| } else if (_deps_mode == deps_mode::msvc) { | |||||
| flags.push_back("/showIncludes"); | |||||
| } | |||||
| vector<string> command; | vector<string> command; | ||||
| for (auto arg : cmd_template) { | for (auto arg : cmd_template) { | ||||
| if (arg == "<FLAGS>") { | if (arg == "<FLAGS>") { | ||||
| command.push_back(arg); | command.push_back(arg); | ||||
| } | } | ||||
| } | } | ||||
| return command; | |||||
| return {command, gnu_depfile_path}; | |||||
| } | } | ||||
| vector<string> toolchain::create_archive_command(const archive_spec& spec) const noexcept { | vector<string> toolchain::create_archive_command(const archive_spec& spec) const noexcept { |
| #pragma once | #pragma once | ||||
| #include <dds/toolchain/deps.hpp> | |||||
| #include <dds/util/fs.hpp> | #include <dds/util/fs.hpp> | ||||
| #include <optional> | #include <optional> | ||||
| bool enable_warnings = false; | bool enable_warnings = false; | ||||
| }; | }; | ||||
| struct compile_command_info { | |||||
| std::vector<std::string> command; | |||||
| std::optional<fs::path> gnu_depfile_path; | |||||
| }; | |||||
| struct archive_spec { | struct archive_spec { | ||||
| std::vector<fs::path> input_files; | std::vector<fs::path> input_files; | ||||
| fs::path out_path; | fs::path out_path; | ||||
| std::string _exe_prefix; | std::string _exe_prefix; | ||||
| std::string _exe_suffix; | std::string _exe_suffix; | ||||
| enum deps_mode _deps_mode; | |||||
| public: | public: | ||||
| toolchain() = default; | toolchain() = default; | ||||
| 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; } | auto& executable_suffix() const noexcept { return _exe_suffix; } | ||||
| auto deps_mode() const noexcept { return _deps_mode; } | |||||
| 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; | |||||
| compile_command_info 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; | std::vector<std::string> create_link_executable_command(const link_exe_spec&) const noexcept; | ||||