Some checks failed
CI / build-test-release (pull_request) Failing after 12m4s
One header per pass, asserting both directions — the objects that include it recompile, the ones that don't are untouched — then running the binary, since "was recompiled" only matters if the program agrees with itself. Covers the module interface (a macro in its global module fragment decides an exported class's layout), the implementation unit, a C source, an idle rebuild that must recompile nothing, and an object whose depfile is gone. The implementation unit's header has a space in its name so the depfile spells it escaped.
141 lines
7.1 KiB
C++
141 lines
7.1 KiB
C++
// SPDX-License-Identifier: LGPL-3.0-only
|
|
// SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
|
|
|
|
import std;
|
|
import Crafter.Build;
|
|
#include "lint-rules.h"
|
|
namespace fs = std::filesystem;
|
|
using namespace Crafter;
|
|
|
|
extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> args) {
|
|
std::vector<std::string> depArgs(args.begin(), args.end());
|
|
Configuration* math = GitProject({
|
|
.source = { "https://forgejo.catcrafts.net/Catcrafts/Crafter.Math.git" },
|
|
.args = depArgs,
|
|
});
|
|
Configuration* asset = GitProject({
|
|
.source = { "https://forgejo.catcrafts.net/Catcrafts/Crafter.Asset.git" },
|
|
.args = depArgs,
|
|
});
|
|
|
|
static auto CrafterBuildLib = std::make_unique<Configuration>();
|
|
CrafterBuildLib->path = "./";
|
|
CrafterBuildLib->name = "crafter.build-lib";
|
|
CrafterBuildLib->outputName = "crafter-build";
|
|
ApplyStandardArgs(*CrafterBuildLib, args);
|
|
// Windows builds (native msvc via build.cmd or cross-compiled mingw from
|
|
// Linux) need a DLL + import lib + launcher exe so LoadProject can
|
|
// compile project.cpp against a stable ABI boundary. Linux is monolithic.
|
|
CrafterBuildLib->type = (CrafterBuildLib->target == "x86_64-w64-mingw32" || CrafterBuildLib->target == "x86_64-pc-windows-msvc")
|
|
? ConfigurationType::LibraryDynamic
|
|
: ConfigurationType::LibraryStatic;
|
|
|
|
CrafterBuildLib->dependencies = { math, asset };
|
|
CrafterBuildLib->defines.push_back({"CRAFTER_BUILD_HAS_ASSET", ""});
|
|
{
|
|
std::array<fs::path, 11> interfaces = {
|
|
"interfaces/Crafter.Build",
|
|
"interfaces/Crafter.Build-Shader",
|
|
"interfaces/Crafter.Build-Platform",
|
|
"interfaces/Crafter.Build-Interface",
|
|
"interfaces/Crafter.Build-Implementation",
|
|
"interfaces/Crafter.Build-External",
|
|
"interfaces/Crafter.Build-Clang",
|
|
"interfaces/Crafter.Build-Test",
|
|
"interfaces/Crafter.Build-Lint",
|
|
"interfaces/Crafter.Build-Progress",
|
|
"interfaces/Crafter.Build-Asset",
|
|
};
|
|
std::array<fs::path, 10> implementations = {
|
|
"implementations/Crafter.Build-Shader",
|
|
"implementations/Crafter.Build-Platform",
|
|
"implementations/Crafter.Build-Interface",
|
|
"implementations/Crafter.Build-Implementation",
|
|
"implementations/Crafter.Build-External",
|
|
"implementations/Crafter.Build-Clang",
|
|
"implementations/Crafter.Build-Test",
|
|
"implementations/Crafter.Build-Lint",
|
|
"implementations/Crafter.Build-Progress",
|
|
"implementations/Crafter.Build-Asset",
|
|
};
|
|
CrafterBuildLib->GetInterfacesAndImplementations(interfaces, implementations);
|
|
}
|
|
ExternalDependency& glslang = CrafterBuildLib->externalDependencies.emplace_back();
|
|
glslang.name = "glslang";
|
|
glslang.source.url = "https://github.com/KhronosGroup/glslang.git";
|
|
glslang.source.branch = "main";
|
|
glslang.builder = ExternalBuilder::CMake;
|
|
glslang.options = { "-DENABLE_OPT=OFF" };
|
|
// mingw cross-build: skip the standalone executable. We only consume the
|
|
// libraries, and glslang.exe pulls in libgcc_eh which needs pthread that
|
|
// mingw-w64 doesn't link by default.
|
|
if (CrafterBuildLib->target == "x86_64-w64-mingw32") {
|
|
glslang.options.push_back("-DENABLE_GLSLANG_BINARIES=OFF");
|
|
}
|
|
glslang.includeDirs = { "" };
|
|
glslang.libs = { "SPIRV", "GenericCodeGen", "glslang", "OSDependent", "MachineIndependent", "glslang-default-resource-limits" };
|
|
|
|
Configuration cfg;
|
|
cfg.path = "./";
|
|
cfg.name = "crafter.build-exe";
|
|
cfg.outputName = "crafter-build";
|
|
ApplyStandardArgs(cfg, args);
|
|
cfg.type = ConfigurationType::Executable;
|
|
cfg.dependencies = { CrafterBuildLib.get() };
|
|
{
|
|
std::array<fs::path, 0> interfaces = {};
|
|
std::array<fs::path, 1> implementations = { "implementations/main" };
|
|
cfg.GetInterfacesAndImplementations(interfaces, implementations);
|
|
}
|
|
if (cfg.target == "x86_64-pc-linux-gnu") {
|
|
cfg.linkFlags.push_back("-Wl,--export-dynamic");
|
|
cfg.linkFlags.push_back("-ldl");
|
|
}
|
|
if (cfg.target == "x86_64-w64-mingw32" || cfg.target == "x86_64-pc-windows-msvc") {
|
|
// winsock for the -r wasm port probe (bind/WSAStartup).
|
|
CrafterBuildLib->linkFlags.push_back("-lws2_32");
|
|
}
|
|
|
|
// Self-tests link the local crafter-build library and exercise it in
|
|
// process. The harness (whichever crafter-build invokes `test`) compiles
|
|
// these against the *installed* share/crafter-build .cppm files, then
|
|
// links each test exe against CrafterBuildLib built from the local
|
|
// sources — so the code under test is whatever's in this checkout.
|
|
// Mirrors how downstream consumers link their own libraries into tests.
|
|
if (cfg.target == "x86_64-pc-linux-gnu") {
|
|
cfg.AddTest("HelloWorld").Dependencies({ CrafterBuildLib.get() });
|
|
cfg.AddTest("StaticLib").Dependencies({ CrafterBuildLib.get() });
|
|
cfg.AddTest("ModuleInterface").Dependencies({ CrafterBuildLib.get() });
|
|
cfg.AddTest("DependencyLink").Dependencies({ CrafterBuildLib.get() });
|
|
cfg.AddTest("IncrementalInterfaceChange").Dependencies({ CrafterBuildLib.get() });
|
|
cfg.AddTest("TransitiveInterfaceChange").Dependencies({ CrafterBuildLib.get() });
|
|
cfg.AddTest("IncrementalHeaderChange").Dependencies({ CrafterBuildLib.get() });
|
|
cfg.AddTest("CleanProject").Dependencies({ CrafterBuildLib.get() });
|
|
cfg.AddTest("ShaderCompile").Dependencies({ CrafterBuildLib.get() });
|
|
cfg.AddTest("StandardArgs").Dependencies({ CrafterBuildLib.get() });
|
|
cfg.AddTest("TestRunnerSpec").Dependencies({ CrafterBuildLib.get() });
|
|
cfg.AddTest("VariantId").Dependencies({ CrafterBuildLib.get() });
|
|
cfg.AddTest("WasiBrowserRuntime").Dependencies({ CrafterBuildLib.get() });
|
|
cfg.AddTest("WasmVariants").Dependencies({ CrafterBuildLib.get() });
|
|
cfg.AddTest("RunSingleTestExit").Dependencies({ CrafterBuildLib.get() });
|
|
// LoadProject dlopens the synthesized project.so, which references
|
|
// Crafter:: symbols (HostTarget, Configuration ctors) that have to be
|
|
// visible from the test exe — same wiring crafter-build itself uses
|
|
// for project.so.
|
|
cfg.AddTest("ConcurrentCacheRace").Dependencies({ CrafterBuildLib.get() })
|
|
.LinkFlag("-Wl,--export-dynamic").LinkFlag("-ldl");
|
|
// Same LoadProject wiring as ConcurrentCacheRace above.
|
|
cfg.AddTest("HostCacheSourceStamp").Dependencies({ CrafterBuildLib.get() })
|
|
.LinkFlag("-Wl,--export-dynamic").LinkFlag("-ldl");
|
|
cfg.AddTest("ConcurrentDependencyReset").Dependencies({ CrafterBuildLib.get() });
|
|
cfg.AddTest("Lint").Dependencies({ CrafterBuildLib.get() });
|
|
cfg.AddTest("HouseRules").Dependencies({ CrafterBuildLib.get() });
|
|
}
|
|
|
|
// Dogfood: this repo's house-style rules (see lint-rules.h). Report
|
|
// rules gate `crafter-build lint`; transform rules also auto-fix under
|
|
// `crafter-build format`.
|
|
ProjectLint::AddProjectLintRules(cfg);
|
|
|
|
return cfg;
|
|
}
|