error messages

This commit is contained in:
Jorijn van der Graaf 2025-09-09 23:04:05 +02:00
commit 23fa8b98b0
9 changed files with 199 additions and 90 deletions

View file

@ -25,36 +25,65 @@ module;
#include <array> #include <array>
#include <string> #include <string>
#include <cstdio> #include <cstdio>
#include <string_view>
#include <regex>
export module Crafter.Build:Bounce; export module Crafter.Build:Bounce;
export void BounceCommand(const std::string& cmd) { namespace Crafter::Build {
// std::array<char, 128> buffer; export std::string RunCommand(const std::string_view cmd) {
// std::string result; std::array<char, 128> buffer;
std::string result;
// std::string with = cmd + " 2>&1"; std::string with = std::string(cmd) + " 2>&1";
// // Open pipe to file // Open pipe to file
// FILE* pipe = popen(with.c_str(), "r"); FILE* pipe = popen(with.c_str(), "r");
// if (!pipe) throw std::runtime_error("popen() failed!"); if (!pipe) throw std::runtime_error("popen() failed!");
// // Read till end of process: // Read till end of process:
// while (fgets(buffer.data(), buffer.size(), pipe) != nullptr) { while (fgets(buffer.data(), buffer.size(), pipe) != nullptr) {
// result += buffer.data(); result += buffer.data();
// } }
// // Close pipe // Close pipe
// auto returnCode = pclose(pipe); pclose(pipe);
// if (returnCode != 0) { return result;
// // Optional: handle non-zero exit status }
// }
export void RunCommandIgnore(const std::string_view cmd) {
std::string with = std::string(cmd) + " > /dev/null 2>&1";
FILE* pipe = popen(with.c_str(), "r");
if (!pipe) throw std::runtime_error("popen() failed!");
pclose(pipe);
}
// std::cout << result; export struct ClangError {
system(cmd.c_str()); std::string filename;
} uint32_t line_number;
std::string error_message;
std::string code;
};
export void BounceCommandIgnore(const std::string& cmd) { export std::vector<ClangError> RunClang(const std::string_view cmd) {
std::string with = cmd + " > /dev/null 2>&1"; std::string result = RunCommand(cmd);
FILE* pipe = popen(with.c_str(), "r"); std::vector<ClangError> errors;
if (!pipe) throw std::runtime_error("popen() failed!");
pclose(pipe); std::regex error_regex(R"((/[^:]+\.cpp):(\d+):\d+: error: (.*)\n\s*[0-9| ]*\s*(.*))");
std::smatch match;
while (std::regex_search(result, match, error_regex)) {
ClangError error;
error.filename = match[1].str();
error.line_number = std::stoi(match[2].str());
error.error_message = match[3].str();
error.code = match[4].str();
errors.push_back(error);
result = match.suffix().str();
}
if(result != "" && errors.size() == 0) {
throw std::runtime_error(result);
}
return errors;
}
} }

View file

