This commit is contained in:
parent
659103a123
commit
03717b5f33
9 changed files with 230 additions and 14 deletions
11
build.cmd
11
build.cmd
|
|
@ -17,6 +17,7 @@ copy /Y interfaces\Crafter.Build-External.cppm share\crafter-build\
|
||||||
copy /Y interfaces\Crafter.Build-Clang.cppm share\crafter-build\
|
copy /Y interfaces\Crafter.Build-Clang.cppm share\crafter-build\
|
||||||
copy /Y interfaces\Crafter.Build-Test.cppm share\crafter-build\
|
copy /Y interfaces\Crafter.Build-Test.cppm share\crafter-build\
|
||||||
copy /Y interfaces\Crafter.Build-Progress.cppm share\crafter-build\
|
copy /Y interfaces\Crafter.Build-Progress.cppm share\crafter-build\
|
||||||
|
copy /Y interfaces\Crafter.Build-Asset.cppm share\crafter-build\
|
||||||
copy /Y interfaces\Crafter.Build-Api.h share\crafter-build\
|
copy /Y interfaces\Crafter.Build-Api.h share\crafter-build\
|
||||||
|
|
||||||
if not exist .\build\glslang\NUL git clone https://github.com/KhronosGroup/glslang.git .\build\glslang
|
if not exist .\build\glslang\NUL git clone https://github.com/KhronosGroup/glslang.git .\build\glslang
|
||||||
|
|
@ -55,6 +56,9 @@ clang++ %common_options% -fmodule-output interfaces\Crafter.Build-External.cppm
|
||||||
clang++ %common_options% -fmodule-output interfaces\Crafter.Build-Clang.cppm -o .\build\Crafter.Build-Clang.o
|
clang++ %common_options% -fmodule-output interfaces\Crafter.Build-Clang.cppm -o .\build\Crafter.Build-Clang.o
|
||||||
clang++ %common_options% -fmodule-output interfaces\Crafter.Build-Test.cppm -o .\build\Crafter.Build-Test.o
|
clang++ %common_options% -fmodule-output interfaces\Crafter.Build-Test.cppm -o .\build\Crafter.Build-Test.o
|
||||||
clang++ %common_options% -fmodule-output interfaces\Crafter.Build-Progress.cppm -o .\build\Crafter.Build-Progress.o
|
clang++ %common_options% -fmodule-output interfaces\Crafter.Build-Progress.cppm -o .\build\Crafter.Build-Progress.o
|
||||||
|
REM Asset partition: bootstrap compiles it WITHOUT CRAFTER_BUILD_HAS_ASSET so
|
||||||
|
REM CompressAsset takes the stub branch (no Crafter.Asset PCM exists yet).
|
||||||
|
clang++ %common_options% -fmodule-output interfaces\Crafter.Build-Asset.cppm -o .\build\Crafter.Build-Asset.o
|
||||||
clang++ %common_options% -fmodule-output interfaces\Crafter.Build.cppm -o .\build\Crafter.Build.o
|
clang++ %common_options% -fmodule-output interfaces\Crafter.Build.cppm -o .\build\Crafter.Build.o
|
||||||
|
|
||||||
clang++ %common_options% .\implementations\Crafter.Build-Shader.cpp -o .\build\Crafter.Build-Shader_impl.o
|
clang++ %common_options% .\implementations\Crafter.Build-Shader.cpp -o .\build\Crafter.Build-Shader_impl.o
|
||||||
|
|
@ -65,6 +69,7 @@ clang++ %common_options% .\implementations\Crafter.Build-External.cpp -o .\build
|
||||||
clang++ %common_options% .\implementations\Crafter.Build-Clang.cpp -o .\build\Crafter.Build-Clang_impl.o
|
clang++ %common_options% .\implementations\Crafter.Build-Clang.cpp -o .\build\Crafter.Build-Clang_impl.o
|
||||||
clang++ %common_options% .\implementations\Crafter.Build-Test.cpp -o .\build\Crafter.Build-Test_impl.o
|
clang++ %common_options% .\implementations\Crafter.Build-Test.cpp -o .\build\Crafter.Build-Test_impl.o
|
||||||
clang++ %common_options% .\implementations\Crafter.Build-Progress.cpp -o .\build\Crafter.Build-Progress_impl.o
|
clang++ %common_options% .\implementations\Crafter.Build-Progress.cpp -o .\build\Crafter.Build-Progress_impl.o
|
||||||
|
clang++ %common_options% .\implementations\Crafter.Build-Asset.cpp -o .\build\Crafter.Build-Asset_impl.o
|
||||||
clang++ %common_options% .\implementations\main.cpp -o .\build\main.o
|
clang++ %common_options% .\implementations\main.cpp -o .\build\main.o
|
||||||
|
|
||||||
REM Step 1: link all impl .o files into crafter-build.dll, generating crafter-build.lib import lib
|
REM Step 1: link all impl .o files into crafter-build.dll, generating crafter-build.lib import lib
|
||||||
|
|
@ -79,6 +84,7 @@ clang++ %useLibcLinker% -shared -std=c++26 -O3 -march=%CRAFTER_BUILD_MARCH% -mtu
|
||||||
.\build\Crafter.Build-Clang.o ^
|
.\build\Crafter.Build-Clang.o ^
|
||||||
.\build\Crafter.Build-Test.o ^
|
.\build\Crafter.Build-Test.o ^
|
||||||
.\build\Crafter.Build-Progress.o ^
|
.\build\Crafter.Build-Progress.o ^
|
||||||
|
.\build\Crafter.Build-Asset.o ^
|
||||||
.\build\Crafter.Build.o ^
|
.\build\Crafter.Build.o ^
|
||||||
.\build\Crafter.Build-Shader_impl.o ^
|
.\build\Crafter.Build-Shader_impl.o ^
|
||||||
.\build\Crafter.Build-Platform_impl.o ^
|
.\build\Crafter.Build-Platform_impl.o ^
|
||||||
|
|
@ -88,6 +94,7 @@ clang++ %useLibcLinker% -shared -std=c++26 -O3 -march=%CRAFTER_BUILD_MARCH% -mtu
|
||||||
.\build\Crafter.Build-Clang_impl.o ^
|
.\build\Crafter.Build-Clang_impl.o ^
|
||||||
.\build\Crafter.Build-Test_impl.o ^
|
.\build\Crafter.Build-Test_impl.o ^
|
||||||
.\build\Crafter.Build-Progress_impl.o ^
|
.\build\Crafter.Build-Progress_impl.o ^
|
||||||
|
.\build\Crafter.Build-Asset_impl.o ^
|
||||||
-o .\bin\crafter-build.dll
|
-o .\bin\crafter-build.dll
|
||||||
|
|
||||||
REM Step 2: link the launcher exe against crafter-build.lib
|
REM Step 2: link the launcher exe against crafter-build.lib
|
||||||
|
|
@ -106,6 +113,7 @@ llvm-lib.exe /OUT:.\lib\crafter-build-static.lib ^
|
||||||
.\build\Crafter.Build-Clang.o ^
|
.\build\Crafter.Build-Clang.o ^
|
||||||
.\build\Crafter.Build-Test.o ^
|
.\build\Crafter.Build-Test.o ^
|
||||||
.\build\Crafter.Build-Progress.o ^
|
.\build\Crafter.Build-Progress.o ^
|
||||||
|
.\build\Crafter.Build-Asset.o ^
|
||||||
.\build\Crafter.Build.o ^
|
.\build\Crafter.Build.o ^
|
||||||
.\build\Crafter.Build-Shader_impl.o ^
|
.\build\Crafter.Build-Shader_impl.o ^
|
||||||
.\build\Crafter.Build-Platform_impl.o ^
|
.\build\Crafter.Build-Platform_impl.o ^
|
||||||
|
|
@ -114,6 +122,7 @@ llvm-lib.exe /OUT:.\lib\crafter-build-static.lib ^
|
||||||
.\build\Crafter.Build-External_impl.o ^
|
.\build\Crafter.Build-External_impl.o ^
|
||||||
.\build\Crafter.Build-Clang_impl.o ^
|
.\build\Crafter.Build-Clang_impl.o ^
|
||||||
.\build\Crafter.Build-Test_impl.o ^
|
.\build\Crafter.Build-Test_impl.o ^
|
||||||
.\build\Crafter.Build-Progress_impl.o
|
.\build\Crafter.Build-Progress_impl.o ^
|
||||||
|
.\build\Crafter.Build-Asset_impl.o
|
||||||
|
|
||||||
copy /Y "%LIBCXX_DIR%\lib\c++.dll" ".\bin\c++.dll"
|
copy /Y "%LIBCXX_DIR%\lib\c++.dll" ".\bin\c++.dll"
|
||||||
|
|
|
||||||
13
build.sh
13
build.sh
|
|
@ -16,6 +16,7 @@ cp interfaces/Crafter.Build-External.cppm share/crafter-build/
|
||||||
cp interfaces/Crafter.Build-Clang.cppm share/crafter-build/
|
cp interfaces/Crafter.Build-Clang.cppm share/crafter-build/
|
||||||
cp interfaces/Crafter.Build-Test.cppm share/crafter-build/
|
cp interfaces/Crafter.Build-Test.cppm share/crafter-build/
|
||||||
cp interfaces/Crafter.Build-Progress.cppm share/crafter-build/
|
cp interfaces/Crafter.Build-Progress.cppm share/crafter-build/
|
||||||
|
cp interfaces/Crafter.Build-Asset.cppm share/crafter-build/
|
||||||
cp interfaces/Crafter.Build-Api.h share/crafter-build/
|
cp interfaces/Crafter.Build-Api.h share/crafter-build/
|
||||||
|
|
||||||
git clone https://github.com/KhronosGroup/glslang.git ./build/glslang
|
git clone https://github.com/KhronosGroup/glslang.git ./build/glslang
|
||||||
|
|
@ -52,6 +53,11 @@ clang++ $common_options -fmodule-output interfaces/Crafter.Build-External.cppm -
|
||||||
clang++ $common_options -fmodule-output interfaces/Crafter.Build-Clang.cppm -o ./build/Crafter.Build-Clang.o
|
clang++ $common_options -fmodule-output interfaces/Crafter.Build-Clang.cppm -o ./build/Crafter.Build-Clang.o
|
||||||
clang++ $common_options -fmodule-output interfaces/Crafter.Build-Test.cppm -o ./build/Crafter.Build-Test.o
|
clang++ $common_options -fmodule-output interfaces/Crafter.Build-Test.cppm -o ./build/Crafter.Build-Test.o
|
||||||
clang++ $common_options -fmodule-output interfaces/Crafter.Build-Progress.cppm -o ./build/Crafter.Build-Progress.o
|
clang++ $common_options -fmodule-output interfaces/Crafter.Build-Progress.cppm -o ./build/Crafter.Build-Progress.o
|
||||||
|
# Asset partition: bootstrap compiles it WITHOUT CRAFTER_BUILD_HAS_ASSET so
|
||||||
|
# CompressAsset takes the stub branch and the impl unit doesn't try to
|
||||||
|
# `import Crafter.Asset` (no Crafter.Asset PCM exists at this stage — the
|
||||||
|
# self-host pass that follows wires in the real dep).
|
||||||
|
clang++ $common_options -fmodule-output interfaces/Crafter.Build-Asset.cppm -o ./build/Crafter.Build-Asset.o
|
||||||
clang++ $common_options -fmodule-output interfaces/Crafter.Build.cppm -o ./build/Crafter.Build.o
|
clang++ $common_options -fmodule-output interfaces/Crafter.Build.cppm -o ./build/Crafter.Build.o
|
||||||
|
|
||||||
clang++ $common_options ./implementations/Crafter.Build-Shader.cpp -o ./build/Crafter.Build-Shader_impl.o
|
clang++ $common_options ./implementations/Crafter.Build-Shader.cpp -o ./build/Crafter.Build-Shader_impl.o
|
||||||
|
|
@ -62,6 +68,7 @@ clang++ $common_options ./implementations/Crafter.Build-External.cpp -o ./build/
|
||||||
clang++ $common_options ./implementations/Crafter.Build-Clang.cpp -o ./build/Crafter.Build-Clang_impl.o
|
clang++ $common_options ./implementations/Crafter.Build-Clang.cpp -o ./build/Crafter.Build-Clang_impl.o
|
||||||
clang++ $common_options ./implementations/Crafter.Build-Test.cpp -o ./build/Crafter.Build-Test_impl.o
|
clang++ $common_options ./implementations/Crafter.Build-Test.cpp -o ./build/Crafter.Build-Test_impl.o
|
||||||
clang++ $common_options ./implementations/Crafter.Build-Progress.cpp -o ./build/Crafter.Build-Progress_impl.o
|
clang++ $common_options ./implementations/Crafter.Build-Progress.cpp -o ./build/Crafter.Build-Progress_impl.o
|
||||||
|
clang++ $common_options ./implementations/Crafter.Build-Asset.cpp -o ./build/Crafter.Build-Asset_impl.o
|
||||||
clang++ $common_options ./implementations/main.cpp -o ./build/main.o
|
clang++ $common_options ./implementations/main.cpp -o ./build/main.o
|
||||||
|
|
||||||
ar rcs ./lib/libcrafter-build.a \
|
ar rcs ./lib/libcrafter-build.a \
|
||||||
|
|
@ -73,6 +80,7 @@ ar rcs ./lib/libcrafter-build.a \
|
||||||
./build/Crafter.Build-Clang.o \
|
./build/Crafter.Build-Clang.o \
|
||||||
./build/Crafter.Build-Test.o \
|
./build/Crafter.Build-Test.o \
|
||||||
./build/Crafter.Build-Progress.o \
|
./build/Crafter.Build-Progress.o \
|
||||||
|
./build/Crafter.Build-Asset.o \
|
||||||
./build/Crafter.Build.o \
|
./build/Crafter.Build.o \
|
||||||
./build/Crafter.Build-Shader_impl.o \
|
./build/Crafter.Build-Shader_impl.o \
|
||||||
./build/Crafter.Build-Platform_impl.o \
|
./build/Crafter.Build-Platform_impl.o \
|
||||||
|
|
@ -81,7 +89,8 @@ ar rcs ./lib/libcrafter-build.a \
|
||||||
./build/Crafter.Build-External_impl.o \
|
./build/Crafter.Build-External_impl.o \
|
||||||
./build/Crafter.Build-Clang_impl.o \
|
./build/Crafter.Build-Clang_impl.o \
|
||||||
./build/Crafter.Build-Test_impl.o \
|
./build/Crafter.Build-Test_impl.o \
|
||||||
./build/Crafter.Build-Progress_impl.o
|
./build/Crafter.Build-Progress_impl.o \
|
||||||
|
./build/Crafter.Build-Asset_impl.o
|
||||||
|
|
||||||
clang++ -std=c++26 -stdlib=libc++ -O3 -march=$MARCH -mtune=$MTUNE -fuse-ld=lld \
|
clang++ -std=c++26 -stdlib=libc++ -O3 -march=$MARCH -mtune=$MTUNE -fuse-ld=lld \
|
||||||
-Wl,--export-dynamic \
|
-Wl,--export-dynamic \
|
||||||
|
|
@ -94,6 +103,7 @@ clang++ -std=c++26 -stdlib=libc++ -O3 -march=$MARCH -mtune=$MTUNE -fuse-ld=lld \
|
||||||
./build/Crafter.Build-Clang.o \
|
./build/Crafter.Build-Clang.o \
|
||||||
./build/Crafter.Build-Test.o \
|
./build/Crafter.Build-Test.o \
|
||||||
./build/Crafter.Build-Progress.o \
|
./build/Crafter.Build-Progress.o \
|
||||||
|
./build/Crafter.Build-Asset.o \
|
||||||
./build/Crafter.Build.o \
|
./build/Crafter.Build.o \
|
||||||
./build/Crafter.Build-Shader_impl.o \
|
./build/Crafter.Build-Shader_impl.o \
|
||||||
./build/Crafter.Build-Platform_impl.o \
|
./build/Crafter.Build-Platform_impl.o \
|
||||||
|
|
@ -103,6 +113,7 @@ clang++ -std=c++26 -stdlib=libc++ -O3 -march=$MARCH -mtune=$MTUNE -fuse-ld=lld \
|
||||||
./build/Crafter.Build-Clang_impl.o \
|
./build/Crafter.Build-Clang_impl.o \
|
||||||
./build/Crafter.Build-Test_impl.o \
|
./build/Crafter.Build-Test_impl.o \
|
||||||
./build/Crafter.Build-Progress_impl.o \
|
./build/Crafter.Build-Progress_impl.o \
|
||||||
|
./build/Crafter.Build-Asset_impl.o \
|
||||||
./build/main.o \
|
./build/main.o \
|
||||||
-lSPIRV -lGenericCodeGen -lglslang -lOSDependent -lMachineIndependent -lglslang-default-resource-limits \
|
-lSPIRV -lGenericCodeGen -lglslang -lOSDependent -lMachineIndependent -lglslang-default-resource-limits \
|
||||||
-ldl \
|
-ldl \
|
||||||
|
|
|
||||||
55
implementations/Crafter.Build-Asset.cpp
Normal file
55
implementations/Crafter.Build-Asset.cpp
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
Crafter® Build
|
||||||
|
Copyright (C) 2026 Catcrafts®
|
||||||
|
Catcrafts.net
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License version 3.0 as published by the Free Software Foundation;
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
module Crafter.Build:Asset_impl;
|
||||||
|
import :Asset;
|
||||||
|
import std;
|
||||||
|
#ifdef CRAFTER_BUILD_HAS_ASSET
|
||||||
|
import Crafter.Asset;
|
||||||
|
import Crafter.Math;
|
||||||
|
#endif
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
namespace Crafter {
|
||||||
|
std::string CompressAsset(const fs::path& input, const fs::path& output) {
|
||||||
|
std::string ext = input.extension().string();
|
||||||
|
#ifdef CRAFTER_BUILD_HAS_ASSET
|
||||||
|
try {
|
||||||
|
if (ext == ".png") {
|
||||||
|
auto tex = TextureAsset<Vector<std::uint8_t, 4, 4>>::LoadPNG<std::uint8_t>(input);
|
||||||
|
tex.SaveCompressed(output);
|
||||||
|
} else if (ext == ".obj") {
|
||||||
|
auto mesh = MeshAsset<VertexNormalTangentUVPacked>::LoadOBJ(input);
|
||||||
|
mesh.SaveCompressed(output);
|
||||||
|
} else {
|
||||||
|
return std::format("{}: unsupported asset extension '{}'", input.string(), ext);
|
||||||
|
}
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
return std::format("{}: {}", input.string(), e.what());
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
#else
|
||||||
|
return std::format(
|
||||||
|
"{}: crafter-build was bootstrapped without Crafter.Asset linkage; "
|
||||||
|
"rebuild via `./bin/crafter-build` so the self-host pass picks up the "
|
||||||
|
"Crafter.Asset dep declared in project.cpp",
|
||||||
|
input.string());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -23,6 +23,7 @@ import :Clang;
|
||||||
import :Platform;
|
import :Platform;
|
||||||
import :Test;
|
import :Test;
|
||||||
import :Progress;
|
import :Progress;
|
||||||
|
import :Asset;
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
using namespace Crafter;
|
using namespace Crafter;
|
||||||
|
|
||||||
|
|
@ -291,6 +292,38 @@ BuildResult Crafter::Build(Configuration& config, std::unordered_map<fs::path, s
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Asset compilation: each .png/.obj listed in cfg.assets is run through
|
||||||
|
// Crafter.Asset's library (linked into crafter-build directly — see
|
||||||
|
// :Asset_impl) to produce the SaveCompressed .ctex/.cmesh in outputDir.
|
||||||
|
// Skipped if the output is newer than the source. Parallel with shaders
|
||||||
|
// and module compiles; cancellation participates in the same flag.
|
||||||
|
auto assetOutput = [](const fs::path& asset) -> std::optional<fs::path> {
|
||||||
|
std::string ext = asset.extension().string();
|
||||||
|
if (ext == ".png") return fs::path(asset.filename()).replace_extension(".ctex");
|
||||||
|
if (ext == ".obj") return fs::path(asset.filename()).replace_extension(".cmesh");
|
||||||
|
return std::nullopt;
|
||||||
|
};
|
||||||
|
for (const fs::path& asset : config.assets) {
|
||||||
|
std::optional<fs::path> outName = assetOutput(asset);
|
||||||
|
if (!outName) {
|
||||||
|
buildCancelled.store(true);
|
||||||
|
buildError = std::format("{}: unsupported asset extension (expected .png or .obj)", asset.string());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fs::path out = outputDir / *outName;
|
||||||
|
if (fs::exists(out) && fs::exists(asset) && fs::last_write_time(asset) <= fs::last_write_time(out)) continue;
|
||||||
|
threads.emplace_back([&asset, out = std::move(out), &buildError, &buildCancelled]() {
|
||||||
|
Progress::Task task(std::format("Compressing asset {}", asset.filename().string()));
|
||||||
|
if (buildCancelled.load(std::memory_order_relaxed)) return;
|
||||||
|
std::string result = CompressAsset(asset, out);
|
||||||
|
if (result.empty()) return;
|
||||||
|
bool expected = false;
|
||||||
|
if (buildCancelled.compare_exchange_strong(expected, true)) {
|
||||||
|
buildError = std::move(result);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
threads.emplace_back([&config, &outputDir, &buildCancelled, &buildError]() {
|
threads.emplace_back([&config, &outputDir, &buildCancelled, &buildError]() {
|
||||||
Progress::Task task(std::format("Copying files for {}", config.name));
|
Progress::Task task(std::format("Copying files for {}", config.name));
|
||||||
if (buildCancelled.load(std::memory_order_relaxed)) return;
|
if (buildCancelled.load(std::memory_order_relaxed)) return;
|
||||||
|
|
@ -432,16 +465,20 @@ BuildResult Crafter::Build(Configuration& config, std::unordered_map<fs::path, s
|
||||||
depThreads.reserve(config.dependencies.size());
|
depThreads.reserve(config.dependencies.size());
|
||||||
std::atomic<bool> repack(false);
|
std::atomic<bool> repack(false);
|
||||||
|
|
||||||
|
// -I propagation that's valid for both C and C++ compiles. Module-only
|
||||||
|
// bits (-fprebuilt-module-path) stay on `command` only.
|
||||||
|
std::string includeFlags;
|
||||||
{
|
{
|
||||||
std::unordered_set<Configuration*> seen;
|
std::unordered_set<Configuration*> seen;
|
||||||
std::function<void(Configuration*)> addFlags = [&](Configuration* dep) {
|
std::function<void(Configuration*)> addFlags = [&](Configuration* dep) {
|
||||||
if (!seen.insert(dep).second) return;
|
if (!seen.insert(dep).second) return;
|
||||||
for (const auto& entry : fs::recursive_directory_iterator(dep->path)) {
|
for (const auto& entry : fs::recursive_directory_iterator(dep->path)) {
|
||||||
if (entry.is_directory() && entry.path().filename() == "include") {
|
if (entry.is_directory() && entry.path().filename() == "include") {
|
||||||
command += " -I" + entry.path().string();
|
includeFlags += " -I" + entry.path().string();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
command += std::format(" -I{} -fprebuilt-module-path={}", dep->path.string(), dep->PcmDir().string());
|
includeFlags += std::format(" -I{}", dep->path.string());
|
||||||
|
command += std::format(" -fprebuilt-module-path={}", dep->PcmDir().string());
|
||||||
for (Configuration* sub : dep->dependencies) {
|
for (Configuration* sub : dep->dependencies) {
|
||||||
addFlags(sub);
|
addFlags(sub);
|
||||||
}
|
}
|
||||||
|
|
@ -450,6 +487,7 @@ BuildResult Crafter::Build(Configuration& config, std::unordered_map<fs::path, s
|
||||||
addFlags(dep);
|
addFlags(dep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
command += includeFlags;
|
||||||
|
|
||||||
for(Configuration* dep : config.dependencies) {
|
for(Configuration* dep : config.dependencies) {
|
||||||
depThreads.emplace_back([&, dep](){
|
depThreads.emplace_back([&, dep](){
|
||||||
|
|
@ -507,17 +545,25 @@ BuildResult Crafter::Build(Configuration& config, std::unordered_map<fs::path, s
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Defines belong on both C and C++ compiles so vendored C dependencies
|
||||||
|
// can see configuration-level macros consistently with module sources.
|
||||||
|
std::string defineFlags;
|
||||||
for(const Define& define : config.defines) {
|
for(const Define& define : config.defines) {
|
||||||
if(define.value.empty()) {
|
if(define.value.empty()) {
|
||||||
command += std::format(" -D {}", define.name);
|
defineFlags += std::format(" -D {}", define.name);
|
||||||
} else {
|
} else {
|
||||||
command += std::format(" -D {}={}", define.name, define.value);
|
defineFlags += std::format(" -D {}={}", define.name, define.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
command += defineFlags;
|
||||||
|
|
||||||
|
// Track caller-provided compileFlags separately so the .c compile can
|
||||||
|
// pick them up too (vendored C deps usually need -I from this set).
|
||||||
|
std::string userFlags;
|
||||||
for(const std::string& flag : config.compileFlags) {
|
for(const std::string& flag : config.compileFlags) {
|
||||||
command += " " + flag;
|
userFlags += " " + flag;
|
||||||
}
|
}
|
||||||
|
command += userFlags;
|
||||||
|
|
||||||
std::string cmakeBuildType;
|
std::string cmakeBuildType;
|
||||||
|
|
||||||
|
|
@ -534,11 +580,11 @@ BuildResult Crafter::Build(Configuration& config, std::unordered_map<fs::path, s
|
||||||
const std::string objPath = (buildDir / cFile.filename()).string() + "_source.o";
|
const std::string objPath = (buildDir / cFile.filename()).string() + "_source.o";
|
||||||
const std::string srcPath = cFile.string() + ".c";
|
const std::string srcPath = cFile.string() + ".c";
|
||||||
if (!fs::exists(objPath) || (fs::exists(srcPath) && fs::last_write_time(srcPath) > fs::last_write_time(objPath))) {
|
if (!fs::exists(objPath) || (fs::exists(srcPath) && fs::last_write_time(srcPath) > fs::last_write_time(objPath))) {
|
||||||
threads.emplace_back([&cFile, &buildDir, &buildError, &buildCancelled, &config]() {
|
threads.emplace_back([&cFile, &buildDir, &buildError, &buildCancelled, &config, &includeFlags, &defineFlags, &userFlags]() {
|
||||||
Progress::Task task(std::format("Compiling {}.c", cFile.filename().string()));
|
Progress::Task task(std::format("Compiling {}.c", cFile.filename().string()));
|
||||||
if (buildCancelled.load(std::memory_order_relaxed)) return;
|
if (buildCancelled.load(std::memory_order_relaxed)) return;
|
||||||
|
|
||||||
std::string result = RunCommand(std::format("clang {}.c --target={} -march={} -mtune={} -O3 -c -o {}_source.o", cFile.string(), config.target, config.march, config.mtune, (buildDir / cFile.filename()).string()));
|
std::string result = RunCommand(std::format("clang {}.c --target={} -march={} -mtune={} -O3 -c{}{}{} -o {}_source.o", cFile.string(), config.target, config.march, config.mtune, includeFlags, defineFlags, userFlags, (buildDir / cFile.filename()).string()));
|
||||||
if (result.empty()) return;
|
if (result.empty()) return;
|
||||||
|
|
||||||
bool expected = false;
|
bool expected = false;
|
||||||
|
|
@ -632,6 +678,16 @@ BuildResult Crafter::Build(Configuration& config, std::unordered_map<fs::path, s
|
||||||
if (!fs::exists(src)) continue;
|
if (!fs::exists(src)) continue;
|
||||||
copyTree(src, outputDir / additionalFile.filename());
|
copyTree(src, outputDir / additionalFile.filename());
|
||||||
}
|
}
|
||||||
|
for (const fs::path& asset : dep->assets) {
|
||||||
|
std::string ext = asset.extension().string();
|
||||||
|
fs::path srcName = asset.filename();
|
||||||
|
if (ext == ".png") srcName.replace_extension(".ctex");
|
||||||
|
else if (ext == ".obj") srcName.replace_extension(".cmesh");
|
||||||
|
else continue;
|
||||||
|
fs::path src = depBinDir / srcName;
|
||||||
|
if (!fs::exists(src)) continue;
|
||||||
|
copyTree(src, outputDir / srcName);
|
||||||
|
}
|
||||||
for (Configuration* sub : dep->dependencies) forwardDepArtifacts(sub);
|
for (Configuration* sub : dep->dependencies) forwardDepArtifacts(sub);
|
||||||
};
|
};
|
||||||
for (Configuration* dep : config.dependencies) forwardDepArtifacts(dep);
|
for (Configuration* dep : config.dependencies) forwardDepArtifacts(dep);
|
||||||
|
|
|
||||||
|
|
@ -227,7 +227,7 @@ fs::path Crafter::GetCacheDir() {
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
constexpr std::array<std::string_view, 9> kCrafterBuildModules = {
|
constexpr std::array<std::string_view, 10> kCrafterBuildModules = {
|
||||||
"Crafter.Build-Shader",
|
"Crafter.Build-Shader",
|
||||||
"Crafter.Build-Platform",
|
"Crafter.Build-Platform",
|
||||||
"Crafter.Build-Interface",
|
"Crafter.Build-Interface",
|
||||||
|
|
@ -236,6 +236,7 @@ namespace {
|
||||||
"Crafter.Build-Clang",
|
"Crafter.Build-Clang",
|
||||||
"Crafter.Build-Test",
|
"Crafter.Build-Test",
|
||||||
"Crafter.Build-Progress",
|
"Crafter.Build-Progress",
|
||||||
|
"Crafter.Build-Asset",
|
||||||
"Crafter.Build",
|
"Crafter.Build",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -737,7 +738,7 @@ std::string Crafter::GetBaseCommand(const Configuration& config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
constexpr std::array<std::string_view, 9> kCrafterBuildModules = {
|
constexpr std::array<std::string_view, 10> kCrafterBuildModules = {
|
||||||
"Crafter.Build-Shader",
|
"Crafter.Build-Shader",
|
||||||
"Crafter.Build-Platform",
|
"Crafter.Build-Platform",
|
||||||
"Crafter.Build-Interface",
|
"Crafter.Build-Interface",
|
||||||
|
|
@ -746,6 +747,7 @@ namespace {
|
||||||
"Crafter.Build-Clang",
|
"Crafter.Build-Clang",
|
||||||
"Crafter.Build-Test",
|
"Crafter.Build-Test",
|
||||||
"Crafter.Build-Progress",
|
"Crafter.Build-Progress",
|
||||||
|
"Crafter.Build-Asset",
|
||||||
"Crafter.Build",
|
"Crafter.Build",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
39
interfaces/Crafter.Build-Asset.cppm
Normal file
39
interfaces/Crafter.Build-Asset.cppm
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
Crafter® Build
|
||||||
|
Copyright (C) 2026 Catcrafts®
|
||||||
|
Catcrafts.net
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License version 3.0 as published by the Free Software Foundation;
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
module;
|
||||||
|
#include "Crafter.Build-Api.h"
|
||||||
|
export module Crafter.Build:Asset;
|
||||||
|
import std;
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
namespace Crafter {
|
||||||
|
// Compress a build-time asset (.png/.obj) into its on-disk
|
||||||
|
// SaveCompressed counterpart (.ctex/.cmesh) using Crafter.Asset's
|
||||||
|
// library API in-process. Returns "" on success, an error message
|
||||||
|
// otherwise (matches Shader::Compile's contract).
|
||||||
|
//
|
||||||
|
// Real implementation lives in the impl unit and only compiles when
|
||||||
|
// CRAFTER_BUILD_HAS_ASSET is defined (i.e. when the build links
|
||||||
|
// Crafter.Asset). The bootstrap build.sh produces a stub variant
|
||||||
|
// that errors out at runtime if cfg.assets is non-empty — full
|
||||||
|
// support requires a self-host rebuild via crafter-build itself,
|
||||||
|
// which resolves the Crafter.Asset dep through project.cpp.
|
||||||
|
export CRAFTER_API std::string CompressAsset(const fs::path& input, const fs::path& output);
|
||||||
|
}
|
||||||
|
|
@ -125,6 +125,15 @@ export namespace Crafter {
|
||||||
std::vector<fs::path> buildFiles;
|
std::vector<fs::path> buildFiles;
|
||||||
std::vector<Define> defines;
|
std::vector<Define> defines;
|
||||||
std::vector<Shader> shaders;
|
std::vector<Shader> shaders;
|
||||||
|
// Source assets (.png, .obj) compressed via Crafter.Asset's
|
||||||
|
// SaveCompressed → .ctex/.cmesh in this configuration's bin dir.
|
||||||
|
// Requires Crafter.Asset in cfg.dependencies (transitively): the
|
||||||
|
// build engine locates it by name and uses its library API to do
|
||||||
|
// the conversion (an auxiliary host-target executable, generated
|
||||||
|
// once per build host, links Crafter.Asset and is invoked per
|
||||||
|
// asset). Forwarded to a consuming executable's bin dir alongside
|
||||||
|
// .spv shaders and cfg.files entries.
|
||||||
|
std::vector<fs::path> assets;
|
||||||
std::vector<ExternalDependency> externalDependencies;
|
std::vector<ExternalDependency> externalDependencies;
|
||||||
std::vector<std::string> compileFlags;
|
std::vector<std::string> compileFlags;
|
||||||
std::vector<std::string> linkFlags;
|
std::vector<std::string> linkFlags;
|
||||||
|
|
|
||||||
|
|
@ -24,4 +24,5 @@ export import :Implementation;
|
||||||
export import :Shader;
|
export import :Shader;
|
||||||
export import :External;
|
export import :External;
|
||||||
export import :Test;
|
export import :Test;
|
||||||
export import :Progress;
|
export import :Progress;
|
||||||
|
export import :Asset;
|
||||||
38
project.cpp
38
project.cpp
|
|
@ -4,6 +4,30 @@ namespace fs = std::filesystem;
|
||||||
using namespace Crafter;
|
using namespace Crafter;
|
||||||
|
|
||||||
extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> args) {
|
extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> args) {
|
||||||
|
std::vector<std::string> depArgs(args.begin(), args.end());
|
||||||
|
|
||||||
|
// Local-mode resolution for the Crafter.Math/Crafter.Asset deps that the
|
||||||
|
// self-host pass links in (so `cfg.assets` calls CompressAsset → Crafter.Asset
|
||||||
|
// in-process). `--local` points at sibling working trees instead of git;
|
||||||
|
// useful during cross-repo development so edits in ../Crafter.Asset are
|
||||||
|
// picked up without commit-and-pull.
|
||||||
|
bool useLocal = false;
|
||||||
|
for (std::string_view a : args) {
|
||||||
|
if (a == "--local") { useLocal = true; break; }
|
||||||
|
}
|
||||||
|
auto resolveDep = [&](std::string_view name, std::string_view gitUrl) -> Configuration* {
|
||||||
|
if (useLocal) {
|
||||||
|
return LocalProject({
|
||||||
|
.projectFile = fs::path("../") / name / "project.cpp",
|
||||||
|
.args = depArgs,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return GitProject({
|
||||||
|
.source = { .url = std::string(gitUrl) },
|
||||||
|
.args = depArgs,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
static auto crafterBuildLib = std::make_unique<Configuration>();
|
static auto crafterBuildLib = std::make_unique<Configuration>();
|
||||||
crafterBuildLib->path = "./";
|
crafterBuildLib->path = "./";
|
||||||
crafterBuildLib->name = "crafter.build-lib";
|
crafterBuildLib->name = "crafter.build-lib";
|
||||||
|
|
@ -15,8 +39,16 @@ extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> a
|
||||||
crafterBuildLib->type = (crafterBuildLib->target == "x86_64-w64-mingw32" || crafterBuildLib->target == "x86_64-pc-windows-msvc")
|
crafterBuildLib->type = (crafterBuildLib->target == "x86_64-w64-mingw32" || crafterBuildLib->target == "x86_64-pc-windows-msvc")
|
||||||
? ConfigurationType::LibraryDynamic
|
? ConfigurationType::LibraryDynamic
|
||||||
: ConfigurationType::LibraryStatic;
|
: ConfigurationType::LibraryStatic;
|
||||||
|
// Self-host pass links Crafter.Asset (and its Crafter.Math dep) into the
|
||||||
|
// crafter-build binary so cfg.assets can call CompressAsset in-process.
|
||||||
|
// The bootstrap (build.sh) defines no such dep — its impl unit takes the
|
||||||
|
// stub branch and cfg.assets errors at runtime until a self-host rebuild.
|
||||||
|
Configuration* math = resolveDep("Crafter.Math", "https://forgejo.catcrafts.net/Catcrafts/Crafter.Math.git");
|
||||||
|
Configuration* asset = resolveDep("Crafter.Asset", "https://forgejo.catcrafts.net/Catcrafts/Crafter.Asset.git");
|
||||||
|
crafterBuildLib->dependencies = { math, asset };
|
||||||
|
crafterBuildLib->defines.push_back({"CRAFTER_BUILD_HAS_ASSET", ""});
|
||||||
{
|
{
|
||||||
std::array<fs::path, 9> interfaces = {
|
std::array<fs::path, 10> interfaces = {
|
||||||
"interfaces/Crafter.Build",
|
"interfaces/Crafter.Build",
|
||||||
"interfaces/Crafter.Build-Shader",
|
"interfaces/Crafter.Build-Shader",
|
||||||
"interfaces/Crafter.Build-Platform",
|
"interfaces/Crafter.Build-Platform",
|
||||||
|
|
@ -26,8 +58,9 @@ extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> a
|
||||||
"interfaces/Crafter.Build-Clang",
|
"interfaces/Crafter.Build-Clang",
|
||||||
"interfaces/Crafter.Build-Test",
|
"interfaces/Crafter.Build-Test",
|
||||||
"interfaces/Crafter.Build-Progress",
|
"interfaces/Crafter.Build-Progress",
|
||||||
|
"interfaces/Crafter.Build-Asset",
|
||||||
};
|
};
|
||||||
std::array<fs::path, 8> implementations = {
|
std::array<fs::path, 9> implementations = {
|
||||||
"implementations/Crafter.Build-Shader",
|
"implementations/Crafter.Build-Shader",
|
||||||
"implementations/Crafter.Build-Platform",
|
"implementations/Crafter.Build-Platform",
|
||||||
"implementations/Crafter.Build-Interface",
|
"implementations/Crafter.Build-Interface",
|
||||||
|
|
@ -36,6 +69,7 @@ extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> a
|
||||||
"implementations/Crafter.Build-Clang",
|
"implementations/Crafter.Build-Clang",
|
||||||
"implementations/Crafter.Build-Test",
|
"implementations/Crafter.Build-Test",
|
||||||
"implementations/Crafter.Build-Progress",
|
"implementations/Crafter.Build-Progress",
|
||||||
|
"implementations/Crafter.Build-Asset",
|
||||||
};
|
};
|
||||||
crafterBuildLib->GetInterfacesAndImplementations(interfaces, implementations);
|
crafterBuildLib->GetInterfacesAndImplementations(interfaces, implementations);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue