| @@ -24,7 +24,7 @@ void create_archive_plan::archive(const build_env& env) const { | |||
| archive_spec ar; | |||
| ar.input_files = std::move(objects); | |||
| 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 | |||
| // in the logs | |||
| @@ -26,7 +26,7 @@ compile_command_info compile_file_plan::generate_compile_command(build_env_ref e | |||
| extend(spec.external_include_dirs, env.ureqs.include_paths(use)); | |||
| } | |||
| 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 { | |||
| @@ -43,7 +43,8 @@ void link_executable_plan::link(build_env_ref env, const library_plan& lib) cons | |||
| std::reverse(spec.inputs.begin(), spec.inputs.end()); | |||
| // 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()); | |||
| auto msg = fmt::format("[{}] Link: {:30}", | |||
| lib.qualified_name(), | |||
| @@ -13,30 +13,33 @@ void check_tc_compile(std::string_view tc_content, | |||
| auto tc = dds::parse_toolchain_json5(tc_content); | |||
| 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); | |||
| CHECK(cf_cmd_str == expected_compile); | |||
| 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); | |||
| dds::archive_spec ar_spec; | |||
| ar_spec.input_files.push_back("foo.o"); | |||
| ar_spec.input_files.push_back("bar.o"); | |||
| 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); | |||
| dds::link_exe_spec exe_spec; | |||
| exe_spec.inputs.push_back("foo.o"); | |||
| exe_spec.inputs.push_back("bar.a"); | |||
| 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); | |||
| CHECK(exe_cmd_str == expected_exe); | |||
| } | |||
| @@ -93,7 +96,7 @@ TEST_CASE("Manipulate a toolchain and file compilation") { | |||
| dds::compile_file_spec cfs; | |||
| cfs.source_path = "foo.cpp"; | |||
| 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 | |||
| == std::vector<std::string>{"g++", | |||
| "-fPIC", | |||
| @@ -108,7 +111,9 @@ TEST_CASE("Manipulate a toolchain and file compilation") { | |||
| "-ofoo.o"}); | |||
| 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 | |||
| == std::vector<std::string>{"g++", | |||
| "-fPIC", | |||
| @@ -126,7 +131,7 @@ TEST_CASE("Manipulate a toolchain and file compilation") { | |||
| "-ofoo.o"}); | |||
| 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 | |||
| == std::vector<std::string>{"g++", | |||
| "-fPIC", | |||
| @@ -6,6 +6,8 @@ | |||
| #include <dds/util/paths.hpp> | |||
| #include <dds/util/string.hpp> | |||
| #include <range/v3/view/transform.hpp> | |||
| #include <cassert> | |||
| #include <optional> | |||
| #include <string> | |||
| @@ -52,7 +54,25 @@ vector<string> toolchain::definition_args(std::string_view s) const noexcept { | |||
| 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, | |||
| path_ref, | |||
| toolchain_knobs knobs) const noexcept { | |||
| using namespace std::literals; | |||
| @@ -119,32 +139,30 @@ compile_command_info toolchain::create_compile_command(const compile_file_spec& | |||
| } | |||
| vector<string> toolchain::create_archive_command(const archive_spec& spec, | |||
| path_ref cwd, | |||
| toolchain_knobs) const noexcept { | |||
| vector<string> cmd; | |||
| auto out_arg = shortest_path_from(spec.out_path, cwd).string(); | |||
| for (auto& arg : _link_archive) { | |||
| 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 { | |||
| cmd.push_back(replace(arg, "[out]", spec.out_path.string())); | |||
| cmd.push_back(replace(arg, "[out]", out_arg)); | |||
| } | |||
| } | |||
| return cmd; | |||
| } | |||
| vector<string> toolchain::create_link_executable_command(const link_exe_spec& spec, | |||
| path_ref cwd, | |||
| toolchain_knobs) const noexcept { | |||
| vector<string> cmd; | |||
| for (auto& arg : _link_exe) { | |||
| 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 { | |||
| cmd.push_back(replace(arg, "[out]", spec.output.string())); | |||
| cmd.push_back(replace(arg, "[out]", shortest_path_from(spec.output, cwd).string())); | |||
| } | |||
| } | |||
| return cmd; | |||
| @@ -82,11 +82,15 @@ public: | |||
| 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> 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&, | |||
| path_ref cwd, | |||
| toolchain_knobs) const noexcept; | |||
| static std::optional<toolchain> get_builtin(std::string_view key) noexcept; | |||