archive_spec ar; | archive_spec ar; | ||||
ar.input_files = std::move(objects); | ar.input_files = std::move(objects); | ||||
ar.out_path = env.output_root / calc_archive_file_path(env.toolchain); | ar.out_path = env.output_root / calc_archive_file_path(env.toolchain); | ||||
auto ar_cmd = env.toolchain.create_archive_command(ar, env.knobs); | |||||
auto ar_cmd = env.toolchain.create_archive_command(ar, fs::current_path(), env.knobs); | |||||
// `out_relpath` is purely for the benefit of the user to have a short name | // `out_relpath` is purely for the benefit of the user to have a short name | ||||
// in the logs | // in the logs |
extend(spec.external_include_dirs, env.ureqs.include_paths(use)); | extend(spec.external_include_dirs, env.ureqs.include_paths(use)); | ||||
} | } | ||||
extend(spec.definitions, _rules.defs()); | extend(spec.definitions, _rules.defs()); | ||||
return env.toolchain.create_compile_command(spec, env.knobs); | |||||
return env.toolchain.create_compile_command(spec, dds::fs::current_path(), env.knobs); | |||||
} | } | ||||
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 { |
std::reverse(spec.inputs.begin(), spec.inputs.end()); | std::reverse(spec.inputs.begin(), spec.inputs.end()); | ||||
// Do it! | // Do it! | ||||
const auto link_command = env.toolchain.create_link_executable_command(spec, env.knobs); | |||||
const auto link_command | |||||
= env.toolchain.create_link_executable_command(spec, dds::fs::current_path(), env.knobs); | |||||
fs::create_directories(spec.output.parent_path()); | fs::create_directories(spec.output.parent_path()); | ||||
auto msg = fmt::format("[{}] Link: {:30}", | auto msg = fmt::format("[{}] Link: {:30}", | ||||
lib.qualified_name(), | lib.qualified_name(), |
auto tc = dds::parse_toolchain_json5(tc_content); | auto tc = dds::parse_toolchain_json5(tc_content); | ||||
dds::compile_file_spec cf; | dds::compile_file_spec cf; | ||||
cf.source_path = "foo.cpp"; | |||||
cf.out_path = "foo.o"; | |||||
auto cf_cmd = tc.create_compile_command(cf, dds::toolchain_knobs{}); | |||||
cf.source_path = "foo.cpp"; | |||||
cf.out_path = "foo.o"; | |||||
auto cf_cmd = tc.create_compile_command(cf, dds::fs::current_path(), dds::toolchain_knobs{}); | |||||
auto cf_cmd_str = dds::quote_command(cf_cmd.command); | 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, dds::toolchain_knobs{}); | |||||
cf_cmd_str = dds::quote_command(cf_cmd.command); | |||||
cf_cmd = tc.create_compile_command(cf, dds::fs::current_path(), dds::toolchain_knobs{}); | |||||
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; | ||||
ar_spec.input_files.push_back("foo.o"); | ar_spec.input_files.push_back("foo.o"); | ||||
ar_spec.input_files.push_back("bar.o"); | ar_spec.input_files.push_back("bar.o"); | ||||
ar_spec.out_path = "stuff.a"; | ar_spec.out_path = "stuff.a"; | ||||
auto ar_cmd = tc.create_archive_command(ar_spec, dds::toolchain_knobs{}); | |||||
auto ar_cmd_str = dds::quote_command(ar_cmd); | |||||
auto ar_cmd | |||||
= tc.create_archive_command(ar_spec, dds::fs::current_path(), dds::toolchain_knobs{}); | |||||
auto ar_cmd_str = dds::quote_command(ar_cmd); | |||||
CHECK(ar_cmd_str == expected_ar); | CHECK(ar_cmd_str == expected_ar); | ||||
dds::link_exe_spec exe_spec; | dds::link_exe_spec exe_spec; | ||||
exe_spec.inputs.push_back("foo.o"); | exe_spec.inputs.push_back("foo.o"); | ||||
exe_spec.inputs.push_back("bar.a"); | exe_spec.inputs.push_back("bar.a"); | ||||
exe_spec.output = "meow.exe"; | exe_spec.output = "meow.exe"; | ||||
auto exe_cmd = tc.create_link_executable_command(exe_spec, dds::toolchain_knobs{}); | |||||
auto exe_cmd = tc.create_link_executable_command(exe_spec, | |||||
dds::fs::current_path(), | |||||
dds::toolchain_knobs{}); | |||||
auto exe_cmd_str = dds::quote_command(exe_cmd); | auto exe_cmd_str = dds::quote_command(exe_cmd); | ||||
CHECK(exe_cmd_str == expected_exe); | CHECK(exe_cmd_str == expected_exe); | ||||
} | } | ||||
dds::compile_file_spec cfs; | dds::compile_file_spec cfs; | ||||
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, dds::toolchain_knobs{}); | |||||
auto cmd = tc.create_compile_command(cfs, dds::fs::current_path(), dds::toolchain_knobs{}); | |||||
CHECK(cmd.command | CHECK(cmd.command | ||||
== std::vector<std::string>{"g++", | == std::vector<std::string>{"g++", | ||||
"-fPIC", | "-fPIC", | ||||
"-ofoo.o"}); | "-ofoo.o"}); | ||||
cfs.definitions.push_back("FOO=BAR"); | cfs.definitions.push_back("FOO=BAR"); | ||||
cmd = tc.create_compile_command(cfs, dds::toolchain_knobs{.is_tty = true}); | |||||
cmd = tc.create_compile_command(cfs, | |||||
dds::fs::current_path(), | |||||
dds::toolchain_knobs{.is_tty = true}); | |||||
CHECK(cmd.command | CHECK(cmd.command | ||||
== std::vector<std::string>{"g++", | == std::vector<std::string>{"g++", | ||||
"-fPIC", | "-fPIC", | ||||
"-ofoo.o"}); | "-ofoo.o"}); | ||||
cfs.include_dirs.push_back("fake-dir"); | cfs.include_dirs.push_back("fake-dir"); | ||||
cmd = tc.create_compile_command(cfs, dds::toolchain_knobs{}); | |||||
cmd = tc.create_compile_command(cfs, dds::fs::current_path(), dds::toolchain_knobs{}); | |||||
CHECK(cmd.command | CHECK(cmd.command | ||||
== std::vector<std::string>{"g++", | == std::vector<std::string>{"g++", | ||||
"-fPIC", | "-fPIC", |
#include <dds/util/paths.hpp> | #include <dds/util/paths.hpp> | ||||
#include <dds/util/string.hpp> | #include <dds/util/string.hpp> | ||||
#include <range/v3/view/transform.hpp> | |||||
#include <cassert> | #include <cassert> | ||||
#include <optional> | #include <optional> | ||||
#include <string> | #include <string> | ||||
return replace(_def_template, "[def]", s); | return replace(_def_template, "[def]", s); | ||||
} | } | ||||
static fs::path shortest_path_from(path_ref file, path_ref base) { | |||||
auto relative = file.lexically_normal().lexically_proximate(base); | |||||
auto abs = file.lexically_normal(); | |||||
if (relative.string().size() > abs.string().size()) { | |||||
return abs; | |||||
} else { | |||||
return relative; | |||||
} | |||||
} | |||||
template <typename R> | |||||
static auto shortest_path_args(path_ref base, R&& r) { | |||||
return ranges::views::all(r) // | |||||
| ranges::views::transform( | |||||
[base](auto&& path) { return shortest_path_from(path, base).string(); }); // | |||||
} | |||||
compile_command_info toolchain::create_compile_command(const compile_file_spec& spec, | compile_command_info toolchain::create_compile_command(const compile_file_spec& spec, | ||||
path_ref, | |||||
toolchain_knobs knobs) const noexcept { | toolchain_knobs knobs) const noexcept { | ||||
using namespace std::literals; | using namespace std::literals; | ||||
} | } | ||||
vector<string> toolchain::create_archive_command(const archive_spec& spec, | vector<string> toolchain::create_archive_command(const archive_spec& spec, | ||||
path_ref cwd, | |||||
toolchain_knobs) const noexcept { | toolchain_knobs) const noexcept { | ||||
vector<string> cmd; | vector<string> cmd; | ||||
auto out_arg = shortest_path_from(spec.out_path, cwd).string(); | |||||
for (auto& arg : _link_archive) { | for (auto& arg : _link_archive) { | ||||
if (arg == "[in]") { | if (arg == "[in]") { | ||||
std::transform(spec.input_files.begin(), | |||||
spec.input_files.end(), | |||||
std::back_inserter(cmd), | |||||
[](auto&& p) { return p.string(); }); | |||||
extend(cmd, shortest_path_args(cwd, spec.input_files)); | |||||
} else { | } else { | ||||
cmd.push_back(replace(arg, "[out]", spec.out_path.string())); | |||||
cmd.push_back(replace(arg, "[out]", out_arg)); | |||||
} | } | ||||
} | } | ||||
return cmd; | return cmd; | ||||
} | } | ||||
vector<string> toolchain::create_link_executable_command(const link_exe_spec& spec, | vector<string> toolchain::create_link_executable_command(const link_exe_spec& spec, | ||||
path_ref cwd, | |||||
toolchain_knobs) const noexcept { | toolchain_knobs) const noexcept { | ||||
vector<string> cmd; | vector<string> cmd; | ||||
for (auto& arg : _link_exe) { | for (auto& arg : _link_exe) { | ||||
if (arg == "[in]") { | if (arg == "[in]") { | ||||
std::transform(spec.inputs.begin(), | |||||
spec.inputs.end(), | |||||
std::back_inserter(cmd), | |||||
[](auto&& p) { return p.string(); }); | |||||
extend(cmd, shortest_path_args(cwd, spec.inputs)); | |||||
} else { | } else { | ||||
cmd.push_back(replace(arg, "[out]", spec.output.string())); | |||||
cmd.push_back(replace(arg, "[out]", shortest_path_from(spec.output, cwd).string())); | |||||
} | } | ||||
} | } | ||||
return cmd; | return cmd; |
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> external_include_args(const fs::path& p) const noexcept; | std::vector<std::string> external_include_args(const fs::path& p) const noexcept; | ||||
compile_command_info create_compile_command(const compile_file_spec&, | |||||
toolchain_knobs) const noexcept; | |||||
std::vector<std::string> create_archive_command(const archive_spec&, | |||||
toolchain_knobs) const noexcept; | |||||
compile_command_info | |||||
create_compile_command(const compile_file_spec&, path_ref cwd, toolchain_knobs) const noexcept; | |||||
std::vector<std::string> | |||||
create_archive_command(const archive_spec&, path_ref cwd, toolchain_knobs) const noexcept; | |||||
std::vector<std::string> create_link_executable_command(const link_exe_spec&, | std::vector<std::string> create_link_executable_command(const link_exe_spec&, | ||||
path_ref cwd, | |||||
toolchain_knobs) const noexcept; | toolchain_knobs) const noexcept; | ||||
static std::optional<toolchain> get_builtin(std::string_view key) noexcept; | static std::optional<toolchain> get_builtin(std::string_view key) noexcept; |