This commit is contained in:
Jorijn van der Graaf 2025-05-15 15:25:06 +02:00
commit 5af6d0080a
8 changed files with 93 additions and 73 deletions

View file

@ -25,7 +25,7 @@ module Crafter.Build;
using namespace Crafter::Build;
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, 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) {
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, std::vector<Define> defines): 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), defines(defines) {
}
@ -83,6 +83,12 @@ Configuration::Configuration(const nlohmann::json& configs, const nlohmann::json
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 == "defines") {
for (auto it : val) {
std::string name = it["name"].get<std::string>();
std::string value = it["value"].get<std::string>();
defines.emplace_back(name, value);
}
} else if(key == "additional_files") {
const std::vector<std::string> tempAdditionalFiles = val.get<std::vector<std::string>>();
additionalFiles = std::vector<fs::path>(tempAdditionalFiles.size());
@ -182,6 +188,9 @@ Configuration::Configuration(const nlohmann::json& configs, const nlohmann::json
if(!extendData.includeDirs.empty()){
includeDirs.insert(includeDirs.end(), extendData.includeDirs.begin(), extendData.includeDirs.end());
}
if(!extendData.defines.empty()){
defines.insert(defines.end(), extendData.defines.begin(), extendData.defines.end());
}
break;
}
}

View file

