fixed recursive libs
Some checks failed
demo.yaml / fixed recursive libs (push) Failing after 0s

This commit is contained in:
Jorijn van der Graaf 2025-11-16 18:44:41 +01:00
commit 0819baf6d3
8 changed files with 170 additions and 117 deletions

View file

@ -22,6 +22,7 @@ module;
module Crafter.Build:Configuration_impl;
import :Configuration;
import std;
import :Project;
//import :Dependency;
import :Shader;
import :Module;
@ -32,11 +33,11 @@ namespace Crafter {
Configuration::Configuration(std::string&& name) : name(std::move(name)) {
}
Configuration::Configuration(const nlohmann::json& configs, const nlohmann::json& config, fs::path workingDir) {
SetDataFromJson(configs, config, workingDir);
Configuration::Configuration(const nlohmann::json& configs, const nlohmann::json& config, fs::path workingDir, const Project& project) {
SetDataFromJson(configs, config, workingDir, project);
}
void Configuration::SetDataFromJson(const nlohmann::json& configs, const nlohmann::json& config, fs::path workingDir) {
void Configuration::SetDataFromJson(const nlohmann::json& configs, const nlohmann::json& config, fs::path workingDir, const Project& project) {
type = static_cast<ConfigurationType>(-1);
debug = static_cast<bool>(2);
if(config.contains("extends")) {
@ -44,7 +45,7 @@ namespace Crafter {
for(const std::string& extendName : extends) {
for (auto it : configs) {
if(it["name"].get<std::string>() == extendName) {
SetDataFromJson(configs, it, workingDir);
SetDataFromJson(configs, it, workingDir, project);
}
}
}
@ -213,6 +214,11 @@ namespace Crafter {
shaders.emplace_back(workingDir / it["path"].get<std::string>(), it["entrypoint"].get<std::string>(), static_cast<EShLanguage>(it["type"].get<std::uint32_t>()));
}
}
if(config.contains("c_files")) {
for (auto it : config["c_files"]) {
c_files.push_back(workingDir / it.get<std::string>());
}
}
if(config.contains("defines")) {
for (auto it : config["defines"]) {
defines.emplace_back(it["name"].get<std::string>(), it["value"].get<std::string>());
@ -226,15 +232,26 @@ namespace Crafter {
}
if(config.contains("dependencies")) {
for (auto it : config["dependencies"]) {
std::string commit;
std::string branch;
if(it.contains("commit")){
commit = it["commit"].get<std::string>();
fs::path path = it["path"].get<std::string>();
std::string configName = it["configuration"].get<std::string>();
if(path.string().ends_with(".git")) {
fs::path name = path.filename();
name.replace_extension();
if(!fs::exists(project.buildDir/name)) {
if(it.contains("branch")) {
system(std::format("cd {} && git clone {} && cd {} && git switch {}",project.buildDir.string(), path.string(), (project.buildDir/name).string(), it["branch"].get<std::string>()).c_str());
} else if(it.contains("commit")){
system(std::format("cd {} && git clone {} && cd {} && git checkout {}", project.buildDir.string(), path.string(), (project.buildDir/name).string(), it["commit"].get<std::string>()).c_str());
} else {
system(std::format("cd {} && git clone {}", project.buildDir.string(), path.string()).c_str());
}
} else if(!it.contains("commit")) {
system(std::format("cd {} && git pull", (project.buildDir/name).string()).c_str());
}
path = project.buildDir/name/"project.json";
}
if(it.contains("branch")){
branch = it["branch"].get<std::string>();
}
dependencies.emplace_back(it["path"].get<std::string>(), it["configuration"].get<std::string>(), std::move(commit), std::move(branch));
std::unique_ptr<Project> depProject = std::make_unique<Project>(std::move(path), configName);
dependencies.emplace_back(std::move(depProject), depProject->configurations[0]);
}
}
}

View file

@ -62,6 +62,6 @@ namespace Crafter {
}
}
}
return RunClang(std::format("{} {}.cpp -c -o {}_impl.o", clang, path.string(), (buildDir/path.filename()).string()));
result = RunClang(std::format("{} {}.cpp -c -o {}_impl.o", clang, path.string(), (buildDir/path.filename()).string()));
}
}

View file

@ -28,6 +28,96 @@ import :Command;
namespace fs = std::filesystem;
namespace Crafter {
Project::Project(fs::path&& path) : path(std::move(path)) {
if (!fs::exists(this->path)) {
throw std::runtime_error(std::format("Project file: {} not found.", this->path.generic_string()));
}
std::ifstream f(this->path);
nlohmann::json data = nlohmann::json::parse(f);
name = data["name"].get<std::string>();
this->path.remove_filename();
nlohmann::json configs = data["configurations"];
nlohmann::json testJson = data["tests"];
if(data.contains("bin_dir")) {
binDir = data["bin_dir"].get<std::string>();
} else {
binDir = "bin";
}
if(data.contains("build_dir")) {
buildDir = data["build_dir"].get<std::string>();
} else {
buildDir = "build";
}
if (!fs::exists(binDir)) {
fs::create_directories(binDir);
}
if (!fs::exists(buildDir)) {
fs::create_directories(buildDir);
}
for (nlohmann::json::iterator it = configs.begin(); it != configs.end(); ++it) {
configurations.emplace_back(configs, (*it), this->path, *this);
}
for (nlohmann::json::iterator it = testJson.begin(); it != testJson.end(); ++it) {
tests.emplace_back(configs, (*it), this->path, *this);
}
}
Project::Project(fs::path&& path, const std::string_view config) : path(std::move(path)) {
if (!fs::exists(this->path)) {
throw std::runtime_error(std::format("Project file: {} not found.", path.generic_string()));
}
std::ifstream f(this->path);
nlohmann::json data = nlohmann::json::parse(f);
name = data["name"].get<std::string>();
this->path.remove_filename();
nlohmann::json configs = data["configurations"];
if(data.contains("bin_dir")) {
binDir = data["bin_dir"].get<std::string>();
} else {
binDir = "bin";
}
if(data.contains("build_dir")) {
buildDir = data["build_dir"].get<std::string>();
} else {
buildDir = "build";
}
if (!fs::exists(binDir)) {
fs::create_directories(binDir);
}
if (!fs::exists(buildDir)) {
fs::create_directories(buildDir);
}
for (nlohmann::json::iterator it = configs.begin(); it != configs.end(); ++it) {
if(it->contains("name")) {
if((*it)["name"].get<std::string>() == config) {
configurations.emplace_back(configs, (*it), this->path, *this);
goto errorSkip;
}
} else {
throw std::runtime_error("Invalid config json, name field is missing");
}
}
throw std::runtime_error(std::format("Config {} not found, requested as dependency", config));
errorSkip:;
}
Project::Project(std::string&& name, fs::path&& path, std::vector<Configuration>&& configurations) : name(std::move(name)), path(std::move(path)), configurations(std::move(configurations)) {}
Project::Project(std::string&& name, fs::path&& path, std::vector<Configuration>&& configurations, fs::path&& binDir, fs::path&& buildDir) : name(std::move(name)), path(std::move(path)), configurations(std::move(configurations)), binDir(std::move(binDir)), buildDir(std::move(buildDir)) {}
@ -51,6 +141,22 @@ namespace Crafter {
BuildResult Project::Build(Configuration& config) const {
return Build(config, binDir/config.name, binDir/config.name, buildDir/config.name, name);
}
void AddLibsRecursive(std::string& libsString, std::unordered_set<std::string> depLibSet, Configuration& depConfig) {
for(const std::string& lib2 : depConfig.libs) {
if (depLibSet.insert(lib2).second) {
libsString+=std::format(" -l{}", lib2);
}
}
for(const std::tuple<std::shared_ptr<Project>, Configuration&>& dep2 : depConfig.dependencies) {
std::string outputLib = std::get<0>(dep2)->name+std::get<1>(dep2).name;
if (depLibSet.insert(outputLib).second) {
libsString+=std::format(" -l{}", outputLib);
}
AddLibsRecursive(libsString, depLibSet, std::get<1>(dep2));
}
}
BuildResult Project::Build(Configuration& config, const fs::path& binDir, const fs::path& outputDir, const fs::path& buildDir, std::string outputName) const {
BuildResult buildResult;
if (!fs::exists(binDir)) {
@ -193,55 +299,20 @@ namespace Crafter {
for(std::uint_fast32_t i = 0; i < depThreads.size(); i++) {
depThreads[i] = std::thread([i, &config, &libMutex, &depLibSet, &buildDir, &pcmDir, &libsString, &binDir, this, &buildResult, &resultsDep](){
if(config.dependencies[i].path.ends_with(".git")) {
fs::path name = fs::path(config.dependencies[i].path).filename();
name.replace_extension();
if(!fs::exists(buildDir/name)) {
if(!config.dependencies[i].branch.empty()) {
system(std::format("cd {} && git clone {} && cd {} && git switch {}", buildDir.string(), config.dependencies[i].path, (buildDir/name).string(), config.dependencies[i].branch).c_str());
} else if(!config.dependencies[i].commit.empty()){
system(std::format("cd {} && git clone {} && cd {} && git checkout {}", buildDir.string(), config.dependencies[i].path, (buildDir/name).string(), config.dependencies[i].commit).c_str());
} else {
system(std::format("cd {} && git clone {}", buildDir.string(), config.dependencies[i].path).c_str());
}
} else if(config.dependencies[i].commit.empty()) {
system(std::format("cd {} && git pull", (buildDir/name).string()).c_str());
}
config.dependencies[i].path = buildDir/name/"project.json";
std::string outputLib = std::get<0>(config.dependencies[i])->name+std::get<1>(config.dependencies[i]).name;
BuildResult depResult = std::get<0>(config.dependencies[i])->Build(std::get<1>(config.dependencies[i]), pcmDir, binDir, buildDir/std::get<0>(config.dependencies[i])->name/std::get<0>(config.dependencies[i])->buildDir, outputLib);
libMutex.lock();
if(depResult.repack) {
buildResult.repack = true;
}
if(fs::path(config.dependencies[i].path).is_relative()) {
config.dependencies[i].path = this->path/config.dependencies[i].path;
}
Project project = Project::LoadFromJSON(config.dependencies[i].path);
for(Configuration& depConfig : project.configurations) {
if(depConfig.name == config.dependencies[i].configuration){
fs::path depBuildDir = fs::path(config.dependencies[i].path).parent_path()/project.buildDir/depConfig.name;
BuildResult depResult = project.Build(depConfig, pcmDir, binDir, depBuildDir, project.name);
libMutex.lock();
if(depResult.repack) {
buildResult.repack = true;
}
resultsDep[i] = depResult.errors;
resultsDep[i] = depResult.errors;
if (depLibSet.insert(project.name).second) {
libsString+=std::format(" -l{}", project.name);
}
for(const std::string& lib2 : depConfig.libs) {
if (depLibSet.insert(lib2).second) {
libsString+=std::format(" -l{}", lib2);
}
}
for(const Dependency& dep2 : depConfig.dependencies) {
if (depLibSet.insert(project.name).second) {
libsString+=std::format(" -l{}", project.name);
}
}
libMutex.unlock();
return;
}
if (depLibSet.insert(outputLib).second) {
libsString+=std::format(" -l{}", outputLib);
}
throw std::runtime_error(std::format("Configuration: {} not found.", config.dependencies[i].configuration));
AddLibsRecursive(libsString, depLibSet, std::get<1>(config.dependencies[i]));
libMutex.unlock();
});
}
@ -259,6 +330,15 @@ namespace Crafter {
}
std::string files;
for(const fs::path& cFile: config.c_files) {
files+=std::format("{}_source.o ",(buildDir/cFile.filename()).string());
if(!fs::exists((buildDir/cFile.filename()).string()+"_source.o") || fs::last_write_time(cFile.string()+".c") > fs::last_write_time((buildDir/cFile.filename()).string()+"_source.o")) {
threads.emplace_back(&RunClang, std::format("clang {}.c -c -o {}_source.o", cFile.string(), (buildDir/cFile.filename()).string()));
}
}
std::vector<std::string> resultInterfaces(config.interfaces.size());
for(uint_fast32_t i = 0; i < config.interfaces.size(); i++) {
@ -332,45 +412,6 @@ namespace Crafter {
return buildResult;
}
Project Project::LoadFromJSON(const fs::path& path) {
if (!fs::exists(path)) {
throw std::runtime_error(std::format("Project file: {} not found.", path.generic_string()));
}
std::ifstream f(path);
nlohmann::json data = nlohmann::json::parse(f);
std::string name = data["name"].get<std::string>();
fs::path workingDir = path;
workingDir.remove_filename();
std::vector<Configuration> configurations;
nlohmann::json configs = data["configurations"];
std::vector<Test> tests;
nlohmann::json testJson = data["tests"];
for (nlohmann::json::iterator it = configs.begin(); it != configs.end(); ++it) {
configurations.emplace_back(configs, (*it), workingDir);
}
for (nlohmann::json::iterator it = testJson.begin(); it != testJson.end(); ++it) {
tests.emplace_back(configs, (*it), workingDir);
}
Project project(std::move(name), std::move(workingDir), std::move(configurations));
if(data.contains("bin_dir")) {
project.binDir = data["bin_dir"].get<std::string>();
} else {
project.binDir = "bin";
}
if(data.contains("build_dir")) {
project.buildDir = data["build_dir"].get<std::string>();
} else {
project.buildDir = "build";
}
project.tests = std::move(tests);
return project;
}
std::vector<TestResult> Project::RunTests() {
std::vector<TestResult> results;
@ -396,6 +437,7 @@ namespace Crafter {
BuildResult buildResult = Build(test.config, binDir, binDir, buildDir, test.config.name);
if(!buildResult.errors.empty()) {
return {test.config.name, buildResult.errors};
}

View file

@ -28,7 +28,7 @@ namespace Crafter {
Test::Test(Configuration&& config) : config(std::move(config)) {
config.type = CRAFTER_CONFIGURATION_TYPE_SHARED_LIBRARY;
}
Test::Test(const nlohmann::json& configs, const nlohmann::json& config, const fs::path& workingDir): config(configs, config, workingDir) {
Test::Test(const nlohmann::json& configs, const nlohmann::json& config, const fs::path& workingDir, const Project& project): config(configs, config, workingDir, project) {
this->config.type = CRAFTER_CONFIGURATION_TYPE_SHARED_LIBRARY;
}
}

View file

@ -66,19 +66,18 @@ int main(int argc, char* argv[]) {
projectPath = filepath;
}
Project project = Project::LoadFromJSON(projectPath);
Project project(std::move(projectPath));
if(command == "build") {
std::tuple<Configuration&, BuildResult> config = project.Build(argument);
std::cout << "amogus" << std::endl;
if(std::get<1>(config).errors.empty()) {
if(run){
std::string binDir = std::format("{}/{}", project.binDir.string(), std::get<0>(config).name);
if(std::get<0>(config).debug) {
system(std::format("cd {} && ./{}", (fs::path(projectPath).parent_path()/binDir).string(), project.name).c_str());
system(std::format("cd {} && ./{}", (project.path.parent_path()/binDir).string(), project.name).c_str());
//system(std::format("cd {} && lldb -o run {}", (fs::path(projectPath).parent_path()/binDir).string(), project.name).c_str());
} else {
system(std::format("cd {} && ./{}", (fs::path(projectPath).parent_path()/binDir).string(), project.name).c_str());
system(std::format("cd {} && ./{}", (project.path.parent_path()/binDir).string(), project.name).c_str());
}
}
} else {