@ -26,6 +26,7 @@ module;
#include <regex> #include <regex>
#include <print> #include <print>
#include <execution> #include <execution>
#include <tuple>
module Crafter.Build; module Crafter.Build;
using namespace Crafter::Build; using namespace Crafter::Build;
namespace fs = std::filesystem; namespace fs = std::filesystem;
@ -83,7 +84,8 @@ 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) { std::vector<ClangError> ModulePartition::Compile(std::string clangDir, const Configuration& config, fs::path pcmDir, std::string target, const std::string& march, const std::string& flags) {
std::vector<ClangError> errors;
if(needsRecompiling) { if(needsRecompiling) {
std::string defines; std::string defines;
for(const Define& define : config.defines) { for(const Define& define : config.defines) {
@ -98,12 +100,13 @@ void ModulePartition::Compile(std::string clangDir, const Configuration& config,
if(config.verbose) { if(config.verbose) {
std::cout << command << std::endl; std::cout << command << std::endl;
} }
BounceCommand(command.c_str()); errors = RunClang(command);
} }
*compiled = true; *compiled = true;
compiled->notify_all(); compiled->notify_all();
return errors;
} }
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::vector<ClangError> 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 defines; std::string defines;
for(const Define& define : config.defines) { for(const Define& define : config.defines) {
defines+=define.ToString(); defines+=define.ToString();
@ -112,7 +115,7 @@ void ModulePartition::CompileSource(std::string clangDir, const Configuration& c
if(config.verbose) { if(config.verbose) {
std::cout << command << std::endl; std::cout << command << std::endl;
} }
BounceCommand(command.c_str()); return RunClang(command);
} }
Module::Module(const std::string& name, const fs::path& path, const Configuration& config, const fs::path& pcmDir, std::string& files, const fs::path& buildDir) : name(name), path(path) { Module::Module(const std::string& name, const fs::path& path, const Configuration& config, const fs::path& pcmDir, std::string& files, const fs::path& buildDir) : name(name), path(path) {
@ -162,18 +165,25 @@ void Module::Check() {
} }
} }
void Module::Compile(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::vector<ClangError> Module::Compile(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 defines; std::string defines;
for(const Define& define : config.defines) { for(const Define& define : config.defines) {
defines+=define.ToString(); defines+=define.ToString();
} }
std::mutex errorMutex;
std::vector<ClangError> errors;
std::vector<std::thread> threads; std::vector<std::thread> threads;
for(auto& [key, val] : partitions) {; for(auto& [key, val] : partitions) {;
if(val.needsRecompiling) { if(val.needsRecompiling) {
threads.emplace_back([&val, &clangDir, &config, &pcmDir, &target, &march, &flags](){ threads.emplace_back([&val, &clangDir, &config, &pcmDir, &target, &march, &flags, &errors, &errorMutex](){
val.Compile(clangDir, config, pcmDir, target, march, flags); std::vector<ClangError> newErrors = val.Compile(clangDir, config, pcmDir, target, march, flags);
if(newErrors.size() > 0) {
errorMutex.lock();
errors.insert(errors.end(), newErrors.begin(), newErrors.end());
errorMutex.unlock();
}
}); });
} }
} }
@ -182,36 +192,56 @@ void Module::Compile(std::string clangDir, const Configuration& config, fs::path
thread.join(); thread.join();
} }
if(errors.size() > 0) {
return errors;
}
{ {
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); 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) { if(config.verbose) {
std::cout << command << std::endl; std::cout << command << std::endl;
} }
BounceCommand(command.c_str()); errors = RunClang(command);
}
if(errors.size() > 0) {
return errors;
} }
std::vector<std::thread> threads2; std::vector<std::thread> threads2;
for(auto& [key, val] : partitions) {; for(auto& [key, val] : partitions) {;
if(val.needsRecompiling) { if(val.needsRecompiling) {
threads2.emplace_back([&val, &clangDir, &config, &pcmDir, &target, &march, &flags, &buildDir](){ threads2.emplace_back([&val, &clangDir, &config, &pcmDir, &target, &march, &flags, &buildDir, &errors, &errorMutex](){
val.CompileSource(clangDir, config, pcmDir, target, march, flags, buildDir); std::vector<ClangError> newErrors = val.CompileSource(clangDir, config, pcmDir, target, march, flags, buildDir);
if(newErrors.size() > 0) {
errorMutex.lock();
errors.insert(errors.end(), newErrors.begin(), newErrors.end());
errorMutex.unlock();
}
}); });
} }
} }
threads2.emplace_back([this, &clangDir, &config, &pcmDir, &target, &march, &flags, &buildDir, &defines](){ threads2.emplace_back([this, &clangDir, &config, &pcmDir, &target, &march, &flags, &buildDir, &defines, &errors, &errorMutex](){
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); 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) { if(config.verbose) {
std::cout << command << std::endl; std::cout << command << std::endl;
} }
BounceCommand(command.c_str()); std::vector<ClangError> newErrors = RunClang(command);
if(newErrors.size() > 0) {
errorMutex.lock();
errors.insert(errors.end(), newErrors.begin(), newErrors.end());
errorMutex.unlock();
}
}); });
for(std::thread& thread : threads2){ for(std::thread& thread : threads2){
thread.join(); thread.join();
} }
return errors;
} }
std::vector<Module> Module::GetModules(std::string clangDir, const Configuration& config, fs::path pcmDir, std::string target, const std::string& march, const std::string& flags, std::string& files, const fs::path& buildDir) { std::tuple<std::vector<Module>, std::vector<ClangError>> Module::GetModules(std::string clangDir, const Configuration& config, fs::path pcmDir, std::string target, const std::string& march, const std::string& flags, std::string& files, const fs::path& buildDir) {
std::vector<Module> modules; std::vector<Module> modules;
for(const fs::path& file: config.moduleFiles) { for(const fs::path& file: config.moduleFiles) {
std::ifstream t(file.generic_string()+".cppm"); std::ifstream t(file.generic_string()+".cppm");
@ -225,9 +255,16 @@ std::vector<Module> Module::GetModules(std::string clangDir, const Configuration
modules.emplace_back(match[1], file, config, pcmDir, files, buildDir); modules.emplace_back(match[1], file, config, pcmDir, files, buildDir);
} }
} }
std::for_each(std::execution::par, modules.begin(), modules.end(), [&clangDir, &config, &pcmDir, &target, &march, &flags, &buildDir](Module& modulee) { std::vector<ClangError> errors;
std::mutex errorMutex;
std::for_each(std::execution::par, modules.begin(), modules.end(), [&clangDir, &config, &pcmDir, &target, &march, &flags, &buildDir, &errors, &errorMutex](Module& modulee) {
modulee.Check(); modulee.Check();
modulee.Compile(clangDir, config, pcmDir, target, march, flags, buildDir); std::vector<ClangError> newErrors = modulee.Compile(clangDir, config, pcmDir, target, march, flags, buildDir);
if(newErrors.size() > 0) {
errorMutex.lock();
errors.insert(errors.end(), newErrors.begin(), newErrors.end());
errorMutex.unlock();
}
}); });
return modules; return {modules, errors};
} }

