Some checks failed
CI / build-test-release (pull_request) Has been cancelled
Linux→mingw cross-compile now produces the same architectural shape as build.cmd (DLL + import lib + launcher exe) instead of a single static binary. The CI Windows artifact becomes a first-class drop-in: a user on Windows can run crafter-build.exe against any project.cpp and have it produce real Windows binaries — for either mingw or MSVC ABI. What changed: project.cpp: when target=mingw or target=msvc, crafter.build-lib is built as LibraryDynamic instead of LibraryStatic so the link emits a DLL + import lib (matching what build.cmd produces natively). Crafter.Build-Clang.cpp Build(): - LibraryDynamic now branches per target — mingw emits <name>.dll + lib<name>.dll.a via lld --out-implib; msvc emits <name>.dll + <name>.lib via /IMPLIB; unix unchanged. - expectedOutputFor returns .dll for Windows-target dynamic libs. - Executable on Windows host now branches per target: mingw target uses simple link (no -lc++/-nostdlib++/LIBCXX_DIR), msvc target keeps the existing path. Both auto-copy LibraryDynamic dep DLLs + import libs alongside the launcher exe (Windows resolves DLLs from the exe's own directory at load time). - Mingw-target Executables get -D CRAFTER_BUILD_DLL_IMPORT so CRAFTER_API resolves to dllimport in their PCMs. - mingw link adds -static-libstdc++ -static-libgcc -Wl,-Bstatic -lpthread so produced .exe/.dll don't depend on a particular libstdc++-6.dll / libwinpthread-1.dll being on the consumer's PATH (avoids the Arch UCRT vs msys2 UCRT vs msys2 MSVCRT ABI rabbit hole). Drops the old auto-copy of /usr/x86_64-w64-mingw32/bin/*.dll which is now dead weight. - -r flag resolves to an absolute path before std::system, otherwise cmd.exe rejects "./bin/..." with "'.' is not recognized...". Crafter.Build-Platform.cpp: - Split the Windows-host block into shared shell helpers (#if MSVC || MINGW) plus separate #if MSVC and #if MINGW blocks for LoadProject / EnsureCrafterBuildPcms / GetBaseCommand / BuildStdPcm. - Mingw-host LoadProject compiles project.cpp with --target=mingw, --sysroot=C:\msys64\ucrt64 (default; override with CRAFTER_MINGW_DIR), -femulated-tls, -Wl,--export-all-symbols (mingw-lld doesn't accept /EXPORT:NAME), and links against libcrafter-build.dll.a from the launcher's directory. - Mingw-host GetBaseCommand and BuildStdPcm dispatch on config.target so a mingw-host crafter-build can also build msvc-target outputs (uses LIBCXX_DIR + libc++ headers, same as native build.cmd) when the user sets cfg.target = "x86_64-pc-windows-msvc". README adds a Quick start (Windows) section covering both build paths (native MSVC via build.cmd and the cross-compiled mingw artifact), documenting the msys2 UCRT toolchain prerequisite. Verified end-to-end on the winvm: - mingw target: cross-compiled crafter-build.exe builds hello-world's project.cpp, compiles main.cpp, links a hello.exe that runs without any custom PATH (only Windows system DLLs needed). - msvc target: same crafter-build.exe builds an MSVC-ABI hello.exe linked against c++.dll (auto-copied from LIBCXX_DIR), runs cleanly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
95 lines
4.2 KiB
C++
95 lines
4.2 KiB
C++
import std;
|
|
import Crafter.Build;
|
|
namespace fs = std::filesystem;
|
|
using namespace Crafter;
|
|
|
|
extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> 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<Configuration>();
|
|
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<fs::path, 8> 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<fs::path, 7> 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<fs::path, 0> interfaces = {};
|
|
std::array<fs::path, 1> 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;
|
|
}
|