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
1 change: 1 addition & 0 deletions .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ Language: Cpp
BasedOnStyle: WebKit
BinPackArguments: false
ColumnLimit: 120
NamespaceIndentation: None
InsertNewlineAtEOF: true
InsertTrailingCommas: Wrapped
IncludeBlocks: Regroup
Expand Down
2 changes: 1 addition & 1 deletion conanfile.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ argparse/2.9
spdlog/1.11.0

[test_requires]
gtest/cci.20210126
gtest/1.16.0

[generators]
CMakeDeps
Expand Down
9 changes: 7 additions & 2 deletions include/cppship/cmd/build.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <cstdint>
#include <functional>
#include <set>
#include <string>
#include <thread>
Expand All @@ -12,6 +13,7 @@
#include "cppship/core/manifest.h"
#include "cppship/core/profile.h"
#include "cppship/core/workspace.h"
#include "cppship/util/cmd_runner.h"
#include "cppship/util/fs.h"
#include "cppship/util/repo.h"

Expand All @@ -23,6 +25,7 @@ struct BuildOptions {
int max_concurrency = gsl::narrow_cast<int>(std::thread::hardware_concurrency());
Profile profile = Profile::debug;
bool dry_run = false;
std::optional<std::string> package;
std::optional<std::string> target;
std::set<BuildGroup> groups;
};
Expand Down Expand Up @@ -57,6 +60,8 @@ struct BuildContext {
}

[[nodiscard]] bool is_expired(const fs::path& path) const;

[[nodiscard]] std::optional<std::string> get_active_package() const;
};

int run_build(const BuildOptions& options);
Expand All @@ -72,12 +77,12 @@ void cppship_install(

namespace cmd_internals {

std::string cmake_gen_config(const BuildContext& ctx, bool for_standalone_cmake = false);
std::string cmake_gen_config(const BuildContext& ctx, bool for_standalone_cmake = false);

}

void cmake_setup(const BuildContext& ctx);

int cmake_build(const BuildContext& ctx, const BuildOptions& options);
int cmake_build(const BuildContext& ctx, const BuildOptions& options, const util::CmdRunner& runner = {});

}
7 changes: 3 additions & 4 deletions include/cppship/core/manifest.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class Manifest {

const PackageManifest* get_if_package() const { return std::get_if<PackageManifest>(&packages_); }

const PackageManifest* get(const fs::path& p) const
const PackageManifest* get_by_path(const fs::path& p) const
{
const auto* map = std::get_if<1>(&packages_);
if (map == nullptr) {
Expand All @@ -78,15 +78,14 @@ class Manifest {
return it == map->end() ? nullptr : &it->second;
}

const PackageManifest* get(std::string_view package) const;

const auto& list_packages() const { return std::get<1>(packages_); }

const std::vector<DeclaredDependency>& dependencies() const { return mDependencies; }

const std::vector<DeclaredDependency>& dev_dependencies() const { return mDevDependencies; }

private:
const PackageManifest& as_package_() const { return std::get<PackageManifest>(packages_); }

private:
std::variant<std::monostate, std::map<fs::path, PackageManifest>, PackageManifest> packages_;

Expand Down
14 changes: 13 additions & 1 deletion include/cppship/exception.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,18 @@ class CmdNotFound : public Error {
std::string mCmd;
};

class InvalidCmdOption : public Error {
public:
explicit InvalidCmdOption(std::string_view option, const std::string& msg)
: Error(msg)
, mOption(option)
{
}

private:
std::string mOption;
};

class RunCmdFailed : public Error {
public:
RunCmdFailed(const int status, std::string_view cmd)
Expand Down Expand Up @@ -54,4 +66,4 @@ class LayoutError : public Error {
using Error::Error;
};

}
}
25 changes: 25 additions & 0 deletions include/cppship/util/cmd_runner.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

#include <functional>
#include <string_view>

namespace cppship::util {

class CmdRunner {
public:
CmdRunner() = default;

template <class Fn>
requires(!std::is_same_v<Fn, CmdRunner>)
explicit CmdRunner(Fn&& fn)
: mHook(std::forward<Fn>(fn))
{
}

int run(std::string_view cmd) const;

private:
std::function<int(std::string_view)> mHook;
};

}
7 changes: 6 additions & 1 deletion include/cppship/util/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,9 @@ template <class Input, class Pred> inline auto split(Input&& input, Pred pred)
return split_to<std::vector>(std::forward<Input>(input), pred);
}

}
inline bool contains(std::string_view corpus, std::string_view patten)
{
return corpus.find(patten) != std::string_view::npos;
}

}
47 changes: 41 additions & 6 deletions lib/cmd/build.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <filesystem>
#include <fstream>
#include <optional>
#include <sstream>
#include <string>