@ -23,6 +23,7 @@ module;
#include <vector>
#include "json.hpp"
#include <unordered_map>
#include <format>
export module Crafter.Build:Configuration;
import :Dependency;
import :Shader;
@ -30,6 +31,14 @@ import :Shader;
namespace fs = std::filesystem;
export namespace Crafter::Build {
struct Define {
std::string name;
std::string value;
std::string ToString() const {
return std::format(" -D {}={}", name, value);
}
};
class Configuration {
public:
std::string name;
@ -40,6 +49,7 @@ export namespace Crafter::Build {
std::vector<Shader> shaderFiles;
std::vector<fs::path> additionalFiles;
std::vector<std::string> includeDirs;
std::vector<Define> defines;
std::string optimizationLevel;
std::string buildDir;
std::string outputDir;
@ -53,7 +63,7 @@ export namespace Crafter::Build {
std::unordered_map<std::string, nlohmann::json> additionalProperties;
std::vector<std::string> flags;
bool verbose = false;
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(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, std::vector<Define> defines);
Configuration(const nlohmann::json& configs, const nlohmann::json& config, fs::path workingDir);
};
}

View file

@ -29,6 +29,7 @@ export namespace Crafter::Build {
std::string configuration;
std::string commit;
std::string branch;
std::string name;
Dependency(std::string path, std::string configuration, std::string commit, std::string branch);
};
}

View file

@ -55,10 +55,8 @@ ModulePartition::ModulePartition(const std::string& name, const fs::path& path,
}
if(!fs::exists((pcmDir/path.filename()).generic_string()+".pcm")) {
needsRecompiling = true;
needsRecompilingDependency = true;
} else if(fs::last_write_time(path.generic_string()+".cppm") > fs::last_write_time((pcmDir/path.filename()).generic_string()+".pcm")) {
needsRecompiling = true;
needsRecompilingDependency = true;
}
}
@ -77,7 +75,7 @@ void ModulePartition::AddDependants() {
void ModulePartition::Check() {
if(!needsRecompiling) {
for(ModulePartition* dependency : partitionDependenciesP) {
if(dependency->needsRecompilingDependency) {
if(dependency->needsRecompiling) {
needsRecompiling = true;
break;
}
@ -87,12 +85,16 @@ void ModulePartition::Check() {
void ModulePartition::Compile(std::string clangDir, const Configuration& config, fs::path pcmDir, std::string target, const std::string& march, const std::string& flags) {
if(needsRecompiling) {
std::string defines;
for(const Define& define : config.defines) {
defines+=define.ToString();
}
for(ModulePartition* dependency : partitionDependenciesP) {
if(dependency->needsRecompiling) {
dependency->compiled->wait(false);
}
}
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);
std::string command = std::format("{} {} {} -std={} {}.cppm --precompile {} -fprebuilt-module-path={} -o {}.pcm {}", clangDir, defines, flags, config.standard, path.generic_string(), march, pcmDir.generic_string(), (pcmDir/path.filename()).generic_string(), target);
if(config.verbose) {
std::cout << command << std::endl;
}
@ -102,7 +104,11 @@ void ModulePartition::Compile(std::string clangDir, const Configuration& config,
compiled->notify_all();
}
void ModulePartition::CompileSource(std::string clangDir, const Configuration& config, fs::path pcmDir, std::string target, const std::string& march, const std::string& flags, const fs::path& buildDir) {
std::string 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, (buildDir/path.filename()).generic_string(), target);
std::string defines;
for(const Define& define : config.defines) {
defines+=define.ToString();
}
std::string command = std::format("{} {} -std={} {}.pcm -fprebuilt-module-path={} -c -O{} {} {} -o {}.o {}", clangDir, defines, config.standard, (pcmDir/path.filename()).generic_string(), pcmDir.generic_string(), config.optimizationLevel, march, flags, (buildDir/path.filename()).generic_string(), target);
if(config.verbose) {
std::cout << command << std::endl;
}
@ -145,9 +151,12 @@ void Module::Check() {
val.Check();
}
for(auto& [key, val] : partitions) {;
if(val.needsRecompilingDependency) {
for(auto& [key, val] : partitions) {
if(val.needsRecompiling) {
needsRecompiling = true;
for(auto& [key, val] : partitions) {
val.needsRecompiling = true;
}
break;
}
}

View file

@ -36,7 +36,6 @@ export namespace Crafter::Build {
class ModulePartition {
public:
bool needsRecompilingDependency = false;
bool needsRecompiling = false;
fs::path path;
Module* parent;

View file

@ -30,73 +30,54 @@ module;
#include <thread>
#include <glslang/SPIRV/GlslangToSpv.h>
#include <regex>
#include <mutex>
module Crafter.Build;
using namespace Crafter::Build;
namespace fs = std::filesystem;
std::vector<std::string> mergeUnique(const std::vector<std::string>& vec1, const std::vector<std::string>& vec2) {
std::unordered_set<std::string> uniqueElements;
std::vector<std::string> result;
for (const auto& str : vec1) {
if (uniqueElements.insert(str).second) {
result.push_back(str);
}
}
for (const auto& str : vec2) {
if (uniqueElements.insert(str).second) {
result.push_back(str);
}
}
return result;
}
Project::Project(std::string name, fs::path path, std::vector<Configuration> configurations) : name(name), path(path), configurations(configurations) {
}
void Project::Build(std::string configuration) const {
for(const Configuration& config : configurations) {
const Configuration& Project::Build(std::string configuration) {
for(Configuration& config : configurations) {
if(config.name == configuration){
Build(config);
return;
return config;
}
}
throw std::runtime_error("Configuration: " + configuration + " not found.");
}
void Project::Build(std::string configuration, fs::path outputDir) const {
for(const Configuration& config : configurations) {
const Configuration& Project::Build(std::string configuration, fs::path outputDir) {
for(Configuration& config : configurations) {
if(config.name == configuration){
Build(config, outputDir);
return;
return config;
}
}
throw std::runtime_error("Configuration: " + configuration + " not found.");
}
void Project::Build(std::string configuration, fs::path outputDir, fs::path binDir) const {
for(const Configuration& config : configurations) {
const Configuration& Project::Build(std::string configuration, fs::path outputDir, fs::path binDir) {
for(Configuration& config : configurations) {
if(config.name == configuration){
Build(config, outputDir, binDir);
return;
return config;
}
}
throw std::runtime_error("Configuration: " + configuration + " not found.");
}
void Project::Build(Configuration configuration) const {
void Project::Build(Configuration& configuration) {
Build(configuration, configuration.outputDir);
}
void Project::Build(Configuration config, fs::path outputDir) const {
void Project::Build(Configuration& config, fs::path outputDir) {
Build(config, outputDir, outputDir);
}
void Project::Build(Configuration config, fs::path outputDir, fs::path binDir) const {
void Project::Build(Configuration& config, fs::path outputDir, fs::path binDir) {
if(config.standard.empty()) {
config.standard = "c++26";
}
@ -149,7 +130,7 @@ void Project::Build(Configuration config, fs::path outputDir, fs::path binDir) c
}
for(Shader& shader : config.shaderFiles) {
shader.Compile(outputDir);
shader.Compile(binDir);
}
std::vector<std::thread> depThreads = std::vector<std::thread>(config.dependencies.size());
@ -157,7 +138,7 @@ void Project::Build(Configuration config, fs::path outputDir, fs::path binDir) c
if(config.dependencies.size() > 0){
libs += std::format(" -L{}", pcmDir.generic_string());
}
std::unordered_set<std::string> depLibSet;
for(std::int_fast32_t i = 0; i < depThreads.size(); i++) {
if(config.dependencies[i].path.ends_with(".git")) {
fs::path name = fs::path(config.dependencies[i].path).filename();
@ -176,26 +157,37 @@ void Project::Build(Configuration config, fs::path outputDir, fs::path binDir) c
}
config.dependencies[i].path = fs::path(config.dependencies[i].path).filename().replace_extension();
Project project = Project::LoadFromJSON(fs::path(buildDir)/config.dependencies[i].path/"project.json");
libs+=std::format(" -l{}", project.name);
depThreads[i] = std::thread([i, pcmDir, config, project, binDir]() {
project.Build(config.dependencies[i].configuration, pcmDir, binDir);
});
for(const Configuration& config2 : project.configurations) {
if(config2.name == config.dependencies[i].configuration){
config.libs = mergeUnique(config.libs, config2.libs);
break;
config.dependencies[i].name = project.name;
if (depLibSet.insert(project.name).second) {
libs+=std::format(" -l{}", project.name);
}
const Configuration& depConfig = project.Build(config.dependencies[i].configuration, pcmDir, binDir);
for(const std::string& lib2 : depConfig.libs) {
if (depLibSet.insert(lib2).second) {
libs+=std::format(" -l{}", lib2);
}
}
for(const Dependency& dep2 : depConfig.dependencies) {
if (depLibSet.insert(dep2.name).second) {
libs+=std::format(" -l{}", dep2.name);
}
}
} else{
Project project = Project::LoadFromJSON(config.dependencies[i].path);
libs+=std::format(" -l{}", project.name);
depThreads[i] = std::thread([i, pcmDir, config, project, binDir]() {
project.Build(config.dependencies[i].configuration, pcmDir, binDir);
});
for(const Configuration& config2 : project.configurations) {
if(config2.name == config.dependencies[i].configuration){
config.libs = mergeUnique(config.libs, config2.libs);
break;
config.dependencies[i].name = project.name;
if (depLibSet.insert(project.name).second) {
libs+=std::format(" -l{}", project.name);
}
const Configuration& depConfig = project.Build(config.dependencies[i].configuration, pcmDir, binDir);
for(const std::string& lib2 : depConfig.libs) {
if (depLibSet.insert(lib2).second) {
libs+=std::format(" -l{}", lib2);
}
}
for(const Dependency& dep2 : depConfig.dependencies) {
if (depLibSet.insert(dep2.name).second) {
libs+=std::format(" -l{}", dep2.name);
}
}
}
@ -231,10 +223,6 @@ void Project::Build(Configuration config, fs::path outputDir, fs::path binDir) c
libs+= std::format(" -l{}",lib);
}
for(std::thread& thread : depThreads){
thread.join();
}
std::string march;
if(config.target != "wasm32-unknown-wasi"){
march = std::format("-march={}", config.march);

View file

@ -33,13 +33,13 @@ export namespace Crafter::Build {
fs::path path;
std::vector<Configuration> configurations;
Project(std::string name, fs::path path, std::vector<Configuration> configurations);
void Build(std::string configuration) const;
void Build(std::string configuration, fs::path outputDir) const;
void Build(std::string configuration, fs::path outputDir, fs::path binDir) const;
void Build(Configuration configuration) const;
void Build(Configuration configuration, fs::path outputDir) const;
void Build(Configuration configuration, fs::path outputDir, fs::path binDir) const;
void SaveToJSON(fs::path path) const;
const Configuration& Build(std::string configuration);
const Configuration& Build(std::string configuration, fs::path outputDir);
const Configuration& Build(std::string configuration, fs::path outputDir, fs::path binDir);
void Build(Configuration& configuration);
void Build(Configuration& configuration, fs::path outputDir);
void Build(Configuration& configuration, fs::path outputDir, fs::path binDir);
void SaveToJSON(fs::path path);
static Project LoadFromJSON(fs::path path);
};
}

View file

@ -31,11 +31,15 @@ using namespace Crafter::Build;
namespace fs = std::filesystem;
void Source::GetSourceFiles(std::string clangDir, const Configuration& config, fs::path pcmDir, std::string target, const std::string& march, const std::string& flags, std::vector<std::thread>& threads, const std::vector<Module>& modules, std::string& files, const fs::path& buildDir) {
std::string defines;
for(const Define& define : config.defines) {
defines+=define.ToString();
}
for(const fs::path& sourceFile : config.sourceFiles) {
files+=std::format("{}_source.o ",(buildDir/sourceFile.filename()).generic_string());
if(Source::Check(sourceFile, modules, config, buildDir)) {
threads.emplace_back([&config, sourceFile, pcmDir, target, clangDir, flags, march, buildDir](){
std::string command = std::format("{} -std={} {}.cpp -fprebuilt-module-path={} -c -O{} {} {} -o {}_source.o {}", clangDir, config.standard, sourceFile.generic_string(), pcmDir.generic_string(), config.optimizationLevel, march, flags, (buildDir/sourceFile.filename()).generic_string(), target);
threads.emplace_back([&config, sourceFile, pcmDir, target, clangDir, flags, march, buildDir, defines](){
std::string command = std::format("{} {} -std={} {}.cpp -fprebuilt-module-path={} -c -O{} {} {} -o {}_source.o {}", clangDir, defines, config.standard, sourceFile.generic_string(), pcmDir.generic_string(), config.optimizationLevel, march, flags, (buildDir/sourceFile.filename()).generic_string(), target);
if(config.verbose) {
std::cout << command << std::endl;
}