| @@ -23,9 +23,11 @@ void create_archive_plan::archive(const build_env& env) const { | |||
| ; | |||
| // Build up the archive command | |||
| archive_spec ar; | |||
| auto ar_cwd = env.output_root; | |||
| 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, fs::current_path(), env.knobs); | |||
| auto ar_cmd = env.toolchain.create_archive_command(ar, ar_cwd, env.knobs); | |||
| // `out_relpath` is purely for the benefit of the user to have a short name | |||
| // in the logs | |||
| @@ -43,7 +45,8 @@ void create_archive_plan::archive(const build_env& env) const { | |||
| // Do it! | |||
| dds_log(info, "[{}] Archive: {}", _qual_name, out_relpath); | |||
| auto&& [dur_ms, ar_res] = timed<std::chrono::milliseconds>([&] { return run_proc(ar_cmd); }); | |||
| auto&& [dur_ms, ar_res] = timed<std::chrono::milliseconds>( | |||
| [&] { return run_proc(proc_options{.command = ar_cmd, .cwd = ar_cwd}); }); | |||
| dds_log(info, "[{}] Archive: {} - {:L}ms", _qual_name, out_relpath, dur_ms.count()); | |||
| // Check, log, and throw | |||
| @@ -1,6 +1,7 @@ | |||
| #pragma once | |||
| #include <chrono> | |||
| #include <filesystem> | |||
| #include <optional> | |||
| #include <string> | |||
| #include <string_view> | |||
| @@ -25,8 +26,8 @@ std::string quote_command(const Container& c) { | |||
| } | |||
| struct proc_result { | |||
| int signal = 0; | |||
| int retc = 0; | |||
| int signal = 0; | |||
| int retc = 0; | |||
| bool timed_out = false; | |||
| std::string output; | |||
| @@ -36,6 +37,8 @@ struct proc_result { | |||
| struct proc_options { | |||
| std::vector<std::string> command; | |||
| std::optional<std::filesystem::path> cwd = std::nullopt; | |||
| /** | |||
| * Timeout for the subprocess, in milliseconds. If zero, will wait forever | |||
| */ | |||
| @@ -1,6 +1,7 @@ | |||
| #ifndef _WIN32 | |||
| #include "./proc.hpp" | |||
| #include <dds/util/fs.hpp> | |||
| #include <dds/util/log.hpp> | |||
| #include <dds/util/signal.hpp> | |||
| @@ -25,17 +26,18 @@ void check_rc(bool b, std::string_view s) { | |||
| } | |||
| } | |||
| ::pid_t | |||
| spawn_child(const std::vector<std::string>& command, int stdout_pipe, int close_me) noexcept { | |||
| ::pid_t spawn_child(const proc_options& opts, int stdout_pipe, int close_me) noexcept { | |||
| // We must allocate BEFORE fork(), since the CRT might stumble with malloc()-related locks that | |||
| // are held during the fork(). | |||
| std::vector<const char*> strings; | |||
| strings.reserve(command.size() + 1); | |||
| for (auto& s : command) { | |||
| strings.reserve(opts.command.size() + 1); | |||
| for (auto& s : opts.command) { | |||
| strings.push_back(s.data()); | |||
| } | |||
| strings.push_back(nullptr); | |||
| std::string workdir = opts.cwd.value_or(fs::current_path()).string(); | |||
| auto child_pid = ::fork(); | |||
| if (child_pid != 0) { | |||
| return child_pid; | |||
| @@ -46,6 +48,8 @@ spawn_child(const std::vector<std::string>& command, int stdout_pipe, int close_ | |||
| check_rc(rc != -1, "Failed to dup2 stdout"); | |||
| rc = dup2(stdout_pipe, STDERR_FILENO); | |||
| check_rc(rc != -1, "Failed to dup2 stderr"); | |||
| rc = ::chdir(workdir.data()); | |||
| check_rc(rc != -1, "Failed to chdir() for subprocess"); | |||
| ::execvp(strings[0], (char* const*)strings.data()); | |||
| @@ -73,7 +77,7 @@ proc_result dds::run_proc(const proc_options& opts) { | |||
| int read_pipe = stdio_pipe[0]; | |||
| int write_pipe = stdio_pipe[1]; | |||
| auto child = spawn_child(opts.command, write_pipe, read_pipe); | |||
| auto child = spawn_child(opts, write_pipe, read_pipe); | |||
| ::close(write_pipe); | |||
| @@ -1,6 +1,7 @@ | |||
| #ifdef _WIN32 | |||
| #include "./proc.hpp" | |||
| #include <dds/util/fs.hpp> | |||
| #include <dds/util/log.hpp> | |||
| #include <fmt/core.h> | |||
| @@ -72,7 +73,7 @@ proc_result dds::run_proc(const proc_options& opts) { | |||
| true, | |||
| CREATE_NEW_PROCESS_GROUP, | |||
| nullptr, | |||
| nullptr, | |||
| opts.cwd.value_or(fs::current_path()).c_str(), | |||
| &startup_info, | |||
| &proc_info); | |||
| if (!okay) { | |||