import std; import Crafter.Build; namespace fs = std::filesystem; using namespace Crafter; extern "C" Configuration CrafterBuildProject(std::span args) { bool debug = false; std::string target = "x86_64-pc-linux-gnu"; for (std::string_view arg : args) { if (arg == "--debug") debug = true; else if (arg.starts_with("--target=")) target = std::string(arg.substr(std::string_view("--target=").size())); } // Honor CRAFTER_BUILD_MARCH/MTUNE so CI (which sets these for portability) // applies them to both the self-rebuild and the mingw cross-compile — // otherwise Configuration's "native" defaults bake in the build host's // CPU and the published artifact's portability becomes accidental. const char* envMarch = std::getenv("CRAFTER_BUILD_MARCH"); const char* envMtune = std::getenv("CRAFTER_BUILD_MTUNE"); std::string march = (envMarch && *envMarch) ? envMarch : "native"; std::string mtune = (envMtune && *envMtune) ? envMtune : "native"; static auto crafterBuildLib = std::make_unique(); crafterBuildLib->path = "./"; crafterBuildLib->name = "crafter.build-lib"; crafterBuildLib->outputName = "crafter-build"; crafterBuildLib->target = target; crafterBuildLib->march = march; crafterBuildLib->mtune = mtune; // 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 = (target == "x86_64-w64-mingw32" || target == "x86_64-pc-windows-msvc") ? ConfigurationType::LibraryDynamic : ConfigurationType::LibraryStatic; crafterBuildLib->debug = debug; { std::array 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", }; std::array 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", }; 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 (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"; cfg.target = target; cfg.march = march; cfg.mtune = mtune; cfg.type = ConfigurationType::Executable; cfg.debug = debug; cfg.dependencies = { crafterBuildLib.get() }; { std::array interfaces = {}; std::array implementations = { "implementations/main" }; cfg.GetInterfacesAndImplementations(interfaces, implementations); } if (target == "x86_64-pc-linux-gnu") { cfg.linkFlags.push_back("-Wl,--export-dynamic"); cfg.linkFlags.push_back("-ldl"); } return cfg; }