View file

@ -26,9 +26,11 @@ module;
#include <vector> #include <vector>
#include <atomic> #include <atomic>
#include <thread> #include <thread>
#include <condition_variable> #include <condition_variable>
#include <tuple>
export module Crafter.Build:ModuleFile; export module Crafter.Build:ModuleFile;
import :Configuration; import :Configuration;
import :Bounce;
namespace fs = std::filesystem; namespace fs = std::filesystem;
export namespace Crafter::Build { export namespace Crafter::Build {
@ -48,8 +50,8 @@ export namespace Crafter::Build {
ModulePartition(const std::string& name, const fs::path& path, Module* parent, const std::string& fileContent, const fs::path& pcmDir); ModulePartition(const std::string& name, const fs::path& path, Module* parent, const std::string& fileContent, const fs::path& pcmDir);
void AddDependants(); void AddDependants();
void Check(); void Check();
void Compile(std::string clangDir, const Configuration& config, fs::path pcmDir, std::string target, const std::string& march, const std::string& flags); std::vector<ClangError> Compile(std::string clangDir, const Configuration& config, fs::path pcmDir, std::string target, const std::string& march, const std::string& flags);
void 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::vector<ClangError> 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);
}; };
class Module { class Module {
@ -60,7 +62,7 @@ export namespace Crafter::Build {
const fs::path path; const fs::path path;
Module(const std::string& name, const fs::path& path, const Configuration& config, const fs::path& pcmDir, std::string& files, const fs::path& buildDir); Module(const std::string& name, const fs::path& path, const Configuration& config, const fs::path& pcmDir, std::string& files, const fs::path& buildDir);
void Check(); void Check();
void Compile(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::vector<ClangError> Compile(std::string clangDir, const Configuration& config, fs::path pcmDir, std::string target, const std::string& march, const std::string& flags, const fs::path& buildDir);
static std::vector<Module> GetModules(std::string clangDir, const Configuration& config, fs::path pcmDir, std::string target, const std::string& march, const std::string& flags, std::string& files, const fs::path& buildDir); static std::tuple<std::vector<Module>, std::vector<ClangError>> GetModules(std::string clangDir, const Configuration& config, fs::path pcmDir, std::string target, const std::string& march, const std::string& flags, std::string& files, const fs::path& buildDir);
}; };
} }

View file

