Crafter.Build/tests/ShaderDep/ShaderDep.cpp
Jorijn van der Graaf d7a9c85ea6
All checks were successful
CI / build-test-release (push) Successful in 15m14s
fixes
2026-05-02 21:08:51 +02:00

117 lines
4.4 KiB
C++

/*
Crafter® Build
Copyright (C) 2026 Catcrafts®
Catcrafts.net
LGPL-3.0-only.
Verifies that when an executable consumes a library that registers shaders
or asset files, those runtime artifacts ship in the executable's bin dir
alongside the binary — not just in the lib's own bin dir, where the runtime
exe wouldn't find them. Covers a .spv (cfg.shaders), a flat asset
(cfg.files file), and a directory tree (cfg.files dir).
Also verifies cfg.buildFiles' include-path semantic: the consumer's own
shader compile resolves `#include "ui-shared.glsl"` against the lib's
buildFiles in-place from the dep's source tree (no copy), and the file is
NOT mirrored into any build/bin dir.
*/
import std;
import Crafter.Build;
#include "../_shared/TestUtil.h"
namespace fs = std::filesystem;
using namespace TestUtil;
using namespace Crafter;
int main() {
try {
fs::path src = fs::current_path() / "tests" / "ShaderDep" / "inner";
Configuration cfg = LoadFixture("ShaderDep", src);
auto br = BuildOnce(cfg);
if (!br.result.empty()) {
std::println(std::cerr, "build failed:\n{}", br.result);
return 1;
}
fs::path libSpv = cfg.dependencies[0]->BinDir() / "triangle.spv";
fs::path appSpv = cfg.BinDir() / "triangle.spv";
if (!fs::exists(libSpv)) {
std::println(std::cerr, "lib .spv missing at {}", libSpv.string());
return 1;
}
if (!fs::exists(appSpv)) {
std::println(std::cerr, "exe .spv missing at {}", appSpv.string());
return 1;
}
std::ifstream f(appSpv, std::ios::binary);
unsigned char magic[4] = {};
f.read(reinterpret_cast<char*>(magic), 4);
if (magic[0] != 0x03 || magic[1] != 0x02 || magic[2] != 0x23 || magic[3] != 0x07) {
std::println(std::cerr,
"SPIR-V magic mismatch in exe-side copy: got {:#04x} {:#04x} {:#04x} {:#04x}",
magic[0], magic[1], magic[2], magic[3]);
return 1;
}
fs::path appAsset = cfg.BinDir() / "asset.txt";
if (!fs::exists(appAsset)) {
std::println(std::cerr, "exe-side asset.txt missing at {}", appAsset.string());
return 1;
}
if (ReadFile(appAsset) != "crafter-build asset\n") {
std::println(std::cerr, "asset.txt content mismatch at {}", appAsset.string());
return 1;
}
fs::path appNested = cfg.BinDir() / "data" / "nested.txt";
if (!fs::exists(appNested)) {
std::println(std::cerr, "exe-side data/nested.txt missing at {}", appNested.string());
return 1;
}
if (ReadFile(appNested) != "nested asset\n") {
std::println(std::cerr, "data/nested.txt content mismatch at {}", appNested.string());
return 1;
}
// The consumer shader includes a header from the lib's buildFiles.
// Successful build (above) means glslang resolved the include
// in-place from the dep's source tree — verify the resulting .spv
// and the SPIR-V magic, same as for the lib's shader.
fs::path consumerSpv = cfg.BinDir() / "consumer.spv";
if (!fs::exists(consumerSpv)) {
std::println(std::cerr, "consumer .spv missing at {}", consumerSpv.string());
return 1;
}
std::ifstream cf(consumerSpv, std::ios::binary);
unsigned char cmagic[4] = {};
cf.read(reinterpret_cast<char*>(cmagic), 4);
if (cmagic[0] != 0x03 || cmagic[1] != 0x02 || cmagic[2] != 0x23 || cmagic[3] != 0x07) {
std::println(std::cerr,
"SPIR-V magic mismatch in consumer.spv: got {:#04x} {:#04x} {:#04x} {:#04x}",
cmagic[0], cmagic[1], cmagic[2], cmagic[3]);
return 1;
}
// buildFiles must NOT be copied anywhere — they're read in place.
for (fs::path probe : {
cfg.BinDir() / "ui-shared.glsl",
cfg.BuildDir() / "ui-shared.glsl",
cfg.dependencies[0]->BinDir() / "ui-shared.glsl",
cfg.dependencies[0]->BuildDir() / "ui-shared.glsl",
}) {
if (fs::exists(probe)) {
std::println(std::cerr, "ui-shared.glsl unexpectedly copied to {}", probe.string());
return 1;
}
}
return 0;
} catch (const std::exception& e) {
std::println(std::cerr, "test exception: {}", e.what());
return 1;
}
}