#include "../include/GlobalLib.hpp" #include "../include/FileUtil.hpp" #include "../backend/ninja/Ninja.hpp" #include "../include/Conf.hpp" using namespace std; namespace sibs { Result GlobalLib::validatePackageExists(const string &globalLibRootDir, const string &name) { string packageDir = globalLibRootDir + "/"; packageDir += name; FileType packageDirFileType = getFileType(packageDir.c_str()); switch(packageDirFileType) { case FileType::FILE_NOT_FOUND: { string errMsg = "Global lib dependency not found: "; errMsg += name; return Result::Err(errMsg); } case FileType::REGULAR: { string errMsg = "Corrupt library directory. "; errMsg += packageDir; errMsg += " is a file, expected it to be a directory"; return Result::Err(errMsg); } case FileType::DIRECTORY: { return Result::Ok(true); } default: { return Result::Err("Unexpected error!"); } } } const char *sourceFileExtensions[] = { "c", "cc", "cpp", "cxx" }; bool isSourceFile(tinydir_file *file) { if(!file->is_reg) return false; for(const char *sourceFileExtension : sourceFileExtensions) { if(_tinydir_strcmp(sourceFileExtension, file->extension) == 0) return true; } return false; } Result GlobalLib::getStaticLibsLinkerFlags(const string &globalLibRootDir, const string &name, const string &version, LinkerFlagCallbackFunc linkerFlagCallbackFunc) { Result packageExistsResult = validatePackageExists(globalLibRootDir, name); if(packageExistsResult.isErr()) return Result::Err(packageExistsResult.getErrMsg()); string packageDir = globalLibRootDir + "/"; packageDir += name; // TODO: Instead of checking if version is exact match, check if package has same major version // and same or newer minor version string foundVersion; walkDir(packageDir.c_str(), [&foundVersion, &version](tinydir_file *file) { if(file->is_dir) { //printf("version: %s\n", file->name); if(_tinydir_strcmp(version.c_str(), file->name) == 0) foundVersion = file->name; } }); if(foundVersion.empty()) return Result::Err("Global lib dependency found, but version doesn't match dependency version"); packageDir += "/"; packageDir += version; string projectConfFilePath = packageDir; projectConfFilePath += "/project.conf"; FileType projectConfFileType = getFileType(projectConfFilePath.c_str()); switch(projectConfFileType) { case FileType::FILE_NOT_FOUND: { string errMsg = "Global lib dependency found: "; errMsg += packageDir; errMsg += ", but it's missing a project.conf file"; return Result::Err(errMsg); } case FileType::DIRECTORY: { string errMsg = "Global lib dependency found: "; errMsg += packageDir; errMsg += ", but it's corrupt (Found directory instead of file)"; return Result::Err(errMsg); } } SibsConfig sibsConfig; Result result = Config::readFromFile(projectConfFilePath.c_str(), sibsConfig); if(result.isErr()) return Result::Err(result.getErrMsg()); if(sibsConfig.getPackageName().empty()) return Result::Err("project.conf is missing required field package.name"); if(sibsConfig.getPackageType() == PackageType::EXECUTABLE) { string errMsg = "The dependency "; errMsg += name; errMsg += " is an executable. Only libraries can be dependencies"; return Result::Err(errMsg); } backend::Ninja ninja(backend::Ninja::LibraryType::STATIC); walkDirFilesRecursive(packageDir.c_str(), [&ninja, &packageDir](tinydir_file *file) { if (isSourceFile(file)) { printf("Adding source file: %s\n", file->path + packageDir.size() + 1); ninja.addSourceFile(file->path + packageDir.size() + 1); } else { //printf("Ignoring non-source file: %s\n", file->path + packageDir.size() + 1); } }); if(ninja.getSourceFiles().empty()) { return Result::Ok(""); } else { // TODO: Create build path if it doesn't exist string debugBuildPath = packageDir + "/build/debug"; Result buildFileResult = ninja.createBuildFile(sibsConfig.getPackageName(), sibsConfig.getDependencies(), debugBuildPath.c_str(), linkerFlagCallbackFunc); if (buildFileResult.isErr()) return Result::Err(buildFileResult.getErrMsg()); Result buildResult = ninja.build(debugBuildPath.c_str()); if (buildResult.isErr()) return Result::Err(buildResult.getErrMsg()); string staticLibPath = debugBuildPath; staticLibPath += "/lib"; staticLibPath += name; staticLibPath += ".a"; linkerFlagCallbackFunc(staticLibPath); return Result::Ok(staticLibPath); } } }