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: 3 additions & 0 deletions src/Builder/BuildProfile.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class BuildProfile {
enum Type : uint8_t {
Dev,
Release,
Test,
};

private:
Expand Down Expand Up @@ -56,6 +57,8 @@ struct fmt::formatter<cabin::BuildProfile> {
return fmt::format_to(ctx.out(), "dev");
case cabin::BuildProfile::Release:
return fmt::format_to(ctx.out(), "release");
case cabin::BuildProfile::Test:
return fmt::format_to(ctx.out(), "test");
}
__builtin_unreachable();
} else {
Expand Down
33 changes: 11 additions & 22 deletions src/Cmd/Test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,13 @@
namespace cabin {

class Test {
struct TestArgs {
BuildProfile buildProfile = BuildProfile::Dev;
};

TestArgs args;
Manifest manifest;
std::string unittestTargetPrefix;
std::vector<std::string> unittestTargets;

Test(TestArgs args, Manifest manifest)
: args(std::move(args)), manifest(std::move(manifest)) {}
explicit Test(Manifest manifest) : manifest(std::move(manifest)) {}

static Result<TestArgs> parseArgs(CliArgsView cliArgs);
static Result<void> parseArgs(CliArgsView cliArgs);
Result<void> compileTestTargets();
Result<void> runTestTargets();

Expand All @@ -49,25 +43,19 @@ const Subcmd TEST_CMD = //
Subcmd{ "test" }
.setShort("t")
.setDesc("Run the tests of a local package")
.addOpt(OPT_RELEASE)
.addOpt(OPT_JOBS)
.setMainFn(Test::exec);

Result<Test::TestArgs>
Result<void>
Test::parseArgs(const CliArgsView cliArgs) {
TestArgs args;

for (auto itr = cliArgs.begin(); itr != cliArgs.end(); ++itr) {
const std::string_view arg = *itr;

const auto control = Try(Cli::handleGlobalOpts(itr, cliArgs.end(), "test"));
if (control == Cli::Return) {
return Ok(args);
return Ok();
} else if (control == Cli::Continue) {
continue;
} else if (arg == "-r" || arg == "--release") {
Diag::warn("Tests in release mode possibly disables assert macros.");
args.buildProfile = BuildProfile::Release;
} else if (arg == "-j" || arg == "--jobs") {
if (itr + 1 == cliArgs.end()) {
return Subcmd::missingOptArgumentFor(arg);
Expand All @@ -85,15 +73,16 @@ Test::parseArgs(const CliArgsView cliArgs) {
}
}

return Ok(args);
return Ok();
}

Result<void>
Test::compileTestTargets() {
const auto start = std::chrono::steady_clock::now();

const BuildProfile buildProfile = BuildProfile::Test;
const BuildConfig config =
Try(emitMakefile(manifest, args.buildProfile, /*includeDevDeps=*/true));
Try(emitMakefile(manifest, buildProfile, /*includeDevDeps=*/true));

// Collect test targets from the generated Makefile.
unittestTargetPrefix = (config.outBasePath / "unittests").string() + '/';
Expand Down Expand Up @@ -150,9 +139,9 @@ Test::compileTestTargets() {
const auto end = std::chrono::steady_clock::now();
const std::chrono::duration<double> elapsed = end - start;

const Profile& profile = manifest.profiles.at(args.buildProfile);
const Profile& profile = manifest.profiles.at(buildProfile);
Diag::info(
"Finished", "`{}` profile [{}] target(s) in {:.2f}s", args.buildProfile,
"Finished", "`{}` profile [{}] target(s) in {:.2f}s", buildProfile,
profile, elapsed.count()
);

Expand Down Expand Up @@ -206,9 +195,9 @@ Test::runTestTargets() {

Result<void>
Test::exec(const CliArgsView cliArgs) {
const TestArgs args = Try(parseArgs(cliArgs));
Try(parseArgs(cliArgs));
Manifest manifest = Try(Manifest::tryParse());
Test cmd(args, std::move(manifest));
Test cmd(std::move(manifest));

Try(cmd.compileTestTargets());
if (cmd.unittestTargets.empty()) {
Expand Down
126 changes: 86 additions & 40 deletions src/Manifest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -154,76 +154,109 @@ static Result<Profile>
parseDevProfile(
const toml::value& val, const BaseProfile& baseProfile
) noexcept {
auto devCxxflags = Try(validateFlags(
static constexpr const char* key = "dev";

auto cxxflags = Try(validateFlags(
"cxxflags", toml::find_or<std::vector<std::string>>(
val, "profile", "dev", "cxxflags", baseProfile.cxxflags
val, "profile", key, "cxxflags", baseProfile.cxxflags
)
));
auto devLdflags = Try(validateFlags(
auto ldflags = Try(validateFlags(
"ldflags", toml::find_or<std::vector<std::string>>(
val, "profile", "dev", "ldflags", baseProfile.ldflags
val, "profile", key, "ldflags", baseProfile.ldflags
)
));
const auto devLto =
toml::find_or<bool>(val, "profile", "dev", "lto", baseProfile.lto);
const auto devDebug = toml::find_or<bool>(
val, "profile", "dev", "debug", baseProfile.debug.unwrap_or(true)
);
const auto devCompDb =
toml::find_or<bool>(val, "profile", "dev", "compdb", baseProfile.compDb);
const auto devOptLevel = Try(validateOptLevel(
const auto lto =
toml::find_or<bool>(val, "profile", key, "lto", baseProfile.lto);
const auto debug = toml::find_or<bool>(
val, "profile", key, "debug", baseProfile.debug.unwrap_or(true)
);
const auto compDb =
toml::find_or<bool>(val, "profile", key, "compdb", baseProfile.compDb);
const auto optLevel = Try(validateOptLevel(
toml::find_or<std::uint8_t>(
val, "profile", "dev", "opt-level", baseProfile.optLevel.unwrap_or(0)
val, "profile", key, "opt-level", baseProfile.optLevel.unwrap_or(0)
)
));

return Ok(Profile(
std::move(devCxxflags), std::move(devLdflags), devLto, devDebug,
devCompDb, devOptLevel
std::move(cxxflags), std::move(ldflags), lto, debug, compDb, optLevel
));
}

static Result<Profile>
parseReleaseProfile(
const toml::value& val, const BaseProfile& baseProfile
) noexcept {
auto relCxxflags = Try(validateFlags(
"cxxflags",
toml::find_or<std::vector<std::string>>(
val, "profile", "release", "cxxflags", baseProfile.cxxflags
static constexpr const char* key = "release";

auto cxxflags = Try(validateFlags(
"cxxflags", toml::find_or<std::vector<std::string>>(
val, "profile", key, "cxxflags", baseProfile.cxxflags
)
));
auto ldflags = Try(validateFlags(
"ldflags", toml::find_or<std::vector<std::string>>(
val, "profile", key, "ldflags", baseProfile.ldflags
)
));
const auto lto =
toml::find_or<bool>(val, "profile", key, "lto", baseProfile.lto);
const auto debug = toml::find_or<bool>(
val, "profile", key, "debug", baseProfile.debug.unwrap_or(false)
);
const auto compDb =
toml::find_or<bool>(val, "profile", key, "compdb", baseProfile.compDb);
const auto optLevel = Try(validateOptLevel(
toml::find_or<std::uint8_t>(
val, "profile", key, "opt-level", baseProfile.optLevel.unwrap_or(3)
)
));
auto relLdflags = Try(validateFlags(

return Ok(Profile(
std::move(cxxflags), std::move(ldflags), lto, debug, compDb, optLevel
));
}

// Inherits from `dev`.
static Result<Profile>
parseTestProfile(const toml::value& val, const Profile& devProfile) noexcept {
static constexpr const char* key = "test";

auto cxxflags = Try(validateFlags(
"cxxflags", toml::find_or<std::vector<std::string>>(
val, "profile", key, "cxxflags", devProfile.cxxflags
)
));
auto ldflags = Try(validateFlags(
"ldflags", toml::find_or<std::vector<std::string>>(
val, "profile", "release", "ldflags", baseProfile.ldflags
val, "profile", key, "ldflags", devProfile.ldflags
)
));
const auto relLto =
toml::find_or<bool>(val, "profile", "release", "lto", baseProfile.lto);
const auto relDebug = toml::find_or<bool>(
val, "profile", "release", "debug", baseProfile.debug.unwrap_or(false)
);
const auto relCompDb = toml::find_or<bool>(
val, "profile", "release", "compdb", baseProfile.compDb
);
const auto relOptLevel = Try(validateOptLevel(
const auto lto =
toml::find_or<bool>(val, "profile", key, "lto", devProfile.lto);
const auto debug =
toml::find_or<bool>(val, "profile", key, "debug", devProfile.debug);
const auto compDb =
toml::find_or<bool>(val, "profile", key, "compdb", devProfile.compDb);
const auto optLevel = Try(validateOptLevel(
toml::find_or<std::uint8_t>(
val, "profile", "release", "opt-level",
baseProfile.optLevel.unwrap_or(3)
val, "profile", key, "opt-level", devProfile.optLevel
)
));

return Ok(Profile(
std::move(relCxxflags), std::move(relLdflags), relLto, relDebug,
relCompDb, relOptLevel
std::move(cxxflags), std::move(ldflags), lto, debug, compDb, optLevel
));
}

static Result<std::unordered_map<BuildProfile, Profile>>
parseProfiles(const toml::value& val) noexcept {
std::unordered_map<BuildProfile, Profile> profiles;
const BaseProfile baseProfile = Try(parseBaseProfile(val));
profiles.emplace(BuildProfile::Dev, Try(parseDevProfile(val, baseProfile)));
Profile devProfile = Try(parseDevProfile(val, baseProfile));
profiles.emplace(BuildProfile::Test, Try(parseTestProfile(val, devProfile)));
profiles.emplace(BuildProfile::Dev, std::move(devProfile));
profiles.emplace(
BuildProfile::Release, Try(parseReleaseProfile(val, baseProfile))
);
Expand Down Expand Up @@ -821,17 +854,19 @@ testParseProfiles() {
const toml::value empty = ""_toml;

const auto profiles = parseProfiles(empty).unwrap();
assertEq(profiles.size(), 2UL);
assertEq(profiles.size(), 3UL);
assertEq(profiles.at(BuildProfile::Dev), devProfileDefault);
assertEq(profiles.at(BuildProfile::Release), relProfileDefault);
assertEq(profiles.at(BuildProfile::Test), devProfileDefault);
}
{
const toml::value profOnly = "[profile]"_toml;

const auto profiles = parseProfiles(profOnly).unwrap();
assertEq(profiles.size(), 2UL);
assertEq(profiles.size(), 3UL);
assertEq(profiles.at(BuildProfile::Dev), devProfileDefault);
assertEq(profiles.at(BuildProfile::Release), relProfileDefault);
assertEq(profiles.at(BuildProfile::Test), devProfileDefault);
}
{
const toml::value baseOnly = R"(
Expand All @@ -851,9 +886,10 @@ testParseProfiles() {
);

const auto profiles = parseProfiles(baseOnly).unwrap();
assertEq(profiles.size(), 2UL);
assertEq(profiles.size(), 3UL);
assertEq(profiles.at(BuildProfile::Dev), expected);
assertEq(profiles.at(BuildProfile::Release), expected);
assertEq(profiles.at(BuildProfile::Test), expected);
}
{
const toml::value overwrite = R"(
Expand All @@ -868,9 +904,10 @@ testParseProfiles() {
)"_toml;

const auto profiles = parseProfiles(overwrite).unwrap();
assertEq(profiles.size(), 2UL);
assertEq(profiles.size(), 3UL);
assertEq(profiles.at(BuildProfile::Dev), devProfileDefault);
assertEq(profiles.at(BuildProfile::Release), relProfileDefault);
assertEq(profiles.at(BuildProfile::Test), devProfileDefault);
}
{
const toml::value overwrite = R"(
Expand All @@ -879,6 +916,9 @@ testParseProfiles() {

[profile.dev]
opt-level = 1

[profile.test]
cxxflags = ["-fno-rtti"]
)"_toml;

const Profile devExpected(
Expand All @@ -891,11 +931,17 @@ testParseProfiles() {
/*debug=*/false,
/*compDb=*/false, /*optLevel=*/2 // here, the default is 3
);
const Profile testExpected(
/*cxxflags=*/{ "-fno-rtti" }, /*ldflags=*/{}, /*lto=*/false,
/*debug=*/true,
/*compDb=*/false, /*optLevel=*/1
);

const auto profiles = parseProfiles(overwrite).unwrap();
assertEq(profiles.size(), 2UL);
assertEq(profiles.size(), 3UL);
assertEq(profiles.at(BuildProfile::Dev), devExpected);
assertEq(profiles.at(BuildProfile::Release), relExpected);
assertEq(profiles.at(BuildProfile::Test), testExpected);
}
}

Expand Down
Loading