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

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