This commit is contained in:
Jorijn van der Graaf 2025-04-24 19:21:09 +02:00
commit be18fb8568
12 changed files with 427 additions and 19 deletions

View file

@ -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

View file

@ -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) {
} }
@ -36,6 +37,10 @@ Configuration::Configuration(const nlohmann::json& configs, const nlohmann::json
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;
} }
} }

View file

@ -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);
}; };
} }

View file

@ -100,17 +100,31 @@ void ModuleFile::Compile(std::string clangDir, const Configuration& config, fs::
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();
} }

View file

@ -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,7 +237,16 @@ 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"){

99
Crafter.Build-Shader.cpp Normal file
View 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
View 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);
};
}

View file

@ -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
View 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);
}
};

View file

@ -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

View file

@ -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;
} }

View file

@ -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",