Expand Down Expand Up @@ -32,6 +33,7 @@
#include "cppship/exception.h"
#include "cppship/util/assert.h"
#include "cppship/util/cmd.h"
#include "cppship/util/cmd_runner.h"
#include "cppship/util/fs.h"
#include "cppship/util/git.h"
#include "cppship/util/io.h"
Expand Down Expand Up @@ -60,6 +62,17 @@ bool cmd::BuildContext::is_expired(const fs::path& path) const
return fs::last_write_time(path) < *ranges::max_element(manifest_last_update_times);
}

std::optional<std::string> cmd::BuildContext::get_active_package() const
{
if (package_root == root) {
return std::nullopt;
}

const auto path = fs::relative(package_root, root);
const auto* p = manifest.get_by_path(path);
return p != nullptr ? std::make_optional<std::string>(p->name()) : std::nullopt;
}

int cmd::run_build(const BuildOptions& options)
{
BuildContext ctx(options.profile);
Expand Down Expand Up @@ -173,7 +186,7 @@ void cmd::conan_setup(const BuildContext& ctx)

oss << '\n'
<< "[test_requires]\n"
<< "gtest/cci.20210126\n"
<< "gtest/1.16.0\n"
<< "benchmark/1.7.1\n";
for (const auto& dep : result.conan_dev_dependencies) {
const auto& desc = std::get<ConanDep>(dep.desc);
Expand Down Expand Up @@ -282,7 +295,7 @@ std::string cmd::cmd_internals::cmake_gen_config(const BuildContext& ctx, bool f
});

for (const auto& [path, layout] : ctx.workspace) {
const auto* manifest = ctx.manifest.get(path);
const auto* manifest = ctx.manifest.get_by_path(path);
enforce(manifest != nullptr, "manifest and workspace inconsistent");

gen.add(layout, *manifest, resolved_deps);
Expand Down Expand Up @@ -381,24 +394,46 @@ std::string_view to_cmake_group(cmd::BuildGroup group)
std::abort();
}

std::string to_cmake_group(cmd::BuildGroup group, const cmd::BuildContext& ctx, const cmd::BuildOptions& options)
{
auto cmake_group = to_cmake_group(group);
const auto package = options.package.has_value() ? options.package : ctx.get_active_package();
if (!package.has_value()) {
return std::string(cmake_group);
}

return fmt::format("{}_{}", *package, cmake_group);
}

void validate_options(const cmd::BuildContext& ctx, const cmd::BuildOptions& options)
{
if (options.package.has_value()) {
if (ctx.manifest.get(*options.package) == nullptr) {
throw InvalidCmdOption("package", "invalid package specified by --package");
}
}
}

}

int cmd::cmake_build(const BuildContext& ctx, const BuildOptions& options)
int cmd::cmake_build(const BuildContext& ctx, const BuildOptions& options, const util::CmdRunner& runner)
{
validate_options(ctx, options);

auto cmd = fmt::format("cmake --build {} -j {} --config {}",
ctx.profile_dir.string(),
options.max_concurrency,
to_string(options.profile));
if (options.target) {
cmd += fmt::format(" --target {}", *options.target);
} else if (options.groups.empty()) {
cmd += fmt::format(" --target {}", cmake::kCppshipGroupBinaries);
cmd += fmt::format(" --target {}", to_cmake_group(BuildGroup::binaries, ctx, options));
} else {
for (const auto group : options.groups) {
cmd += fmt::format(" --target {}", to_cmake_group(group));
cmd += fmt::format(" --target {}", to_cmake_group(group, ctx, options));
}
}

status("build", "{}", cmd);
return run_cmd(cmd);
return runner.run(cmd);
}
23 changes: 21 additions & 2 deletions lib/core/manifest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
#include <fmt/os.h>
#include <range/v3/action/push_back.hpp>
#include <range/v3/algorithm/any_of.hpp>
#include <range/v3/algorithm/find.hpp>
#include <range/v3/view/concat.hpp>
#include <range/v3/view/filter.hpp>
#include <toml.hpp>
#include <toml/get.hpp>
#include <toml/value.hpp>
Expand Down Expand Up @@ -119,7 +121,7 @@ std::vector<DeclaredDependency> parse_dependencies(const toml::value& manifest,
} else if (dep_config.is_table()) {
if (dep_config.contains("git")) {
GitDep desc;
desc.git = find<std::string>(dep_config, "git");
desc.git = toml::find<std::string>(dep_config, "git");
desc.commit = find_or<std::string>(dep_config, "commit", "");
if (desc.git.empty()) {
throw Error { fmt::format("invalid git url {}", desc.git) };
Expand Down Expand Up @@ -276,7 +278,7 @@ Manifest::Manifest(const fs::path& file)
std::set<std::string> package_names;
for (const auto& member : get_list(workspace, "members")) {
auto package_path = fs::path(member);
const auto package_manifest_path = package_path / kRepoConfigFile;
const auto package_manifest_path = file.parent_path() / package_path / kRepoConfigFile;
if (!fs::exists(package_manifest_path)) {
throw Error { fmt::format("invalid workspace member {}", member) };
}
Expand All @@ -298,6 +300,23 @@ Manifest::Manifest(const fs::path& file)
}
}

const PackageManifest* Manifest::get(std::string_view package) const
{
switch (packages_.index()) {
case 1: {
const auto& ps = views::values(std::get<1>(packages_));
const auto it = find(ps, package, &PackageManifest::name);
return it != ps.end() ? &*it : nullptr;
}
case 2: {
const auto& p = std::get<2>(packages_);
return p.name() == package ? &p : nullptr;
}
default:
return nullptr;
}
}

void cppship::generate_manifest(std::string_view name, CxxStd std, const fs::path& dir)
{
if (!fs::exists(dir)) {
Expand Down
16 changes: 16 additions & 0 deletions lib/util/cmd_runner.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include "cppship/util/cmd_runner.h"

#include "cppship/util/cmd.h"

namespace cppship::util {

int CmdRunner::run(std::string_view cmd) const
{
if (mHook) {
return mHook(cmd);
}

return run_cmd(cmd);
}

}
8 changes: 7 additions & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ struct SubCommand {
int run() { return cmd_runner(parser); }
};

namespace {

Profile get_profile(const ArgumentParser& cmd)
{
if (cmd.is_used("profile")) {
Expand Down Expand Up @@ -131,6 +133,7 @@ std::list<SubCommand> build_commands(const ArgumentParser& common)
.max_concurrency = get_concurrency(cmd),
.profile = get_profile(cmd),
.dry_run = cmd.get<bool>("-d"),
.package = cmd.present("--package"),
.groups = groups,
});
});
Expand All @@ -146,6 +149,7 @@ std::list<SubCommand> build_commands(const ArgumentParser& common)
.help("dry-run, generate compile_commands.json")
.default_value(false)
.implicit_value(true);
build.parser.add_argument("--package").help("package to build");
build.parser.add_argument("--profile").help("build with specific profile").default_value(kProfileDebug);
build.parser.add_argument("--examples").help("build all examples").default_value(false).implicit_value(true);
build.parser.add_argument("--tests").help("build all tests").default_value(false).implicit_value(true);
Expand Down Expand Up @@ -274,6 +278,8 @@ std::list<SubCommand> build_commands(const ArgumentParser& common)
return commands;
}

}

int main(int argc, const char* argv[])
try {
spdlog::set_pattern("%v");
Expand Down Expand Up @@ -322,4 +328,4 @@ try {
} catch (const std::exception& e) {
error("unknown error {}", e.what());
return EXIT_FAILURE;
}
}
Loading