From 0819baf6d323c94f38b8c1f416a9c597597f1d73 Mon Sep 17 00:00:00 2001 From: Jorijn van der Graaf Date: Sun, 16 Nov 2025 18:44:41 +0100 Subject: [PATCH] fixed recursive libs --- .../Crafter.Build-Configuration.cpp | 41 +++- .../Crafter.Build-Implementation.cpp | 2 +- implementations/Crafter.Build-Project.cpp | 212 +++++++++++------- implementations/Crafter.Build-Test.cpp | 2 +- implementations/main.cpp | 7 +- interfaces/Crafter.Build-Configuration.cppm | 17 +- interfaces/Crafter.Build-Project.cppm | 3 +- interfaces/Crafter.Build-Test.cppm | 3 +- 8 files changed, 170 insertions(+), 117 deletions(-) diff --git a/implementations/Crafter.Build-Configuration.cpp b/implementations/Crafter.Build-Configuration.cpp index 8e4aee9..5f86f0f 100644 --- a/implementations/Crafter.Build-Configuration.cpp +++ b/implementations/Crafter.Build-Configuration.cpp @@ -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(-1); debug = static_cast(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() == extendName) { - SetDataFromJson(configs, it, workingDir); + SetDataFromJson(configs, it, workingDir, project); } } } @@ -213,6 +214,11 @@ namespace Crafter { shaders.emplace_back(workingDir / it["path"].get(), it["entrypoint"].get(), static_cast(it["type"].get())); } } + if(config.contains("c_files")) { + for (auto it : config["c_files"]) { + c_files.push_back(workingDir / it.get()); + } + } if(config.contains("defines")) { for (auto it : config["defines"]) { defines.emplace_back(it["name"].get(), it["value"].get()); @@ -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(); + fs::path path = it["path"].get(); + std::string configName = it["configuration"].get(); + 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()).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()).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(); - } - dependencies.emplace_back(it["path"].get(), it["configuration"].get(), std::move(commit), std::move(branch)); + std::unique_ptr depProject = std::make_unique(std::move(path), configName); + dependencies.emplace_back(std::move(depProject), depProject->configurations[0]); } } } diff --git a/implementations/Crafter.Build-Implementation.cpp b/implementations/Crafter.Build-Implementation.cpp index 0db5cda..8c6ed17 100644 --- a/implementations/Crafter.Build-Implementation.cpp +++ b/implementations/Crafter.Build-Implementation.cpp @@ -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())); } } diff --git a/implementations/Crafter.Build-Project.cpp b/implementations/Crafter.Build-Project.cpp index 61651f5..914d630 100644 --- a/implementations/Crafter.Build-Project.cpp +++ b/implementations/Crafter.Build-Project.cpp @@ -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(); + + this->path.remove_filename(); + + nlohmann::json configs = data["configurations"]; + nlohmann::json testJson = data["tests"]; + + if(data.contains("bin_dir")) { + binDir = data["bin_dir"].get(); + } else { + binDir = "bin"; + } + if(data.contains("build_dir")) { + buildDir = data["build_dir"].get(); + } 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(); + + this->path.remove_filename(); + + nlohmann::json configs = data["configurations"]; + + if(data.contains("bin_dir")) { + binDir = data["bin_dir"].get(); + } else { + binDir = "bin"; + } + if(data.contains("build_dir")) { + buildDir = data["build_dir"].get(); + } 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() == 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&& configurations) : name(std::move(name)), path(std::move(path)), configurations(std::move(configurations)) {} Project::Project(std::string&& name, fs::path&& path, std::vector&& 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 depLibSet, Configuration& depConfig) { + for(const std::string& lib2 : depConfig.libs) { + if (depLibSet.insert(lib2).second) { + libsString+=std::format(" -l{}", lib2); + } + } + for(const std::tuple, 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 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(); - - fs::path workingDir = path; - workingDir.remove_filename(); - - std::vector configurations; - nlohmann::json configs = data["configurations"]; - std::vector 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(); - } else { - project.binDir = "bin"; - } - if(data.contains("build_dir")) { - project.buildDir = data["build_dir"].get(); - } else { - project.buildDir = "build"; - } - project.tests = std::move(tests); - return project; - } std::vector Project::RunTests() { std::vector 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}; } diff --git a/implementations/Crafter.Build-Test.cpp b/implementations/Crafter.Build-Test.cpp index 58f64f5..9fcace9 100644 --- a/implementations/Crafter.Build-Test.cpp +++ b/implementations/Crafter.Build-Test.cpp @@ -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; } } diff --git a/implementations/main.cpp b/implementations/main.cpp index 1c2bfc3..fcfcb51 100644 --- a/implementations/main.cpp +++ b/implementations/main.cpp @@ -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 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 { diff --git a/interfaces/Crafter.Build-Configuration.cppm b/interfaces/Crafter.Build-Configuration.cppm index 407d49e..5b9eb30 100644 --- a/interfaces/Crafter.Build-Configuration.cppm +++ b/interfaces/Crafter.Build-Configuration.cppm @@ -33,28 +33,21 @@ namespace Crafter { Define(std::string&& name, std::string&& value): name(std::move(name)), value(std::move(value)) { } }; - export class Dependency { - public: - std::string path; - std::string configuration; - std::string commit; - std::string branch; - Dependency(std::string&& path, std::string&& configuration, std::string&& commit, std::string&& branch): path(std::move(path)), configuration(std::move(configuration)), commit(std::move(commit)), branch(std::move(branch)) { } - };; - export enum ConfigurationType { CRAFTER_CONFIGURATION_TYPE_EXECUTABLE, CRAFTER_CONFIGURATION_TYPE_LIBRARY, CRAFTER_CONFIGURATION_TYPE_SHARED_LIBRARY, }; + export class Project; export class Configuration { public: std::string name; std::string standard; std::vector> interfaces; std::vector implementations; - std::vector dependencies; + std::vector c_files; + std::vector, Configuration&>> dependencies; std::vector shaders; std::vector additionalFiles; std::vector defines; @@ -64,7 +57,7 @@ namespace Crafter { bool debug; std::vector libs; Configuration(std::string&& name); - Configuration(const nlohmann::json& configs, const nlohmann::json& config, fs::path workingDir); - void SetDataFromJson(const nlohmann::json& configs, const nlohmann::json& config, fs::path workingDir); + Configuration(const nlohmann::json& configs, const nlohmann::json& config, fs::path workingDir, const Project& project); + void SetDataFromJson(const nlohmann::json& configs, const nlohmann::json& config, fs::path workingDir, const Project& project); }; } diff --git a/interfaces/Crafter.Build-Project.cppm b/interfaces/Crafter.Build-Project.cppm index 06b3209..a072d0e 100644 --- a/interfaces/Crafter.Build-Project.cppm +++ b/interfaces/Crafter.Build-Project.cppm @@ -37,9 +37,10 @@ namespace Crafter { fs::path path; std::vector configurations; std::vector tests; + Project(fs::path&& path); + Project(fs::path&& path, const std::string_view config); Project(std::string&& name, fs::path&& path, std::vector&& configurations); Project(std::string&& name, fs::path&& path, std::vector&& configurations, fs::path&& buildDir, fs::path&& binDir); - static Project LoadFromJSON(const fs::path& path); std::tuple Build(std::string_view configuration); std::tuple Build(std::string_view configuration, const fs::path& binDir, const fs::path& outputDir, const fs::path& buildDir, std::string outputName); BuildResult Build(Configuration& configuration) const; diff --git a/interfaces/Crafter.Build-Test.cppm b/interfaces/Crafter.Build-Test.cppm index f292665..5f94437 100644 --- a/interfaces/Crafter.Build-Test.cppm +++ b/interfaces/Crafter.Build-Test.cppm @@ -30,10 +30,11 @@ namespace Crafter { std::string message; }; + export class Project; export class Test { public: Configuration config; Test(Configuration&& name); - Test(const nlohmann::json& configs, const nlohmann::json& config, const fs::path& workingDir); + Test(const nlohmann::json& configs, const nlohmann::json& config, const fs::path& workingDir, const Project& project); }; }