update
This commit is contained in:
parent
2daf890ed1
commit
be18fb8568
12 changed files with 427 additions and 19 deletions
2
.github/workflows/release.yaml
vendored
2
.github/workflows/release.yaml
vendored
|
|
@ -11,8 +11,6 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Prepare
|
|
||||||
run: sudo apt install clang lld
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: ./build.sh
|
run: ./build.sh
|
||||||
- name: Release
|
- name: Release
|
||||||
|
|
|
||||||
|
|
@ -20,11 +20,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
module;
|
module;
|
||||||
#include "json.hpp"
|
#include "json.hpp"
|
||||||
|
#include <glslang/Public/ShaderLang.h>
|
||||||
module Crafter.Build;
|
module Crafter.Build;
|
||||||
using namespace Crafter::Build;
|
using namespace Crafter::Build;
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
Configuration::Configuration(std::string name, std::string standard, std::vector<fs::path> sourceFiles, std::vector<fs::path> moduleFiles, std::string optimizationLevel, std::string buildDir, std::string outputDir, std::string type, std::string target, std::string march, std::vector<Dependency> dependencies, std::vector<fs::path> additionalFiles, std::vector<std::string> flags): name(name), standard(standard), sourceFiles(sourceFiles), moduleFiles(moduleFiles), optimizationLevel(optimizationLevel), buildDir(buildDir), outputDir(outputDir), type(type), target(target), march(march), dependencies(dependencies), additionalFiles(additionalFiles), flags(flags) {
|
Configuration::Configuration(std::string name, std::string standard, std::vector<fs::path> sourceFiles, std::vector<fs::path> moduleFiles, std::string optimizationLevel, std::string buildDir, std::string outputDir, std::string type, std::string target, std::string march, std::vector<Dependency> dependencies, std::vector<fs::path> additionalFiles, std::vector<std::string> flags, bool debug, std::vector<std::string> libs, std::vector<std::string> lib_paths, std::vector<fs::path> c_files, std::vector<Shader> shaderFiles, std::vector<std::string> includeDirs, bool verbose): name(name), standard(standard), sourceFiles(sourceFiles), moduleFiles(moduleFiles), optimizationLevel(optimizationLevel), buildDir(buildDir), outputDir(outputDir), type(type), target(target), march(march), dependencies(dependencies), additionalFiles(additionalFiles), flags(flags), debug(debug), libs(libs), lib_paths(lib_paths), c_files(c_files), shaderFiles(shaderFiles), includeDirs(includeDirs), verbose(verbose) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -33,9 +34,13 @@ Configuration::Configuration(const nlohmann::json& configs, const nlohmann::json
|
||||||
for (auto& [key, val] : config.items())
|
for (auto& [key, val] : config.items())
|
||||||
{
|
{
|
||||||
if(key == "standard"){
|
if(key == "standard"){
|
||||||
standard = val.get<std::string>();
|
standard = val.get<std::string>();
|
||||||
} else if(key == "target") {
|
} else if(key == "target") {
|
||||||
target = val.get<std::string>();
|
target = val.get<std::string>();
|
||||||
|
} else if(key == "debug") {
|
||||||
|
debug = val.get<bool>();
|
||||||
|
} else if(key == "verbose") {
|
||||||
|
verbose = val.get<bool>();
|
||||||
} else if(key == "type") {
|
} else if(key == "type") {
|
||||||
type = val.get<std::string>();
|
type = val.get<std::string>();
|
||||||
} else if(key == "march") {
|
} else if(key == "march") {
|
||||||
|
|
@ -48,8 +53,22 @@ Configuration::Configuration(const nlohmann::json& configs, const nlohmann::json
|
||||||
const std::filesystem::path fullFilePath = workingDir / filePath;
|
const std::filesystem::path fullFilePath = workingDir / filePath;
|
||||||
sourceFiles[i] = fullFilePath.generic_string();
|
sourceFiles[i] = fullFilePath.generic_string();
|
||||||
}
|
}
|
||||||
|
} else if(key == "c_files") {
|
||||||
|
const std::vector<std::string> tempSourceFiles = val.get<std::vector<std::string>>();
|
||||||
|
c_files = std::vector<fs::path>(tempSourceFiles.size());
|
||||||
|
for(std::int_fast32_t i = 0; i < c_files.size(); i++){
|
||||||
|
const std::filesystem::path filePath (tempSourceFiles[i]);
|
||||||
|
const std::filesystem::path fullFilePath = workingDir / filePath;
|
||||||
|
c_files[i] = fullFilePath.generic_string();
|
||||||
|
}
|
||||||
} else if(key == "flags") {
|
} else if(key == "flags") {
|
||||||
flags = val.get<std::vector<std::string>>();
|
flags = val.get<std::vector<std::string>>();
|
||||||
|
} else if(key == "lib_paths") {
|
||||||
|
lib_paths = val.get<std::vector<std::string>>();
|
||||||
|
} else if(key == "include_dirs") {
|
||||||
|
includeDirs = val.get<std::vector<std::string>>();
|
||||||
|
} else if(key == "libs") {
|
||||||
|
libs = val.get<std::vector<std::string>>();
|
||||||
} else if(key == "module_files") {
|
} else if(key == "module_files") {
|
||||||
const std::vector<std::string> tempModuleFiles = val.get<std::vector<std::string>>();
|
const std::vector<std::string> tempModuleFiles = val.get<std::vector<std::string>>();
|
||||||
moduleFiles = std::vector<fs::path>(tempModuleFiles.size());
|
moduleFiles = std::vector<fs::path>(tempModuleFiles.size());
|
||||||
|
|
@ -58,6 +77,12 @@ Configuration::Configuration(const nlohmann::json& configs, const nlohmann::json
|
||||||
const std::filesystem::path fullFilePath = workingDir / filePath;
|
const std::filesystem::path fullFilePath = workingDir / filePath;
|
||||||
moduleFiles[i] = fullFilePath.generic_string();
|
moduleFiles[i] = fullFilePath.generic_string();
|
||||||
}
|
}
|
||||||
|
} else if(key == "shaders") {
|
||||||
|
for (auto it : val) {
|
||||||
|
const std::filesystem::path filePath (it["path"].get<std::string>());
|
||||||
|
const std::filesystem::path fullFilePath = workingDir / filePath;
|
||||||
|
shaderFiles.emplace_back(fullFilePath, it["entrypoint"].get<std::string>(), static_cast<EShLanguage>(it["type"].get<std::uint32_t>()));
|
||||||
|
}
|
||||||
} else if(key == "additional_files") {
|
} else if(key == "additional_files") {
|
||||||
const std::vector<std::string> tempAdditionalFiles = val.get<std::vector<std::string>>();
|
const std::vector<std::string> tempAdditionalFiles = val.get<std::vector<std::string>>();
|
||||||
additionalFiles = std::vector<fs::path>(tempAdditionalFiles.size());
|
additionalFiles = std::vector<fs::path>(tempAdditionalFiles.size());
|
||||||
|
|
@ -133,9 +158,30 @@ Configuration::Configuration(const nlohmann::json& configs, const nlohmann::json
|
||||||
if(!extendData.march.empty() && march.empty()) {
|
if(!extendData.march.empty() && march.empty()) {
|
||||||
march = extendData.march;
|
march = extendData.march;
|
||||||
}
|
}
|
||||||
|
if(!extendData.lib_paths.empty()){
|
||||||
|
lib_paths.insert(lib_paths.end(), extendData.lib_paths.begin(), extendData.lib_paths.end());
|
||||||
|
}
|
||||||
|
if(!extendData.c_files.empty()){
|
||||||
|
c_files.insert(c_files.end(), extendData.c_files.begin(), extendData.c_files.end());
|
||||||
|
}
|
||||||
if(!extendData.flags.empty()){
|
if(!extendData.flags.empty()){
|
||||||
flags.insert(flags.end(), extendData.flags.begin(), extendData.flags.end());
|
flags.insert(flags.end(), extendData.flags.begin(), extendData.flags.end());
|
||||||
}
|
}
|
||||||
|
if(extendData.debug){
|
||||||
|
debug = true;
|
||||||
|
}
|
||||||
|
if(extendData.verbose){
|
||||||
|
verbose = true;
|
||||||
|
}
|
||||||
|
if(!extendData.libs.empty()){
|
||||||
|
libs.insert(libs.end(), extendData.libs.begin(), extendData.libs.end());
|
||||||
|
}
|
||||||
|
if(!extendData.shaderFiles.empty()){
|
||||||
|
shaderFiles.insert(shaderFiles.end(), extendData.shaderFiles.begin(), extendData.shaderFiles.end());
|
||||||
|
}
|
||||||
|
if(!extendData.includeDirs.empty()){
|
||||||
|
includeDirs.insert(includeDirs.end(), extendData.includeDirs.begin(), extendData.includeDirs.end());
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ module;
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
export module Crafter.Build:Configuration;
|
export module Crafter.Build:Configuration;
|
||||||
import :Dependency;
|
import :Dependency;
|
||||||
|
import :Shader;
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
|
@ -34,18 +35,25 @@ export namespace Crafter::Build {
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string standard;
|
std::string standard;
|
||||||
std::vector<fs::path> sourceFiles;
|
std::vector<fs::path> sourceFiles;
|
||||||
|
std::vector<fs::path> c_files;
|
||||||
std::vector<fs::path> moduleFiles;
|
std::vector<fs::path> moduleFiles;
|
||||||
|
std::vector<Shader> shaderFiles;
|
||||||
std::vector<fs::path> additionalFiles;
|
std::vector<fs::path> additionalFiles;
|
||||||
|
std::vector<std::string> includeDirs;
|
||||||
std::string optimizationLevel;
|
std::string optimizationLevel;
|
||||||
std::string buildDir;
|
std::string buildDir;
|
||||||
std::string outputDir;
|
std::string outputDir;
|
||||||
std::string type;
|
std::string type;
|
||||||
std::string target;
|
std::string target;
|
||||||
std::string march;
|
std::string march;
|
||||||
|
bool debug;
|
||||||
|
std::vector<std::string> libs;
|
||||||
|
std::vector<std::string> lib_paths;
|
||||||
std::vector<Dependency> dependencies;
|
std::vector<Dependency> dependencies;
|
||||||
std::unordered_map<std::string, nlohmann::json> additionalProperties;
|
std::unordered_map<std::string, nlohmann::json> additionalProperties;
|
||||||
std::vector<std::string> flags;
|
std::vector<std::string> flags;
|
||||||
Configuration(std::string name, std::string standard, std::vector<fs::path> sourceFiles, std::vector<fs::path> moduleFiles, std::string optimizationLevel, std::string buildDir, std::string outputDir, std::string type, std::string target, std::string march, std::vector<Dependency> dependencies, std::vector<fs::path> additionalFiles, std::vector<std::string> flags);
|
bool verbose;
|
||||||
|
Configuration(std::string name, std::string standard, std::vector<fs::path> sourceFiles, std::vector<fs::path> moduleFiles, std::string optimizationLevel, std::string buildDir, std::string outputDir, std::string type, std::string target, std::string march, std::vector<Dependency> dependencies, std::vector<fs::path> additionalFiles, std::vector<std::string> flags, bool debug, std::vector<std::string> libs, std::vector<std::string> lib_paths, std::vector<fs::path> c_files, std::vector<Shader> shaderFiles, std::vector<std::string> includeDirs, bool verbose);
|
||||||
Configuration(const nlohmann::json& configs, const nlohmann::json& config, fs::path workingDir);
|
Configuration(const nlohmann::json& configs, const nlohmann::json& config, fs::path workingDir);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -99,18 +99,32 @@ void ModuleFile::Compile(std::string clangDir, const Configuration& config, fs::
|
||||||
for(const std::string& flag : config.flags) {
|
for(const std::string& flag : config.flags) {
|
||||||
flags+=flag;
|
flags+=flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(config.debug) {
|
||||||
|
flags+=" -g";
|
||||||
|
}
|
||||||
|
|
||||||
std::string march;
|
std::string march;
|
||||||
if(config.target != "wasm32-unknown-wasi"){
|
if(config.target != "wasm32-unknown-wasi"){
|
||||||
march = std::format("-march={}", config.march);
|
march = std::format("-march={}", config.march);
|
||||||
}
|
}
|
||||||
|
|
||||||
system(std::format("{} -std={} {}.cppm --precompile {} {} -fprebuilt-module-path={} -o {}.pcm {}", clangDir, config.standard, path.generic_string(), march, flags, pcmDir.generic_string(), (pcmDir/path.filename()).generic_string(), target).c_str());
|
std::string command = std::format("{} {} -std={} {}.cppm --precompile {} -fprebuilt-module-path={} -o {}.pcm {}", clangDir, flags, config.standard, path.generic_string(), march, pcmDir.generic_string(), (pcmDir/path.filename()).generic_string(), target);
|
||||||
|
if(config.verbose) {
|
||||||
|
std::cout << command << std::endl;
|
||||||
|
}
|
||||||
|
system(command.c_str());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
recompiled = true;
|
recompiled = true;
|
||||||
fileMutex.unlock();
|
fileMutex.unlock();
|
||||||
|
|
||||||
system(std::format("{} -std={} {}.pcm -fprebuilt-module-path={} -c -O{} {} {} -o {}.o {}", clangDir, config.standard, (pcmDir/path.filename()).generic_string(), pcmDir.generic_string(), config.optimizationLevel, march, flags, (config.buildDir/path.filename()).generic_string(), target).c_str());
|
command = std::format("{} -std={} {}.pcm -fprebuilt-module-path={} -c -O{} {} {} -o {}.o {}", clangDir, config.standard, (pcmDir/path.filename()).generic_string(), pcmDir.generic_string(), config.optimizationLevel, march, flags, (config.buildDir/path.filename()).generic_string(), target);
|
||||||
|
if(config.verbose) {
|
||||||
|
std::cout << command << std::endl;
|
||||||
|
}
|
||||||
|
system(command.c_str());
|
||||||
} else {
|
} else {
|
||||||
fileMutex.unlock();
|
fileMutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ module;
|
||||||
#include "json.hpp"
|
#include "json.hpp"
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <glslang/SPIRV/GlslangToSpv.h>
|
||||||
module Crafter.Build;
|
module Crafter.Build;
|
||||||
using namespace Crafter::Build;
|
using namespace Crafter::Build;
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
@ -102,7 +103,24 @@ void Project::Build(Configuration config, fs::path outputDir, fs::path binDir) c
|
||||||
pcmDir = config.buildDir;
|
pcmDir = config.buildDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string libs;
|
|
||||||
|
std::string libs = " -L/usr/local/lib";
|
||||||
|
|
||||||
|
if(config.target != "x86_64-w64-mingw64" && config.target != "x86_64-w64-mingw32") {
|
||||||
|
libs += " -L/usr/lib/";
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const std::string& path : config.lib_paths) {
|
||||||
|
libs += std::format(" -L{}", path);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const std::string& path : config.includeDirs) {
|
||||||
|
libs += std::format(" -I{}", path);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Shader& shader : config.shaderFiles) {
|
||||||
|
shader.Compile(outputDir);
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::thread> depThreads = std::vector<std::thread>(config.dependencies.size());
|
std::vector<std::thread> depThreads = std::vector<std::thread>(config.dependencies.size());
|
||||||
|
|
||||||
|
|
@ -161,6 +179,14 @@ void Project::Build(Configuration config, fs::path outputDir, fs::path binDir) c
|
||||||
flags+=flag;
|
flags+=flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(config.debug) {
|
||||||
|
flags+=" -g";
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const std::string& lib : config.libs) {
|
||||||
|
libs+= std::format(" -l{}",lib);
|
||||||
|
}
|
||||||
|
|
||||||
for(std::thread& thread : depThreads){
|
for(std::thread& thread : depThreads){
|
||||||
thread.join();
|
thread.join();
|
||||||
}
|
}
|
||||||
|
|
@ -182,12 +208,26 @@ void Project::Build(Configuration config, fs::path outputDir, fs::path binDir) c
|
||||||
march = std::format("-march={}", config.march);
|
march = std::format("-march={}", config.march);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::vector<std::thread> threads;
|
std::vector<std::thread> threads;
|
||||||
for(std::uint_fast32_t i = 0; i < config.sourceFiles.size(); i++) {
|
for(std::uint_fast32_t i = 0; i < config.sourceFiles.size(); i++) {
|
||||||
files+=std::format("{}_source.o ",(config.buildDir/config.sourceFiles[i].filename()).generic_string());
|
files+=std::format("{}_source.o ",(config.buildDir/config.sourceFiles[i].filename()).generic_string());
|
||||||
//if(!fs::exists((config.buildDir/config.sourceFiles[i].filename()).generic_string()+"_source.o") || fs::last_write_time(config.sourceFiles[i].generic_string()+".cpp") > fs::last_write_time((config.buildDir/config.sourceFiles[i].filename()).generic_string()+"_source.o")) {
|
//if(!fs::exists((config.buildDir/config.sourceFiles[i].filename()).generic_string()+"_source.o") || fs::last_write_time(config.sourceFiles[i].generic_string()+".cpp") > fs::last_write_time((config.buildDir/config.sourceFiles[i].filename()).generic_string()+"_source.o")) {
|
||||||
threads.emplace_back([i, &config, pcmDir, target, clangDir, flags, march](){
|
threads.emplace_back([i, &config, pcmDir, target, clangDir, flags, march](){
|
||||||
system(std::format("{} -std={} {}.cpp -fprebuilt-module-path={} -c -O{} {} {} -o {}_source.o {}", clangDir, config.standard, config.sourceFiles[i].generic_string(), pcmDir.generic_string(), config.optimizationLevel, march, flags, (config.buildDir/config.sourceFiles[i].filename()).generic_string(), target).c_str());
|
std::string command = std::format("{} -std={} {}.cpp -fprebuilt-module-path={} -c -O{} {} {} -o {}_source.o {}", clangDir, config.standard, config.sourceFiles[i].generic_string(), pcmDir.generic_string(), config.optimizationLevel, march, flags, (config.buildDir/config.sourceFiles[i].filename()).generic_string(), target);
|
||||||
|
if(config.verbose) {
|
||||||
|
std::cout << command << std::endl;
|
||||||
|
}
|
||||||
|
system(command.c_str());
|
||||||
|
});
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(std::uint_fast32_t i = 0; i < config.c_files.size(); i++) {
|
||||||
|
files+=std::format("{}_source.o ",(config.buildDir/config.c_files[i].filename()).generic_string());
|
||||||
|
//if(!fs::exists((config.buildDir/config.sourceFiles[i].filename()).generic_string()+"_source.o") || fs::last_write_time(config.sourceFiles[i].generic_string()+".cpp") > fs::last_write_time((config.buildDir/config.sourceFiles[i].filename()).generic_string()+"_source.o")) {
|
||||||
|
threads.emplace_back([i, &config, pcmDir, target, clangDir, flags, march](){
|
||||||
|
system(std::format("clang {}.c -c -O{} {} {} -o {}_source.o {}", config.c_files[i].generic_string(), config.optimizationLevel, march, flags, (config.buildDir/config.c_files[i].filename()).generic_string(), target).c_str());
|
||||||
});
|
});
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
@ -197,9 +237,18 @@ void Project::Build(Configuration config, fs::path outputDir, fs::path binDir) c
|
||||||
}
|
}
|
||||||
|
|
||||||
if(config.type == "executable"){
|
if(config.type == "executable"){
|
||||||
system(std::format("{} {}-O{} -o {} {} {} -fuse-ld=lld", clangDir, files, config.optimizationLevel, (outputDir/name).generic_string(), target, libs).c_str());
|
//std::cout << std::format("{} {} {}-O{} -o {} {} {} -fuse-ld=lld", clangDir, flags, files, config.optimizationLevel, (outputDir/name).generic_string(), target, libs).c_str() << std::endl;
|
||||||
|
if(config.target == "x86_64-w64-mingw64" || config.target == "x86_64-w64-mingw32") {
|
||||||
|
flags += " -static-libgcc -static-libstdc++ -Wl,-Bstatic -lstdc++ -lpthread";
|
||||||
|
name += ".exe";
|
||||||
|
}
|
||||||
|
std::string command = std::format("{} {} {}-O{} -o {} {} {} -fuse-ld=lld", clangDir, flags, files, config.optimizationLevel, (outputDir/name).generic_string(), target, libs);
|
||||||
|
if(config.verbose) {
|
||||||
|
std::cout << command << std::endl;
|
||||||
|
}
|
||||||
|
system(command.c_str());
|
||||||
} else if(config.type == "library"){
|
} else if(config.type == "library"){
|
||||||
system(std::format("ar r {}.a {}", (outputDir/fs::path("lib"+name)).generic_string(), files).c_str());
|
system(std::format("ar r {}.a {}", (outputDir/fs::path("lib"+name)).generic_string(), files).c_str());
|
||||||
} else if(config.type == "shared-library"){
|
} else if(config.type == "shared-library"){
|
||||||
system(std::format("ar r {}.so {}", (outputDir/fs::path("lib"+name)).generic_string(), files).c_str());
|
system(std::format("ar r {}.so {}", (outputDir/fs::path("lib"+name)).generic_string(), files).c_str());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
99
Crafter.Build-Shader.cpp
Normal file
99
Crafter.Build-Shader.cpp
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
/*
|
||||||
|
Crafter.Build
|
||||||
|
Copyright (C) 2025 Catcrafts
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 3.0 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
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 <string>
|
||||||
|
#include <iostream>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <glslang/SPIRV/GlslangToSpv.h>
|
||||||
|
#include <glslang/Public/ShaderLang.h>
|
||||||
|
#include <glslang/Public/ResourceLimits.h>
|
||||||
|
#include "DirStackFileIncluder.h"
|
||||||
|
#include <fstream>
|
||||||
|
#include <iterator>
|
||||||
|
module Crafter.Build;
|
||||||
|
using namespace Crafter::Build;
|
||||||
|
|
||||||
|
Shader::Shader(fs::path path, std::string entrypoint, EShLanguage type): path(path), entrypoint(entrypoint), type(type) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shader::Compile(fs::path outputDir) {
|
||||||
|
glslang::InitializeProcess();
|
||||||
|
EShMessages messages = static_cast<EShMessages>(EShMsgDefault | EShMsgVulkanRules | EShMsgSpvRules);
|
||||||
|
std::ifstream fileStream(path, std::ios::in | std::ios::binary);
|
||||||
|
if (!fileStream) {
|
||||||
|
throw std::ios_base::failure("Failed to open file: " + path.string());
|
||||||
|
}
|
||||||
|
std::ostringstream contents;
|
||||||
|
contents << fileStream.rdbuf();
|
||||||
|
std::string src = contents.str();
|
||||||
|
|
||||||
|
const char *file_name_list[1] = {""};
|
||||||
|
const char *shader_source = reinterpret_cast<const char *>(src.data());
|
||||||
|
|
||||||
|
glslang::TShader shader(type);
|
||||||
|
shader.setStringsWithLengthsAndNames(&shader_source, nullptr, file_name_list, 1);
|
||||||
|
shader.setEntryPoint(entrypoint.c_str());
|
||||||
|
shader.setSourceEntryPoint(entrypoint.c_str());
|
||||||
|
shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_4);
|
||||||
|
DirStackFileIncluder includeDir;
|
||||||
|
includeDir.pushExternalLocalDirectory(path.parent_path().generic_string());
|
||||||
|
std::string info_log;
|
||||||
|
if (!shader.parse(GetDefaultResources(), 100, false, messages, includeDir))
|
||||||
|
{
|
||||||
|
info_log = std::string(shader.getInfoLog()) + std::string(shader.getInfoDebugLog());
|
||||||
|
}
|
||||||
|
// Add shader to new program object.
|
||||||
|
glslang::TProgram program;
|
||||||
|
program.addShader(&shader);
|
||||||
|
|
||||||
|
// Link program.
|
||||||
|
if (!program.link(messages))
|
||||||
|
{
|
||||||
|
info_log = std::string(program.getInfoLog()) + std::string(program.getInfoDebugLog());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save any info log that was generated.
|
||||||
|
if (shader.getInfoLog())
|
||||||
|
{
|
||||||
|
info_log += std::string(shader.getInfoLog()) + std::string(shader.getInfoDebugLog());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (program.getInfoLog())
|
||||||
|
{
|
||||||
|
info_log += std::string(program.getInfoLog()) + std::string(program.getInfoDebugLog());
|
||||||
|
}
|
||||||
|
|
||||||
|
glslang::TIntermediate* intermediate = program.getIntermediate(type);
|
||||||
|
if (!intermediate)
|
||||||
|
{
|
||||||
|
info_log += "Failed to get shared intermediate code.";
|
||||||
|
}
|
||||||
|
|
||||||
|
spv::SpvBuildLogger logger;
|
||||||
|
std::vector<std::uint32_t> spirv;
|
||||||
|
std::cout << info_log;
|
||||||
|
glslang::GlslangToSpv(*intermediate, spirv, &logger);
|
||||||
|
std::cout << logger.getAllMessages();
|
||||||
|
glslang::FinalizeProcess();
|
||||||
|
path.replace_extension("spirv");
|
||||||
|
std::ofstream file(outputDir/path, std::ios::binary);
|
||||||
|
file.write(reinterpret_cast<const char*>(spirv.data()), spirv.size() * sizeof(std::uint32_t));
|
||||||
|
}
|
||||||
36
Crafter.Build-Shader.cppm
Normal file
36
Crafter.Build-Shader.cppm
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
Crafter.Build
|
||||||
|
Copyright (C) 2025 Catcrafts
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 3.0 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
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 <string>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <glslang/Public/ShaderLang.h>
|
||||||
|
export module Crafter.Build:Shader;
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
export namespace Crafter::Build {
|
||||||
|
class Shader {
|
||||||
|
public:
|
||||||
|
fs::path path;
|
||||||
|
std::string entrypoint;
|
||||||
|
EShLanguage type;
|
||||||
|
Shader(fs::path path, std::string entrypoint, EShLanguage type);
|
||||||
|
void Compile(fs::path outputDir);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -23,3 +23,4 @@ export import :Dependency;
|
||||||
export import :Project;
|
export import :Project;
|
||||||
export import :Configuration;
|
export import :Configuration;
|
||||||
export import :ModuleFile;
|
export import :ModuleFile;
|
||||||
|
export import :Shader;
|
||||||
|
|
|
||||||
149
DirStackFileIncluder.h
Normal file
149
DirStackFileIncluder.h
Normal file
|
|
@ -0,0 +1,149 @@
|
||||||
|
//
|
||||||
|
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
||||||
|
// Copyright (C) 2017 Google, Inc.
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions
|
||||||
|
// are met:
|
||||||
|
//
|
||||||
|
// Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following
|
||||||
|
// disclaimer in the documentation and/or other materials provided
|
||||||
|
// with the distribution.
|
||||||
|
//
|
||||||
|
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived
|
||||||
|
// from this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <fstream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
#include <glslang/Public/ShaderLang.h>
|
||||||
|
|
||||||
|
// Default include class for normal include convention of search backward
|
||||||
|
// through the stack of active include paths (for nested includes).
|
||||||
|
// Can be overridden to customize.
|
||||||
|
class DirStackFileIncluder : public glslang::TShader::Includer {
|
||||||
|
public:
|
||||||
|
DirStackFileIncluder() : externalLocalDirectoryCount(0) { }
|
||||||
|
|
||||||
|
virtual IncludeResult* includeLocal(const char* headerName,
|
||||||
|
const char* includerName,
|
||||||
|
size_t inclusionDepth) override
|
||||||
|
{
|
||||||
|
return readLocalPath(headerName, includerName, (int)inclusionDepth);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual IncludeResult* includeSystem(const char* headerName,
|
||||||
|
const char* /*includerName*/,
|
||||||
|
size_t /*inclusionDepth*/) override
|
||||||
|
{
|
||||||
|
return readSystemPath(headerName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Externally set directories. E.g., from a command-line -I<dir>.
|
||||||
|
// - Most-recently pushed are checked first.
|
||||||
|
// - All these are checked after the parse-time stack of local directories
|
||||||
|
// is checked.
|
||||||
|
// - This only applies to the "local" form of #include.
|
||||||
|
// - Makes its own copy of the path.
|
||||||
|
virtual void pushExternalLocalDirectory(const std::string& dir)
|
||||||
|
{
|
||||||
|
directoryStack.push_back(dir);
|
||||||
|
externalLocalDirectoryCount = (int)directoryStack.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void releaseInclude(IncludeResult* result) override
|
||||||
|
{
|
||||||
|
if (result != nullptr) {
|
||||||
|
delete [] static_cast<tUserDataElement*>(result->userData);
|
||||||
|
delete result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::set<std::string> getIncludedFiles()
|
||||||
|
{
|
||||||
|
return includedFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~DirStackFileIncluder() override { }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
typedef char tUserDataElement;
|
||||||
|
std::vector<std::string> directoryStack;
|
||||||
|
int externalLocalDirectoryCount;
|
||||||
|
std::set<std::string> includedFiles;
|
||||||
|
|
||||||
|
// Search for a valid "local" path based on combining the stack of include
|
||||||
|
// directories and the nominal name of the header.
|
||||||
|
virtual IncludeResult* readLocalPath(const char* headerName, const char* includerName, int depth)
|
||||||
|
{
|
||||||
|
// Discard popped include directories, and
|
||||||
|
// initialize when at parse-time first level.
|
||||||
|
directoryStack.resize(depth + externalLocalDirectoryCount);
|
||||||
|
if (depth == 1)
|
||||||
|
directoryStack.back() = getDirectory(includerName);
|
||||||
|
|
||||||
|
// Find a directory that works, using a reverse search of the include stack.
|
||||||
|
for (auto it = directoryStack.rbegin(); it != directoryStack.rend(); ++it) {
|
||||||
|
std::string path = *it + '/' + headerName;
|
||||||
|
std::replace(path.begin(), path.end(), '\\', '/');
|
||||||
|
std::ifstream file(path, std::ios_base::binary | std::ios_base::ate);
|
||||||
|
if (file) {
|
||||||
|
directoryStack.push_back(getDirectory(path));
|
||||||
|
includedFiles.insert(path);
|
||||||
|
return newIncludeResult(path, file, (int)file.tellg());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search for a valid <system> path.
|
||||||
|
// Not implemented yet; returning nullptr signals failure to find.
|
||||||
|
virtual IncludeResult* readSystemPath(const char* /*headerName*/) const
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do actual reading of the file, filling in a new include result.
|
||||||
|
virtual IncludeResult* newIncludeResult(const std::string& path, std::ifstream& file, int length) const
|
||||||
|
{
|
||||||
|
char* content = new tUserDataElement [length];
|
||||||
|
file.seekg(0, file.beg);
|
||||||
|
file.read(content, length);
|
||||||
|
return new IncludeResult(path, content, length, content);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no path markers, return current working directory.
|
||||||
|
// Otherwise, strip file name and return path leading up to it.
|
||||||
|
virtual std::string getDirectory(const std::string path) const
|
||||||
|
{
|
||||||
|
size_t last = path.find_last_of("/\\");
|
||||||
|
return last == std::string::npos ? "." : path.substr(0, last);
|
||||||
|
}
|
||||||
|
};
|
||||||
5
build.sh
5
build.sh
|
|
@ -5,19 +5,22 @@ clang++ -std=c++26 Crafter.Build-Dependency.cppm --precompile -fprebuilt-module-
|
||||||
clang++ -std=c++26 Crafter.Build-Configuration.cppm --precompile -fprebuilt-module-path=./build -o ./build/Crafter.Build-Configuration.pcm
|
clang++ -std=c++26 Crafter.Build-Configuration.cppm --precompile -fprebuilt-module-path=./build -o ./build/Crafter.Build-Configuration.pcm
|
||||||
clang++ -std=c++26 Crafter.Build-ModuleFile.cppm --precompile -fprebuilt-module-path=./build -o ./build/Crafter.Build-ModuleFile.pcm
|
clang++ -std=c++26 Crafter.Build-ModuleFile.cppm --precompile -fprebuilt-module-path=./build -o ./build/Crafter.Build-ModuleFile.pcm
|
||||||
clang++ -std=c++26 Crafter.Build-Project.cppm --precompile -fprebuilt-module-path=./build -o ./build/Crafter.Build-Project.pcm
|
clang++ -std=c++26 Crafter.Build-Project.cppm --precompile -fprebuilt-module-path=./build -o ./build/Crafter.Build-Project.pcm
|
||||||
|
clang++ -std=c++26 Crafter.Build-Shader.cppm --precompile -fprebuilt-module-path=./build -o ./build/Crafter.Build-Shader.pcm
|
||||||
clang++ -std=c++26 Crafter.Build.cppm --precompile -fprebuilt-module-path=./build -o ./build/Crafter.Build.pcm
|
clang++ -std=c++26 Crafter.Build.cppm --precompile -fprebuilt-module-path=./build -o ./build/Crafter.Build.pcm
|
||||||
|
|
||||||
clang++ -std=c++26 Crafter.Build-Dependency.cpp -fprebuilt-module-path=./build -c -O3 -o ./build/Crafter.Build-Dependency_source.o
|
clang++ -std=c++26 Crafter.Build-Dependency.cpp -fprebuilt-module-path=./build -c -O3 -o ./build/Crafter.Build-Dependency_source.o
|
||||||
clang++ -std=c++26 Crafter.Build-Configuration.cpp -fprebuilt-module-path=./build -c -O3 -o ./build/Crafter.Build-Configuration_source.o
|
clang++ -std=c++26 Crafter.Build-Configuration.cpp -fprebuilt-module-path=./build -c -O3 -o ./build/Crafter.Build-Configuration_source.o
|
||||||
clang++ -std=c++26 Crafter.Build-ModuleFile.cpp -fprebuilt-module-path=./build -c -O3 -o ./build/Crafter.Build-ModuleFile_source.o
|
clang++ -std=c++26 Crafter.Build-ModuleFile.cpp -fprebuilt-module-path=./build -c -O3 -o ./build/Crafter.Build-ModuleFile_source.o
|
||||||
|
clang++ -std=c++26 Crafter.Build-Shader.cpp -fprebuilt-module-path=./build -c -O3 -o ./build/Crafter.Build-Shader_source.o
|
||||||
clang++ -std=c++26 Crafter.Build-Project.cpp -fprebuilt-module-path=./build -c -O3 -o ./build/Crafter.Build-Project_source.o
|
clang++ -std=c++26 Crafter.Build-Project.cpp -fprebuilt-module-path=./build -c -O3 -o ./build/Crafter.Build-Project_source.o
|
||||||
clang++ -std=c++26 main.cpp -fprebuilt-module-path=./build -c -o ./build/main.o
|
clang++ -std=c++26 main.cpp -fprebuilt-module-path=./build -c -o ./build/main.o
|
||||||
|
|
||||||
clang++ -std=c++26 ./build/Crafter.Build-Project.pcm -fprebuilt-module-path=./build -c -O3 -o ./build/Crafter.Build-Project.o
|
clang++ -std=c++26 ./build/Crafter.Build-Project.pcm -fprebuilt-module-path=./build -c -O3 -o ./build/Crafter.Build-Project.o
|
||||||
clang++ -std=c++26 ./build/Crafter.Build-Configuration.pcm -fprebuilt-module-path=./build -c -O3 -o ./build/Crafter.Build-Configuration.o
|
clang++ -std=c++26 ./build/Crafter.Build-Configuration.pcm -fprebuilt-module-path=./build -c -O3 -o ./build/Crafter.Build-Configuration.o
|
||||||
clang++ -std=c++26 ./build/Crafter.Build-ModuleFile.pcm -fprebuilt-module-path=./build -c -O3 -o ./build/Crafter.Build-ModuleFile.o
|
clang++ -std=c++26 ./build/Crafter.Build-ModuleFile.pcm -fprebuilt-module-path=./build -c -O3 -o ./build/Crafter.Build-ModuleFile.o
|
||||||
|
clang++ -std=c++26 ./build/Crafter.Build-Shader.pcm -fprebuilt-module-path=./build -c -O3 -o ./build/Crafter.Build-Shader.o
|
||||||
clang++ -std=c++26 ./build/Crafter.Build-Dependency.pcm -fprebuilt-module-path=./build -c -O3 -o ./build/Crafter.Build-Dependency.o
|
clang++ -std=c++26 ./build/Crafter.Build-Dependency.pcm -fprebuilt-module-path=./build -c -O3 -o ./build/Crafter.Build-Dependency.o
|
||||||
clang++ -std=c++26 ./build/Crafter.Build.pcm -fprebuilt-module-path=./build -c -O3 -o ./build/Crafter.Build.o
|
clang++ -std=c++26 ./build/Crafter.Build.pcm -fprebuilt-module-path=./build -c -O3 -o ./build/Crafter.Build.o
|
||||||
clang++ ./build/main.o ./build/Crafter.Build-ModuleFile_source.o ./build/Crafter.Build-ModuleFile.o ./build/Crafter.Build.o ./build/Crafter.Build-Configuration.o ./build/Crafter.Build-Configuration_source.o ./build/Crafter.Build-Project.o ./build/Crafter.Build-Project_source.o ./build/Crafter.Build-Dependency.o ./build/Crafter.Build-Dependency_source.o -O3 -o ./bin/crafter-build
|
clang++ -Llibvulkan -LlibMachineIndependent, -LlibOSDependent, -LlibGenericCodeGen -Llibglslang -Lglslang-default-resource-limits -LlibSPIRV -LlibSPVRemapper ./build/main.o ./build/Crafter.Build-ModuleFile_source.o ./build/Crafter.Build-ModuleFile.o ./build/Crafter.Build-Shader_source.o ./build/Crafter.Build-Shader.o ./build/Crafter.Build.o ./build/Crafter.Build-Configuration.o ./build/Crafter.Build-Configuration_source.o ./build/Crafter.Build-Project.o ./build/Crafter.Build-Project_source.o ./build/Crafter.Build-Dependency.o ./build/Crafter.Build-Dependency_source.o -O3 -o ./bin/crafter-build
|
||||||
|
|
||||||
rm -rf build
|
rm -rf build
|
||||||
|
|
|
||||||
7
main.cpp
7
main.cpp
|
|
@ -66,8 +66,11 @@ int main(int argc, char* argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(run){
|
if(run){
|
||||||
for(const Configuration& config : project.configurations) {
|
for(Configuration& config : project.configurations) {
|
||||||
if(config.name == configuration){
|
if(config.name == configuration) {
|
||||||
|
if(config.target == "x86_64-w64-mingw64" || config.target == "x86_64-w64-mingw32") {
|
||||||
|
project.name += ".exe";
|
||||||
|
}
|
||||||
system(std::format("{}", (projectPath/fs::path(config.outputDir)/project.name).generic_string()).c_str());
|
system(std::format("{}", (projectPath/fs::path(config.outputDir)/project.name).generic_string()).c_str());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
10
project.json
10
project.json
|
|
@ -4,10 +4,11 @@
|
||||||
{
|
{
|
||||||
"name": "base",
|
"name": "base",
|
||||||
"standard": "c++26",
|
"standard": "c++26",
|
||||||
"source_files": ["Crafter.Build-Configuration", "Crafter.Build-Project", "Crafter.Build-Dependency", "Crafter.Build-ModuleFile"],
|
"source_files": ["Crafter.Build-Configuration", "Crafter.Build-Project", "Crafter.Build-Dependency", "Crafter.Build-ModuleFile", "Crafter.Build-Shader"],
|
||||||
"module_files": ["Crafter.Build-Dependency", "Crafter.Build-Configuration", "Crafter.Build-Project", "Crafter.Build", "Crafter.Build-ModuleFile"],
|
"module_files": ["Crafter.Build-Dependency", "Crafter.Build-Configuration", "Crafter.Build-Project", "Crafter.Build-Shader", "Crafter.Build", "Crafter.Build-ModuleFile"],
|
||||||
"build_dir": "./build",
|
"build_dir": "./build",
|
||||||
"output_dir": "./bin"
|
"output_dir": "./bin",
|
||||||
|
"libs": ["vulkan", "MachineIndependent", "OSDependent", "GenericCodeGen", "glslang", "glslang-default-resource-limits", "SPIRV", "SPVRemapper"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "executable",
|
"name": "executable",
|
||||||
|
|
@ -23,7 +24,8 @@
|
||||||
{
|
{
|
||||||
"name": "debug",
|
"name": "debug",
|
||||||
"extends": ["executable"],
|
"extends": ["executable"],
|
||||||
"optimization_level": "0"
|
"optimization_level": "0",
|
||||||
|
"debug": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "release",
|
"name": "release",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue