103 lines
4.6 KiB
C++
103 lines
4.6 KiB
C++
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||
|
|
// SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
|
||
|
|
|
||
|
|
import std;
|
||
|
|
import Crafter.Build;
|
||
|
|
// Pinned: the Flatpak builds with the base app's crafter-build, which can be
|
||
|
|
// older than the rules' master. Move the pin together with the base.
|
||
|
|
#pragma crafter dependency "https://forgejo.catcrafts.net/Catcrafts/Crafter.LintRules.git" commit "7d932892017800b4e1f1a15fe7aa49b3daee9ceb"
|
||
|
|
import Crafter.LintRules;
|
||
|
|
namespace fs = std::filesystem;
|
||
|
|
using namespace Crafter;
|
||
|
|
|
||
|
|
namespace {
|
||
|
|
// The umbrella, then the partitions in import order: each after the ones
|
||
|
|
// it imports, which is also the order the module map in AGENTS.md uses.
|
||
|
|
constexpr std::array<std::string_view, 7> Interfaces = {
|
||
|
|
"interfaces/Crafter.Review",
|
||
|
|
"interfaces/Crafter.Review-Unicode",
|
||
|
|
"interfaces/Crafter.Review-Json",
|
||
|
|
"interfaces/Crafter.Review-Text",
|
||
|
|
"interfaces/Crafter.Review-Crypto",
|
||
|
|
"interfaces/Crafter.Review-Core",
|
||
|
|
"interfaces/Crafter.Review-Driver",
|
||
|
|
};
|
||
|
|
constexpr std::array<std::string_view, 4> Implementations = {
|
||
|
|
"implementations/Crafter.Review-Text",
|
||
|
|
"implementations/Crafter.Review-Crypto",
|
||
|
|
"implementations/Crafter.Review-Core",
|
||
|
|
"implementations/Crafter.Review-Driver",
|
||
|
|
};
|
||
|
|
|
||
|
|
// One per directory under tests/, each an ordinary main() that links the
|
||
|
|
// library: exit 0 passes, nonzero fails, 77 skips.
|
||
|
|
constexpr std::array<std::string_view, 2> Tests = {
|
||
|
|
"Crypto",
|
||
|
|
"Text",
|
||
|
|
};
|
||
|
|
|
||
|
|
// The version the binary reports: CI sets it from the tag, a checkout
|
||
|
|
// describes itself, anything else is a development build. A define on
|
||
|
|
// the library, so each version is its own library variant.
|
||
|
|
std::string Version() {
|
||
|
|
if (const char* env = std::getenv("CRAFTER_REVIEW_VERSION"); env && *env) return env;
|
||
|
|
auto described = RunCommandWithTimeout("git describe --tags --always --dirty --exclude=latest 2>/dev/null", std::chrono::seconds(10));
|
||
|
|
std::string version = described.output;
|
||
|
|
while (!version.empty() && (version.back() == '\n' || version.back() == '\r')) version.pop_back();
|
||
|
|
if (described.exitCode != 0 || version.empty()) return "0.0.0-dev";
|
||
|
|
return version;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> args) {
|
||
|
|
// Crafter.Network for its TCP and HTTP/1.1 clients and listener, without
|
||
|
|
// QUIC: msquic is most of a fresh build and nothing here speaks HTTP/3.
|
||
|
|
// From forgejo at a pinned commit, or with --local from the checkout next
|
||
|
|
// to this one (which is also how Crafter.Network then finds
|
||
|
|
// Crafter.Thread).
|
||
|
|
std::vector<std::string> depArgs(args.begin(), args.end());
|
||
|
|
depArgs.emplace_back("--no-quic");
|
||
|
|
const bool useLocal = std::ranges::find(args, std::string_view("--local")) != args.end();
|
||
|
|
Configuration* network = useLocal
|
||
|
|
? LocalProject({ .projectFile = "../Crafter.Network/project.cpp", .args = depArgs })
|
||
|
|
: GitProject({
|
||
|
|
.source = { .url = "https://forgejo.catcrafts.net/Catcrafts/Crafter.Network.git", .commit = "f68321685006be65f6bc0436fd0175611f1e0a55" },
|
||
|
|
.args = depArgs,
|
||
|
|
});
|
||
|
|
|
||
|
|
static auto ReviewLib = std::make_unique<Configuration>();
|
||
|
|
ReviewLib->path = "./";
|
||
|
|
ReviewLib->name = "crafter.review-lib";
|
||
|
|
ReviewLib->outputName = "crafter-review";
|
||
|
|
ApplyStandardArgs(*ReviewLib, args);
|
||
|
|
ReviewLib->type = ConfigurationType::LibraryStatic;
|
||
|
|
ReviewLib->dependencies = { network };
|
||
|
|
// Backslash-escaped quotes: the define travels through the shell before
|
||
|
|
// it reaches clang, which must still see a string literal.
|
||
|
|
ReviewLib->defines.push_back({"CRAFTER_REVIEW_VERSION", std::format("\\\"{}\\\"", Version())});
|
||
|
|
{
|
||
|
|
std::vector<fs::path> interfaces(Interfaces.begin(), Interfaces.end());
|
||
|
|
std::vector<fs::path> implementations(Implementations.begin(), Implementations.end());
|
||
|
|
ReviewLib->GetInterfacesAndImplementations(interfaces, implementations);
|
||
|
|
}
|
||
|
|
|
||
|
|
Configuration cfg;
|
||
|
|
cfg.path = "./";
|
||
|
|
cfg.name = "crafter.review-exe";
|
||
|
|
cfg.outputName = "crafter-review";
|
||
|
|
ApplyStandardArgs(cfg, args);
|
||
|
|
cfg.type = ConfigurationType::Executable;
|
||
|
|
cfg.dependencies = { ReviewLib.get() };
|
||
|
|
{
|
||
|
|
std::array<fs::path, 0> interfaces = {};
|
||
|
|
std::array<fs::path, 1> implementations = { "implementations/main" };
|
||
|
|
cfg.GetInterfacesAndImplementations(interfaces, implementations);
|
||
|
|
}
|
||
|
|
|
||
|
|
for (const std::string_view test : Tests) {
|
||
|
|
cfg.AddTest(test).Dependencies({ ReviewLib.get() });
|
||
|
|
}
|
||
|
|
|
||
|
|
LintRules::AddLiteRules(cfg);
|
||
|
|
return cfg;
|
||
|
|
}
|