shader copy to output
All checks were successful
CI / build-test-release (push) Successful in 15m1s

This commit is contained in:
Jorijn van der Graaf 2026-05-01 19:16:13 +02:00
commit de9865b583
8 changed files with 163 additions and 1 deletions

View file

@ -0,0 +1,58 @@
/*
Crafter® Build
Copyright (C) 2026 Catcrafts®
Catcrafts.net
LGPL-3.0-only.
Verifies that when an executable consumes a library that registers a shader,
the resulting .spv ships 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 it.
*/
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;
}
return 0;
} catch (const std::exception& e) {
std::println(std::cerr, "test exception: {}", e.what());
return 1;
}
}

View file

@ -0,0 +1,3 @@
export module ShaderLib;
export int Identify() { return 0; }

View file

@ -0,0 +1,13 @@
#version 450
layout(location = 0) out vec3 color;
void main() {
vec2 positions[3] = vec2[](
vec2( 0.0, -0.5),
vec2( 0.5, 0.5),
vec2(-0.5, 0.5)
);
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
color = vec3(1.0, 0.0, 0.0);
}

View file

@ -0,0 +1,4 @@
import std;
import ShaderLib;
int main() { return Identify(); }

View file

@ -0,0 +1,33 @@
import std;
import Crafter.Build;
namespace fs = std::filesystem;
using namespace Crafter;
extern "C" Configuration CrafterBuildProject(std::span<const std::string_view>) {
static auto ShaderLib = std::make_unique<Configuration>();
ShaderLib->path = "./lib/";
ShaderLib->name = "ShaderLib";
ShaderLib->outputName = "ShaderLib";
ShaderLib->target = "x86_64-pc-linux-gnu";
ShaderLib->type = ConfigurationType::LibraryStatic;
{
std::array<fs::path, 1> ifaces = { "ShaderLib" };
std::array<fs::path, 0> impls = {};
ShaderLib->GetInterfacesAndImplementations(ifaces, impls);
}
ShaderLib->shaders.emplace_back("./lib/triangle.glsl", "main", ShaderType::Vertex);
Configuration app;
app.path = "./";
app.name = "shader-dep-app";
app.outputName = "shader-dep-app";
app.target = "x86_64-pc-linux-gnu";
app.type = ConfigurationType::Executable;
app.dependencies = { ShaderLib.get() };
{
std::array<fs::path, 0> ifaces = {};
std::array<fs::path, 1> impls = { "main" };
app.GetInterfacesAndImplementations(ifaces, impls);
}
return app;
}

View file

@ -0,0 +1,20 @@
import std;
import Crafter.Build;
namespace fs = std::filesystem;
using namespace Crafter;
extern "C" Configuration CrafterBuildProject(std::span<const std::string_view>) {
Configuration cfg;
cfg.path = "tests/ShaderDep/";
cfg.name = "ShaderDep";
cfg.outputName = "ShaderDep";
cfg.target = "x86_64-pc-linux-gnu";
cfg.type = ConfigurationType::Executable;
cfg.dependencies = { ParentLib("crafter.build-lib") };
cfg.linkFlags.push_back("-Wl,--export-dynamic");
cfg.linkFlags.push_back("-ldl");
std::array<fs::path, 0> ifaces = {};
std::array<fs::path, 1> impls = { "ShaderDep" };
cfg.GetInterfacesAndImplementations(ifaces, impls);
return cfg;
}