/* Crafter® Build Copyright (C) 2026 Catcrafts® Catcrafts.net LGPL-3.0-only. End-to-end shader build through the V2 pipeline: the inner project.cpp registers a vertex shader via cfg.shaders, and crafter.build-lib invokes glslang in-process to lower it to SPIR-V. The test verifies the resulting .spv file lands in the per-target bin dir and starts with the SPIR-V magic word — a zero-length output or one written under a different name would be flagged here rather than silently passing. */ 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" / "Shader" / "inner"; Configuration cfg = LoadFixture("Shader", src); fs::path work = fs::current_path(); auto br = BuildOnce(cfg); if (!br.result.empty()) { std::println(std::cerr, "build failed:\n{}", br.result); return 1; } fs::path spv = work / "bin" / "shader-test-x86_64-pc-linux-gnu-native" / "triangle.spv"; if (!fs::exists(spv)) { std::println(std::cerr, "expected SPIR-V output missing at {}", spv.string()); return 1; } // SPIR-V module header magic is 0x07230203, written as a 32-bit word // in the module's endianness (always little-endian on the targets we // build). Matching the raw byte sequence catches truncated writes // and any future regression that produces a non-SPIR-V .spv. std::ifstream f(spv, std::ios::binary); unsigned char magic[4] = {}; f.read(reinterpret_cast(magic), 4); if (magic[0] != 0x03 || magic[1] != 0x02 || magic[2] != 0x23 || magic[3] != 0x07) { std::println(std::cerr, "SPIR-V magic mismatch: got {:#04x} {:#04x} {:#04x} {:#04x}", magic[0], magic[1], magic[2], magic[3]); return 1; } return 0; } catch (const std::exception& e) { std::println(std::cerr, "test exception: {}", e.what()); return 1; } }