Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion include/cppship/cmd/install.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ namespace cppship::cmd {

struct InstallOptions {
Profile profile = Profile::debug;
std::optional<std::string> binary;
};

int run_install(const InstallOptions& options);

}
}
60 changes: 45 additions & 15 deletions lib/cmd/install.cpp
Original file line number Diff line number Diff line change
@@ -1,43 +1,73 @@
#include "cppship/cmd/install.h"

#include <cstdlib>
#include <functional>

#include <gsl/narrow>
#include <range/v3/range/conversion.hpp>
#include <range/v3/view/transform.hpp>
#include <spdlog/spdlog.h>

#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<std::string> 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<std::string> binaries = std::invoke([&] {
if (options.binary) {
return std::vector<std::string> { *options.binary };
}

const auto tmp = layout.binaries();
return tmp | ranges::views::transform(&Target::name) | ranges::to<std::vector>();
});

return do_install(ctx, binaries, "/usr/local");
#endif
}
2 changes: 2 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ std::list<SubCommand> 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"),
});
});

Expand All @@ -173,6 +174,7 @@ std::list<SubCommand> 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) {
Expand Down