From e561cce71e2af06c6a58e9df09292100d0b745b3 Mon Sep 17 00:00:00 2001 From: qqiangwu Date: Sat, 5 Apr 2025 15:13:57 +0800 Subject: [PATCH] feat(install): exclude workspaces and add --bin option --- include/cppship/cmd/install.h | 3 +- lib/cmd/install.cpp | 60 ++++++++++++++++++++++++++--------- src/main.cpp | 2 ++ 3 files changed, 49 insertions(+), 16 deletions(-) diff --git a/include/cppship/cmd/install.h b/include/cppship/cmd/install.h index 0faaf10..c4f9684 100644 --- a/include/cppship/cmd/install.h +++ b/include/cppship/cmd/install.h @@ -6,8 +6,9 @@ namespace cppship::cmd { struct InstallOptions { Profile profile = Profile::debug; + std::optional binary; }; int run_install(const InstallOptions& options); -} \ No newline at end of file +} diff --git a/lib/cmd/install.cpp b/lib/cmd/install.cpp index 1ed292c..01198c5 100644 --- a/lib/cmd/install.cpp +++ b/lib/cmd/install.cpp @@ -1,43 +1,73 @@ #include "cppship/cmd/install.h" #include +#include #include +#include +#include #include #include "cppship/cmd/build.h" +#include "cppship/core/layout.h" #include "cppship/core/manifest.h" +#include "cppship/exception.h" #include "cppship/util/fs.h" #include "cppship/util/log.h" using namespace cppship; +namespace { + +int do_install(const cmd::BuildContext& ctx, std::span binaries, std::string_view prefix) +{ + for (const auto& bin : binaries) { + const auto bin_file = ctx.profile_dir / bin; + if (!fs::exists(bin_file)) { + warn("binary {} not found", bin_file.string()); + continue; + } + + const auto dst = fmt::format("{}/bin/{}", prefix, bin); + status("install", "{} to {}", bin_file.string(), dst); + fs::copy_file(bin_file, dst, fs::copy_options::overwrite_existing); + } + + return EXIT_SUCCESS; +} + +} + int cmd::run_install([[maybe_unused]] const InstallOptions& options) { // TODO(someone): fix me #ifdef _WINNDOWS throw Error { "install is not supported in Windows" }; #else - const int result = run_build({ .profile = options.profile }); - if (result != 0) { - return EXIT_FAILURE; + BuildContext ctx(options.profile); + if (ctx.manifest.is_workspace()) { + throw Error { "install for workspace is not supported" }; } - BuildContext ctx(options.profile); - Manifest manifest(ctx.metafile); - if (manifest.is_workspace()) { - throw Error { "install for workspace is not supported now" }; + const auto& layout = ctx.workspace.as_package(); + if (options.binary && !layout.binary(*options.binary).has_value()) { + throw InvalidCmdOption { "--bin", fmt::format("specified binary {} is not found", *options.binary) }; } - const auto bin_file = ctx.profile_dir / manifest.get_if_package()->name(); - if (!fs::exists(bin_file)) { - warn("no binary to install"); - return EXIT_SUCCESS; + const int result = run_build({ .profile = options.profile, .cmake_target = options.binary }); + if (result != 0) { + return EXIT_FAILURE; } - const auto dst = fmt::format("/usr/local/bin/{}", manifest.get_if_package()->name()); - status("install", "{} to {}", bin_file.string(), dst); - fs::copy_file(bin_file, dst, fs::copy_options::overwrite_existing); - return EXIT_SUCCESS; + std::vector binaries = std::invoke([&] { + if (options.binary) { + return std::vector { *options.binary }; + } + + const auto tmp = layout.binaries(); + return tmp | ranges::views::transform(&Target::name) | ranges::to(); + }); + + return do_install(ctx, binaries, "/usr/local"); #endif } diff --git a/src/main.cpp b/src/main.cpp index 4f6e152..51c80bb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -165,6 +165,7 @@ std::list build_commands(const ArgumentParser& common) auto& install = commands.emplace_back("install", common, [](const ArgumentParser& cmd) { return cmd::run_install({ .profile = parse_profile(cmd.get("--profile")), + .binary = cmd.present("bin"), }); }); @@ -173,6 +174,7 @@ std::list build_commands(const ArgumentParser& common) .help("build with specific profile") .metavar("profile") .default_value(std::string { kProfileRelease }); + install.parser.add_argument("--bin").metavar("name").help("install only the specified binary"); // run auto& run = commands.emplace_back("run", common, [](const ArgumentParser& cmd) {