} | } | ||||
void create_archive_plan::archive(const build_env& env) const { | void create_archive_plan::archive(const build_env& env) const { | ||||
// Convert the file compilation plans into the paths to their respective object files. | |||||
const auto objects = // | const auto objects = // | ||||
_compile_files // | _compile_files // | ||||
| ranges::views::transform([&](auto&& cf) { return cf.calc_object_file_path(env); }) | | ranges::views::transform([&](auto&& cf) { return cf.calc_object_file_path(env); }) | ||||
| ranges::to_vector // | | ranges::to_vector // | ||||
; | ; | ||||
// Build up the archive command | |||||
archive_spec ar; | archive_spec ar; | ||||
ar.input_files = std::move(objects); | |||||
ar.out_path = calc_archive_file_path(env); | |||||
auto ar_cmd = env.toolchain.create_archive_command(ar); | |||||
ar.input_files = std::move(objects); | |||||
ar.out_path = calc_archive_file_path(env); | |||||
auto ar_cmd = env.toolchain.create_archive_command(ar); | |||||
// `out_relpath` is purely for the benefit of the user to have a short name | |||||
// in the logs | |||||
auto out_relpath = fs::relative(ar.out_path, env.output_root).string(); | auto out_relpath = fs::relative(ar.out_path, env.output_root).string(); | ||||
// Different archiving tools behave differently between platforms depending on whether the | |||||
// archive file exists. Make it uniform by simply removing the prior copy. | |||||
if (fs::exists(ar.out_path)) { | if (fs::exists(ar.out_path)) { | ||||
fs::remove(ar.out_path); | fs::remove(ar.out_path); | ||||
} | } | ||||
spdlog::info("[{}] Archive: {}", _name, out_relpath); | |||||
// Ensure the parent directory exists | |||||
fs::create_directories(ar.out_path.parent_path()); | fs::create_directories(ar.out_path.parent_path()); | ||||
// Do it! | |||||
spdlog::info("[{}] Archive: {}", _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(ar_cmd); }); | ||||
spdlog::info("[{}] Archive: {} - {:n}ms", _name, out_relpath, dur_ms.count()); | spdlog::info("[{}] Archive: {} - {:n}ms", _name, out_relpath, dur_ms.count()); | ||||
// Check, log, and throw | |||||
if (!ar_res.okay()) { | if (!ar_res.okay()) { | ||||
spdlog::error("Creating static library archive failed: {}", out_relpath); | spdlog::error("Creating static library archive failed: {}", out_relpath); | ||||
spdlog::error("Subcommand FAILED: {}\n{}", quote_command(ar_cmd), ar_res.output); | spdlog::error("Subcommand FAILED: {}\n{}", quote_command(ar_cmd), ar_res.output); |
#include <dds/util/fs.hpp> | #include <dds/util/fs.hpp> | ||||
#include <string> | #include <string> | ||||
#include <string_view> | |||||
namespace dds { | namespace dds { | ||||
/** | |||||
* Represents the intention to create an library archive. This also contains | |||||
* the compile plans for individual files. | |||||
* | |||||
* This is distinct from `library_plan`, becuase this corresponds to an actual | |||||
* static library and its compiled source files. | |||||
*/ | |||||
class create_archive_plan { | class create_archive_plan { | ||||
std::string _name; | |||||
fs::path _subdir; | |||||
/// The name of the archive. Not the filename, but the base name thereof | |||||
std::string _name; | |||||
/// The subdirectory in which the archive should be generated. | |||||
fs::path _subdir; | |||||
/// The plans for compiling the constituent source files of this library | |||||
std::vector<compile_file_plan> _compile_files; | std::vector<compile_file_plan> _compile_files; | ||||
public: | public: | ||||
/** | |||||
* Construct an archive plan. | |||||
* @param name The name of the archive | |||||
* @param subdir The subdirectory in which the archive and its object files | |||||
* will be placed | |||||
* @param cfs The file compilation plans that will be collected together to | |||||
* form the static library. | |||||
*/ | |||||
create_archive_plan(std::string_view name, path_ref subdir, std::vector<compile_file_plan> cfs) | create_archive_plan(std::string_view name, path_ref subdir, std::vector<compile_file_plan> cfs) | ||||
: _name(name) | : _name(name) | ||||
, _subdir(subdir) | , _subdir(subdir) | ||||
, _compile_files(std::move(cfs)) {} | , _compile_files(std::move(cfs)) {} | ||||
/** | |||||
* Get the name of the archive library. | |||||
*/ | |||||
const std::string& name() const noexcept { return _name; } | |||||
/** | |||||
* Calculate the absolute path where the generated archive libary file will | |||||
* be generated after execution. | |||||
* @param env The build environment for the archival. | |||||
*/ | |||||
fs::path calc_archive_file_path(build_env_ref env) const noexcept; | fs::path calc_archive_file_path(build_env_ref env) const noexcept; | ||||
auto& compile_files() const noexcept { return _compile_files; } | |||||
/** | |||||
* Get the compilation plans for this library. | |||||
*/ | |||||
auto& compile_files() const noexcept { return _compile_files; } | |||||
/** | |||||
* Perform the actual archive generation. Expects all compilations to have | |||||
* completed. | |||||
* @param env The build environment for the archival. | |||||
*/ | |||||
void archive(build_env_ref env) const; | void archive(build_env_ref env) const; | ||||
}; | }; | ||||