@ -31,6 +31,7 @@ module;
#include <glslang/SPIRV/GlslangToSpv.h> #include <glslang/SPIRV/GlslangToSpv.h>
#include <regex> #include <regex>
#include <mutex> #include <mutex>
#include <tuple>
module Crafter.Build; module Crafter.Build;
using namespace Crafter::Build; using namespace Crafter::Build;
namespace fs = std::filesystem; namespace fs = std::filesystem;
@ -39,45 +40,42 @@ Project::Project(std::string name, fs::path path, std::vector<Configuration> con
} }
const Configuration& Project::Build(std::string configuration) { std::tuple<Configuration&, std::vector<ClangError>> Project::Build(std::string configuration) {
for(Configuration& config : configurations) { for(Configuration& config : configurations) {
if(config.name == configuration){ if(config.name == configuration){
Build(config); return {config, Build(config)};
return config;
} }
} }
throw std::runtime_error("Configuration: " + configuration + " not found."); throw std::runtime_error("Configuration: " + configuration + " not found.");
} }
const Configuration& Project::Build(std::string configuration, fs::path outputDir) { std::tuple<Configuration&, std::vector<ClangError>> Project::Build(std::string configuration, fs::path outputDir) {
for(Configuration& config : configurations) { for(Configuration& config : configurations) {
if(config.name == configuration){ if(config.name == configuration){
Build(config, outputDir); return {config, Build(config, outputDir)};
return config;
} }
} }
throw std::runtime_error("Configuration: " + configuration + " not found."); throw std::runtime_error("Configuration: " + configuration + " not found.");
} }
const Configuration& Project::Build(std::string configuration, fs::path outputDir, fs::path binDir) { std::tuple<Configuration&, std::vector<ClangError>> Project::Build(std::string configuration, fs::path outputDir, fs::path binDir) {
for(Configuration& config : configurations) { for(Configuration& config : configurations) {
if(config.name == configuration){ if(config.name == configuration){
Build(config, outputDir, binDir); return {config, Build(config, outputDir, binDir)};
return config;
} }
} }
throw std::runtime_error("Configuration: " + configuration + " not found."); throw std::runtime_error("Configuration: " + configuration + " not found.");
} }
void Project::Build(Configuration& configuration) { std::vector<ClangError> Project::Build(Configuration& configuration) {
Build(configuration, configuration.outputDir); return Build(configuration, configuration.outputDir);
} }
void Project::Build(Configuration& config, fs::path outputDir) { std::vector<ClangError> Project::Build(Configuration& config, fs::path outputDir) {
Build(config, outputDir, outputDir); return Build(config, outputDir, outputDir);
} }
void Project::Build(Configuration& config, fs::path outputDir, fs::path binDir) { std::vector<ClangError> Project::Build(Configuration& config, fs::path outputDir, fs::path binDir) {
if(config.standard.empty()) { if(config.standard.empty()) {
config.standard = "c++26"; config.standard = "c++26";
} }
@ -161,13 +159,16 @@ void Project::Build(Configuration& config, fs::path outputDir, fs::path binDir)
if (depLibSet.insert(project.name).second) { if (depLibSet.insert(project.name).second) {
libs+=std::format(" -l{}", project.name); libs+=std::format(" -l{}", project.name);
} }
const Configuration& depConfig = project.Build(config.dependencies[i].configuration, pcmDir, binDir); std::tuple<Configuration&, std::vector<ClangError>> depConfig = project.Build(config.dependencies[i].configuration, pcmDir, binDir);
for(const std::string& lib2 : depConfig.libs) { if(std::get<1>(depConfig).size() > 0) {
return std::get<1>(depConfig);
}
for(const std::string& lib2 : std::get<0>(depConfig).libs) {
if (depLibSet.insert(lib2).second) { if (depLibSet.insert(lib2).second) {
libs+=std::format(" -l{}", lib2); libs+=std::format(" -l{}", lib2);
} }
} }
for(const Dependency& dep2 : depConfig.dependencies) { for(const Dependency& dep2 : std::get<0>(depConfig).dependencies) {
if (depLibSet.insert(dep2.name).second) { if (depLibSet.insert(dep2.name).second) {
libs+=std::format(" -l{}", dep2.name); libs+=std::format(" -l{}", dep2.name);
} }
@ -179,13 +180,16 @@ void Project::Build(Configuration& config, fs::path outputDir, fs::path binDir)
if (depLibSet.insert(project.name).second) { if (depLibSet.insert(project.name).second) {
libs+=std::format(" -l{}", project.name); libs+=std::format(" -l{}", project.name);
} }
const Configuration& depConfig = project.Build(config.dependencies[i].configuration, pcmDir, binDir); std::tuple<Configuration&, std::vector<ClangError>> depConfig = project.Build(config.dependencies[i].configuration, pcmDir, binDir);
for(const std::string& lib2 : depConfig.libs) { if(std::get<1>(depConfig).size() > 0) {
if (depLibSet.insert(lib2).second) { return std::get<1>(depConfig);
}
for(const std::string& lib2 : std::get<0>(depConfig).libs) {
if (depLibSet.insert(lib2).second) {
libs+=std::format(" -l{}", lib2); libs+=std::format(" -l{}", lib2);
} }
} }
for(const Dependency& dep2 : depConfig.dependencies) { for(const Dependency& dep2 : std::get<0>(depConfig).dependencies) {
if (depLibSet.insert(dep2.name).second) { if (depLibSet.insert(dep2.name).second) {
libs+=std::format(" -l{}", dep2.name); libs+=std::format(" -l{}", dep2.name);
} }
@ -229,17 +233,24 @@ void Project::Build(Configuration& config, fs::path outputDir, fs::path binDir)
} }
std::string files; std::string files;
std::vector<Module> modules = Module::GetModules(clangDir, config, pcmDir, target, march, flags, files, buildDir); std::tuple<std::vector<Module>, std::vector<ClangError>> modules = Module::GetModules(clangDir, config, pcmDir, target, march, flags, files, buildDir);
if(std::get<1>(modules).size() > 0) {
return std::get<1>(modules);
}
std::vector<ClangError> errors = Source::GetSourceFiles(clangDir, config, pcmDir, target, march, flags, std::get<0>(modules), files, buildDir);
if(errors.size() > 0) {
return errors;
}
std::vector<std::thread> threads; std::vector<std::thread> threads;
Source::GetSourceFiles(clangDir, config, pcmDir, target, march, flags, threads, modules, files, buildDir);
for(std::uint_fast32_t i = 0; i < config.c_files.size(); i++) { for(std::uint_fast32_t i = 0; i < config.c_files.size(); i++) {
files+=std::format("{}_source.o ",(buildDir/config.c_files[i].filename()).generic_string()); files+=std::format("{}_source.o ",(buildDir/config.c_files[i].filename()).generic_string());
if(!fs::exists((buildDir/config.c_files[i].filename()).generic_string()+"_source.o") || fs::last_write_time(config.c_files[i].generic_string()+".c") > fs::last_write_time((buildDir/config.c_files[i].filename()).generic_string()+"_source.o")) { if(!fs::exists((buildDir/config.c_files[i].filename()).generic_string()+"_source.o") || fs::last_write_time(config.c_files[i].generic_string()+".c") > fs::last_write_time((buildDir/config.c_files[i].filename()).generic_string()+"_source.o")) {
threads.emplace_back([i, &config, pcmDir, target, clangDir, flags, march, &buildDir](){ threads.emplace_back([i, &config, pcmDir, target, clangDir, flags, march, &buildDir](){
BounceCommand(std::format("clang {}.c -c -O{} {} {} -o {}_source.o {}", config.c_files[i].generic_string(), config.optimizationLevel, march, flags, (buildDir/config.c_files[i].filename()).generic_string(), target).c_str()); RunCommand(std::format("clang {}.c -c -O{} {} {} -o {}_source.o {}", config.c_files[i].generic_string(), config.optimizationLevel, march, flags, (buildDir/config.c_files[i].filename()).generic_string(), target).c_str());
}); });
} }
} }
@ -249,19 +260,18 @@ void Project::Build(Configuration& config, fs::path outputDir, fs::path binDir)
} }
if(config.type == "executable"){ if(config.type == "executable"){
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); std::string command = std::format("{} {} {}-O{} -o {} {} {} -fuse-ld=lld", clangDir, flags, files, config.optimizationLevel, (outputDir/name).generic_string(), target, libs);
if(config.verbose) { if(config.verbose) {
std::cout << command << std::endl; std::cout << command << std::endl;
} }
BounceCommand(command.c_str()); std::vector<ClangError> errors = RunClang(command);
if(errors.size() > 0) {
return errors;
}
} else if(config.type == "library"){ } else if(config.type == "library"){
BounceCommandIgnore(std::format("ar r {}.a {}", (outputDir/fs::path("lib"+name)).generic_string(), files).c_str()); RunCommandIgnore(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"){
BounceCommandIgnore(std::format("ar r {}.so {}", (outputDir/fs::path("lib"+name)).generic_string(), files).c_str()); RunCommandIgnore(std::format("ar r {}.so {}", (outputDir/fs::path("lib"+name)).generic_string(), files).c_str());
} }
for(const fs::path& additionalFile : config.additionalFiles){ for(const fs::path& additionalFile : config.additionalFiles){
@ -272,6 +282,7 @@ void Project::Build(Configuration& config, fs::path outputDir, fs::path binDir)
fs::copy(additionalFile, binDir); fs::copy(additionalFile, binDir);
} }
} }
return {};
} }
Project Project::LoadFromJSON(fs::path path) { Project Project::LoadFromJSON(fs::path path) {

View file

@ -22,8 +22,10 @@ module;
#include <vector> #include <vector>
#include <string> #include <string>
#include <filesystem> #include <filesystem>
#include <tuple>
export module Crafter.Build:Project; export module Crafter.Build:Project;
import :Configuration; import :Configuration;
import :Bounce;
namespace fs = std::filesystem; namespace fs = std::filesystem;
export namespace Crafter::Build { export namespace Crafter::Build {
@ -33,12 +35,12 @@ export namespace Crafter::Build {
fs::path path; fs::path path;
std::vector<Configuration> configurations; std::vector<Configuration> configurations;
Project(std::string name, fs::path path, std::vector<Configuration> configurations); Project(std::string name, fs::path path, std::vector<Configuration> configurations);
const Configuration& Build(std::string configuration); std::tuple<Configuration&, std::vector<ClangError>> Build(std::string configuration);
const Configuration& Build(std::string configuration, fs::path outputDir); std::tuple<Configuration&, std::vector<ClangError>> Build(std::string configuration, fs::path outputDir);
const Configuration& Build(std::string configuration, fs::path outputDir, fs::path binDir); std::tuple<Configuration&, std::vector<ClangError>> Build(std::string configuration, fs::path outputDir, fs::path binDir);
void Build(Configuration& configuration); std::vector<ClangError> Build(Configuration& configuration);
void Build(Configuration& configuration, fs::path outputDir); std::vector<ClangError> Build(Configuration& configuration, fs::path outputDir);
void Build(Configuration& configuration, fs::path outputDir, fs::path binDir); std::vector<ClangError> Build(Configuration& configuration, fs::path outputDir, fs::path binDir);
void SaveToJSON(fs::path path); void SaveToJSON(fs::path path);
static Project LoadFromJSON(fs::path path); static Project LoadFromJSON(fs::path path);
}; };

View file

@ -25,28 +25,41 @@ module;
#include <iostream> #include <iostream>
#include <regex> #include <regex>
#include <print> #include <print>
#include <mutex>
#include <execution> #include <execution>
module Crafter.Build; module Crafter.Build;
using namespace Crafter::Build; using namespace Crafter::Build;
namespace fs = std::filesystem; 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::vector<ClangError> Source::GetSourceFiles(std::string clangDir, const Configuration& config, fs::path pcmDir, std::string target, const std::string& march, const std::string& flags, const std::vector<Module>& modules, std::string& files, const fs::path& buildDir) {
std::string defines; std::string defines;
for(const Define& define : config.defines) { for(const Define& define : config.defines) {
defines+=define.ToString(); defines+=define.ToString();
} }
std::vector<std::thread> threads;
std::mutex errorMutex;
std::vector<ClangError> errors;
for(const fs::path& sourceFile : config.sourceFiles) { for(const fs::path& sourceFile : config.sourceFiles) {
files+=std::format("{}_source.o ",(buildDir/sourceFile.filename()).generic_string()); files+=std::format("{}_source.o ",(buildDir/sourceFile.filename()).generic_string());
if(Source::Check(sourceFile, modules, config, buildDir)) { if(Source::Check(sourceFile, modules, config, buildDir)) {
threads.emplace_back([&config, sourceFile, pcmDir, target, clangDir, flags, march, buildDir, defines](){ threads.emplace_back([&config, sourceFile, pcmDir, target, clangDir, flags, march, buildDir, defines, &errors, &errorMutex]() {
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); 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) { if(config.verbose) {
std::cout << command << std::endl; std::cout << command << std::endl;
} }
BounceCommand(command.c_str()); std::vector<ClangError> newErrors = RunClang(command);
if(newErrors.size() > 0) {
errorMutex.lock();
errors.insert(errors.end(), newErrors.begin(), newErrors.end());
errorMutex.unlock();
}
}); });
} }
} }
for(std::thread& thread : threads){
thread.join();
}
return errors;
} }
bool Source::Check(const fs::path& path, const std::vector<Module>& modules, const Configuration& config, const fs::path& buildDir) { bool Source::Check(const fs::path& path, const std::vector<Module>& modules, const Configuration& config, const fs::path& buildDir) {

View file

@ -35,7 +35,7 @@ namespace fs = std::filesystem;
namespace Crafter::Build { namespace Crafter::Build {
class Source { class Source {
public: public:
static void 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); static std::vector<ClangError> GetSourceFiles(std::string clangDir, const Configuration& config, fs::path pcmDir, std::string target, const std::string& march, const std::string& flags, const std::vector<Module>& modules, std::string& files, const fs::path& buildDir);
private: private:
static bool Check(const fs::path& path, const std::vector<Module>& modules, const Configuration& config, const fs::path& buildDir); static bool Check(const fs::path& path, const std::vector<Module>& modules, const Configuration& config, const fs::path& buildDir);
}; };

View file

@ -1,6 +1,7 @@
mkdir build mkdir build
mkdir bin mkdir bin
clang++ -std=c++26 Crafter.Build-Bounce.cppm --precompile -fprebuilt-module-path=./build -o ./build/Crafter.Build-Bounce.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-Shader.cppm --precompile -fprebuilt-module-path=./build -o ./build/Crafter.Build-Shader.pcm
clang++ -std=c++26 Crafter.Build-Dependency.cppm --precompile -fprebuilt-module-path=./build -o ./build/Crafter.Build-Dependency.pcm clang++ -std=c++26 Crafter.Build-Dependency.cppm --precompile -fprebuilt-module-path=./build -o ./build/Crafter.Build-Dependency.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-Configuration.cppm --precompile -fprebuilt-module-path=./build -o ./build/Crafter.Build-Configuration.pcm
@ -17,6 +18,7 @@ clang++ -std=c++26 Crafter.Build-Shader.cpp -fprebuilt-module-path=./build -c -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-Bounce.pcm -fprebuilt-module-path=./build -c -O3 -o ./build/Crafter.Build-Bounce.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
@ -24,6 +26,6 @@ clang++ -std=c++26 ./build/Crafter.Build-SourceFile.pcm -fprebuilt-module-path=.
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-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-SourceFile_source.o ./build/Crafter.Build-SourceFile.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 -L/usr/local/lib -L/usr/lib/ -lvulkan -lMachineIndependent -lOSDependent -lGenericCodeGen -lglslang -lglslang-default-resource-limits -lSPIRV -lSPVRemapper -ltbb -fuse-ld=lld clang++ ./build/main.o ./build/Crafter.Build-ModuleFile_source.o ./build/Crafter.Build-Bounce.o ./build/Crafter.Build-ModuleFile.o ./build/Crafter.Build-SourceFile_source.o ./build/Crafter.Build-SourceFile.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 -L/usr/local/lib -L/usr/lib/ -lvulkan -lMachineIndependent -lOSDependent -lGenericCodeGen -lglslang -lglslang-default-resource-limits -lSPIRV -lSPVRemapper -ltbb -fuse-ld=lld
rm -rf build rm -rf build

View file

@ -20,6 +20,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include <cstdint> #include <cstdint>
#include <print> #include <print>
#include <tuple>
#include <iostream>
#include "json.hpp" #include "json.hpp"
import Crafter.Build; import Crafter.Build;
using namespace Crafter::Build; using namespace Crafter::Build;
@ -58,11 +60,22 @@ int main(int argc, char* argv[]) {
projectPath = filepath; projectPath = filepath;
} }
std::vector<ClangError> errors;
Project project = Project::LoadFromJSON(projectPath); Project project = Project::LoadFromJSON(projectPath);
if(outputDir.empty()){ if(outputDir.empty()){
project.Build(configuration); errors = std::get<1>(project.Build(configuration));
} else{ } else{
project.Build(configuration, fs::path(outputDir)); errors = std::get<1>(project.Build(configuration, fs::path(outputDir)));
}
if(errors.size() > 0){
for (const ClangError& error : errors) {
std::cout << "Filename: " << error.filename << std::endl;
std::cout << "Line: " << error.line_number << std::endl;
std::cout << "Error Message: " << error.error_message << std::endl;
std::cout << "Code: " << error.code << std::endl << std::endl;
}
return 0;
} }
if(run){ if(run){