From 91ab79f1475371e6e57d00f24f98bccb7749d15a Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sun, 14 Jan 2018 18:36:20 +0100 Subject: Add git dependencies --- src/GlobalLib.cpp | 158 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 119 insertions(+), 39 deletions(-) (limited to 'src/GlobalLib.cpp') diff --git a/src/GlobalLib.cpp b/src/GlobalLib.cpp index 3842388..eee37dd 100644 --- a/src/GlobalLib.cpp +++ b/src/GlobalLib.cpp @@ -5,6 +5,8 @@ #include "../include/curl.hpp" #include "../include/Archive.hpp" #include "../include/CmakeModule.hpp" +#include "../include/Dependency.hpp" +#include "../include/GitRepository.hpp" using namespace std; @@ -65,13 +67,13 @@ namespace sibs return _tinydir_strncmp(path, subPathOf.c_str(), subPathOf.size()) == 0; } - Result GlobalLib::getLibs(const std::vector &libs, const SibsConfig &parentConfig, const FileString &globalLibRootDir, LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallbackFunc, GlobalIncludeDirCallbackFunc globalIncludeDirCallback) + Result GlobalLib::getLibs(const std::vector &libs, const SibsConfig &parentConfig, const FileString &globalLibRootDir, LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallbackFunc, GlobalIncludeDirCallbackFunc globalIncludeDirCallback) { - for(const Dependency &globalLibDependency : libs) + for(PackageListDependency *globalLibDependency : libs) { - printf("Dependency %s is missing from pkg-config, trying global lib\n", globalLibDependency.name.c_str()); - Result globalLibLinkerFlagsResult = GlobalLib::getLibsLinkerFlags(parentConfig, globalLibRootDir, globalLibDependency.name, globalLibDependency.version, staticLinkerFlagCallbackFunc, dynamicLinkerFlagCallbackFunc, globalIncludeDirCallback); - if(globalLibLinkerFlagsResult.isErr()) + printf("Dependency %s is missing from pkg-config, trying global lib\n", globalLibDependency->name.c_str()); + Result globalLibLinkerFlagsResult = GlobalLib::getLibsLinkerFlags(parentConfig, globalLibRootDir, globalLibDependency->name, globalLibDependency->version, staticLinkerFlagCallbackFunc, dynamicLinkerFlagCallbackFunc, globalIncludeDirCallback); + if(!globalLibLinkerFlagsResult) { if(globalLibLinkerFlagsResult.getErrorCode() == GlobalLib::DependencyError::DEPENDENCY_NOT_FOUND || globalLibLinkerFlagsResult.getErrorCode() == GlobalLib::DependencyError::DEPENDENCY_VERSION_NO_MATCH) { @@ -86,16 +88,48 @@ namespace sibs // invalid package name/version. A check should be done if it is the name or version // that is invalid. Result downloadDependencyResult = GlobalLib::downloadDependency(globalLibDependency); - if(downloadDependencyResult.isErr()) + if(!downloadDependencyResult) return downloadDependencyResult; - globalLibLinkerFlagsResult = GlobalLib::getLibsLinkerFlags(parentConfig, globalLibRootDir, globalLibDependency.name, globalLibDependency.version, staticLinkerFlagCallbackFunc, dynamicLinkerFlagCallbackFunc, globalIncludeDirCallback); - if(globalLibLinkerFlagsResult.isErr()) - return Result::Err(globalLibLinkerFlagsResult); + globalLibLinkerFlagsResult = GlobalLib::getLibsLinkerFlags(parentConfig, globalLibRootDir, globalLibDependency->name, globalLibDependency->version, staticLinkerFlagCallbackFunc, dynamicLinkerFlagCallbackFunc, globalIncludeDirCallback); + if(!globalLibLinkerFlagsResult) + return globalLibLinkerFlagsResult; } else { - return Result::Err(globalLibLinkerFlagsResult); + return globalLibLinkerFlagsResult; + } + } + } + + for(GitDependency *gitDependency : parentConfig.getGitDependencies()) + { + Result gitLibLinkerFlagsResult = GlobalLib::getLibsLinkerFlags(parentConfig, globalLibRootDir, gitDependency, staticLinkerFlagCallbackFunc, dynamicLinkerFlagCallbackFunc, globalIncludeDirCallback); + if(!gitLibLinkerFlagsResult) + { + if(gitLibLinkerFlagsResult.getErrorCode() == GlobalLib::DependencyError::DEPENDENCY_NOT_FOUND) + { + printf("Dependency %s not found in global lib, trying to download from git\n", gitDependency->name.c_str()); + // TODO: Download several dependencies at the same time by adding them to a list + // and then iterate them and download them all using several threads. + // All dependecies should be downloaded at the same time, this includes dependencies of dependencies. + // If a dependency is missing, fail build BEFORE downloading dependencies and before compiling anything. + // You do not want to possibly wait several minutes only for build to fail when there is no compilation error. + + // TODO: If return error is invalid url, then the message should be converted to + // invalid package name/version. A check should be done if it is the name or version + // that is invalid. + Result downloadDependencyResult = GlobalLib::downloadDependency(gitDependency); + if(!downloadDependencyResult) + return downloadDependencyResult; + + gitLibLinkerFlagsResult = GlobalLib::getLibsLinkerFlags(parentConfig, globalLibRootDir, gitDependency, staticLinkerFlagCallbackFunc, dynamicLinkerFlagCallbackFunc, globalIncludeDirCallback); + if(!gitLibLinkerFlagsResult) + return gitLibLinkerFlagsResult; + } + else + { + return gitLibLinkerFlagsResult; } } } @@ -138,28 +172,53 @@ namespace sibs packageDir += TINYDIR_STRING("/"); packageDir += versionPlatformNative; + return GlobalLib::getLibsLinkerFlagsCommon(parentConfig, packageDir, name, staticLinkerFlagCallbackFunc, dynamicLinkerFlagCallbackFunc, globalIncludeDirCallback); + } + + Result GlobalLib::getLibsLinkerFlags(const SibsConfig &parentConfig, const FileString &globalLibRootDir, GitDependency *gitDependency, LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallbackFunc, GlobalIncludeDirCallbackFunc globalIncludeDirCallback) + { + Result packageExistsResult = validatePackageExists(globalLibRootDir, gitDependency->name); + if (packageExistsResult.isErr()) + return packageExistsResult; + +#if OS_FAMILY == OS_FAMILY_POSIX + FileString namePlatformNative = gitDependency->name; + FileString versionPlatformNative = gitDependency->revision; +#else + FileString namePlatformNative = utf8To16(name); + FileString versionPlatformNative = utf8To16(version); +#endif + + FileString packageDir = globalLibRootDir + TINYDIR_STRING("/"); + packageDir += namePlatformNative; + packageDir += TINYDIR_STRING("/"); + packageDir += versionPlatformNative; + + // TODO: Check path is valid git repository by using git_repository_open_ext + + // TODO: Pull if revision == HEAD, fail build if there are conflicts. + // TODO: When building a sibs project, put a symlink in libs directory. + // This allows you to have dependency on a project and make changes to it without pushing + // to remote before the dependant project can see the changes. + //GitRepository gitRepo; + //gitRepo.pull(gitDependency, packageDir); + + return GlobalLib::getLibsLinkerFlagsCommon(parentConfig, packageDir, gitDependency->name, staticLinkerFlagCallbackFunc, dynamicLinkerFlagCallbackFunc, globalIncludeDirCallback); + } + + Result GlobalLib::getLibsLinkerFlagsCommon(const SibsConfig &parentConfig, const FileString &packageDir, const string &dependencyName, LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallbackFunc, GlobalIncludeDirCallbackFunc globalIncludeDirCallback) + { FileString projectConfFilePath = packageDir; projectConfFilePath += TINYDIR_STRING("/project.conf"); FileType projectConfFileType = getFileType(projectConfFilePath.c_str()); - switch(projectConfFileType) + if(projectConfFileType != FileType::REGULAR) { - case FileType::FILE_NOT_FOUND: - { - string errMsg = "Global lib dependency found: "; - errMsg += toUtf8(packageDir); - errMsg += ", but it's missing a project.conf file"; - return Result::Err(errMsg); - } - case FileType::DIRECTORY: - { - string errMsg = "Global lib dependency found: "; - errMsg += toUtf8(packageDir); - errMsg += ", but it's corrupt (Found directory instead of file)"; - return Result::Err(errMsg); - } + string errMsg = "Dependency not found: "; + errMsg += toUtf8(packageDir); + return Result::Err(errMsg, DependencyError::DEPENDENCY_NOT_FOUND); } - + SibsConfig sibsConfig(parentConfig.getCompiler(), packageDir, parentConfig.getOptimizationLevel(), false); Result result = Config::readFromFile(projectConfFilePath.c_str(), sibsConfig); if (result.isErr()) @@ -171,7 +230,7 @@ namespace sibs if(sibsConfig.getPackageType() == PackageType::EXECUTABLE) { string errMsg = "The dependency "; - errMsg += name; + errMsg += dependencyName; errMsg += " is an executable. Only libraries can be dependencies"; return Result::Err(errMsg); } @@ -179,7 +238,7 @@ namespace sibs if (!containsPlatform(sibsConfig.getPlatforms(), SYSTEM_PLATFORM)) { string errMsg = "The dependency "; - errMsg += name; + errMsg += dependencyName; errMsg += " does not support your platform ("; errMsg += asString(SYSTEM_PLATFORM); errMsg += ")"; @@ -268,7 +327,7 @@ namespace sibs case Compiler::GCC: { libPath += "/lib"; - libPath += name; + libPath += dependencyName; if (sibsConfig.getPackageType() == PackageType::STATIC) { libPath += ".a"; @@ -290,7 +349,7 @@ namespace sibs case Compiler::MSVC: { libPath += "/"; - libPath += name; + libPath += dependencyName; if (sibsConfig.getPackageType() == PackageType::STATIC) { libPath += ".lib"; @@ -316,9 +375,9 @@ namespace sibs } } - Result GlobalLib::downloadDependency(const Dependency &dependency) + Result GlobalLib::downloadDependency(PackageListDependency *dependency) { - Result packageUrlResult = Package::getPackageUrl(dependency.name.c_str(), dependency.version.c_str(), SYSTEM_PLATFORM_NAME); + Result packageUrlResult = Package::getPackageUrl(dependency->name.c_str(), dependency->version.c_str(), SYSTEM_PLATFORM_NAME); if(!packageUrlResult) return Result::Err(packageUrlResult); @@ -329,28 +388,49 @@ namespace sibs return Result::Err(libPathResult); FileString libPath = libPathResult.unwrap(); libPath += TINYDIR_STRING("/.sibs/lib/"); - libPath += toFileString(dependency.name); + libPath += toFileString(dependency->name); libPath += TINYDIR_STRING("/"); - libPath += toFileString(dependency.version); + libPath += toFileString(dependency->version); FileString libArchivedFilePath = libPathResult.unwrap(); libArchivedFilePath += TINYDIR_STRING("/.sibs/archive/"); - libArchivedFilePath += toFileString(dependency.name); + libArchivedFilePath += toFileString(dependency->name); Result createArchiveDirResult = createDirectoryRecursive(libArchivedFilePath.c_str()); - if(createArchiveDirResult.isErr()) + if(!createArchiveDirResult) return createArchiveDirResult; libArchivedFilePath += TINYDIR_STRING("/"); - libArchivedFilePath += toFileString(dependency.version); + libArchivedFilePath += toFileString(dependency->version); Result downloadResult = curl::downloadFile(url.c_str(), libArchivedFilePath.c_str()); - if(downloadResult.isErr()) + if(!downloadResult) return downloadResult; // Create build path. This is done here because we dont want to create it if download fails Result createLibDirResult = createDirectoryRecursive(libPath.c_str()); - if(createLibDirResult.isErr()) + if(!createLibDirResult) return createLibDirResult; return Archive::extract(libArchivedFilePath.c_str(), libPath.c_str()); } + + Result GlobalLib::downloadDependency(GitDependency *dependency) + { + Result libPathResult = getHomeDir(); + if (!libPathResult) + return Result::Err(libPathResult); + FileString libPath = libPathResult.unwrap(); + libPath += TINYDIR_STRING("/.sibs/lib/"); + libPath += toFileString(dependency->name); + + // We dont care if the directory already exists. Nothing will happen if it does + Result createLibDirResult = createDirectoryRecursive(libPath.c_str()); + if(!createLibDirResult) + return createLibDirResult; + + libPath += TINYDIR_STRING("/"); + libPath += toFileString(dependency->revision); + + GitRepository gitRepo; + return gitRepo.clone(dependency, libPath); + } } -- cgit v1.2.3