From 87a65f6913429b26e63fdee17cb8cfe93990db35 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Tue, 2 Jan 2018 17:38:18 +0100 Subject: Add support for cmake Not working fully yet, will investigate why --- src/CmakeModule.cpp | 206 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 src/CmakeModule.cpp (limited to 'src/CmakeModule.cpp') diff --git a/src/CmakeModule.cpp b/src/CmakeModule.cpp new file mode 100644 index 0000000..1995023 --- /dev/null +++ b/src/CmakeModule.cpp @@ -0,0 +1,206 @@ +#include "../include/CmakeModule.hpp" +#include "../include/Exec.hpp" +#include "../include/GlobalLib.hpp" + +#if OS_FAMILY == OS_FAMILY_POSIX +#define nprintf printf +#else +#define nprintf wprintf +#endif + +using namespace std; + +namespace sibs +{ + Result CmakeModule::compile(const SibsConfig &config, const FileString &buildPath, LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallbackFunc, GlobalIncludeDirCallbackFunc globalIncludeDirCallback) + { + Result globalLibDirResult = getHomeDir(); + if (!globalLibDirResult) + return Result::Err(globalLibDirResult); + FileString globalLibDir = globalLibDirResult.unwrap(); + globalLibDir += TINYDIR_STRING("/.sibs/lib"); + Result createGlobalLibDirResult = createDirectoryRecursive(globalLibDir.c_str()); + if(createGlobalLibDirResult.isErr()) + return createGlobalLibDirResult; + + // TODO: Create a cmake module that contains library/include path for the dependencies (https://cmake.org/Wiki/CMake:How_To_Find_Libraries). + // Modify the project CMakeLists.txt and add: list(APPEND CMAKE_MODULE_PATH "PathToDependenciesCmakeModulesGoesHere"). + // CMakeLists.txt may contain: set(CMAKE_MODULE_PATH "PathToModules"). This needs to be replaced with list append, + // otherwise our added module path is replaced. + // It may work to do like vcpkg instead - to use -DCMAKE_TOOLCHAIN_FILE program argument to specify path to script (https://github.com/Microsoft/vcpkg/blob/master/docs/examples/using-sqlite.md) + for(const Dependency &globalLibDependency : config.getDependencies()) + { + Result globalLibLinkerFlagsResult = GlobalLib::getLibsLinkerFlags(config, globalLibDir, globalLibDependency.name, globalLibDependency.version, staticLinkerFlagCallbackFunc, dynamicLinkerFlagCallbackFunc, globalIncludeDirCallback); + if(globalLibLinkerFlagsResult.isErr()) + { + if(globalLibLinkerFlagsResult.getErrorCode() == GlobalLib::DependencyError::DEPENDENCY_NOT_FOUND || globalLibLinkerFlagsResult.getErrorCode() == GlobalLib::DependencyError::DEPENDENCY_VERSION_NO_MATCH) + { + printf("Dependency not found in global lib, trying to download from github\n"); + // 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(globalLibDependency); + if(downloadDependencyResult.isErr()) + return downloadDependencyResult; + + globalLibLinkerFlagsResult = GlobalLib::getLibsLinkerFlags(config, globalLibDir, globalLibDependency.name, globalLibDependency.version, staticLinkerFlagCallbackFunc, dynamicLinkerFlagCallbackFunc, globalIncludeDirCallback); + if(globalLibLinkerFlagsResult.isErr()) + return Result::Err(globalLibLinkerFlagsResult); + } + else + { + return Result::Err(globalLibLinkerFlagsResult); + } + } + } + + Result createBuildDirResult = createDirectoryRecursive(buildPath.c_str()); + if (createBuildDirResult.isErr()) + return createBuildDirResult; + + FileString cmd = TINYDIR_STRING("cmake "); + switch(config.getPackageType()) + { + case PackageType::EXECUTABLE: + { + cmd += config.getCmakeArgs(); + break; + } + case PackageType::STATIC: + { + cmd += config.getCmakeArgsStatic(); + break; + } + case PackageType::DYNAMIC: + case PackageType::LIBRARY: + { + cmd += config.getCmakeArgsDynamic(); + break; + } + } + cmd += TINYDIR_STRING(" \"-B"); + cmd += buildPath; + cmd += TINYDIR_STRING("\" \"-H"); + switch(config.getPackageType()) + { + case PackageType::EXECUTABLE: + { + cmd += config.getCmakeDir(); + break; + } + case PackageType::STATIC: + { + cmd += config.getCmakeDirStatic(); + break; + } + case PackageType::DYNAMIC: + case PackageType::LIBRARY: + { + cmd += config.getCmakeDirDynamic(); + break; + } + } + cmd += TINYDIR_STRING("\""); + nprintf("Compiling with cmake with arguments: %s\n", cmd.c_str()); + + Result execResult = exec(cmd.c_str(), true); + if(execResult.isOk()) + { + if(execResult.unwrap().exitCode != 0) + return Result::Err(execResult.unwrap().execStdout); + } + else + return Result::Err(execResult); + + FileString ninjaCommand = TINYDIR_STRING("ninja -C \""); + ninjaCommand += buildPath; + ninjaCommand += TINYDIR_STRING("\""); + nprintf("Compiling cmake generated ninja file: %s\n", ninjaCommand.c_str()); + execResult = exec(ninjaCommand.c_str(), true); + if(execResult.isOk()) + { + if(execResult.unwrap().exitCode != 0) + return Result::Err(execResult.unwrap().execStdout); + } + else + return Result::Err(execResult); + + if(config.getPackageType() != PackageType::EXECUTABLE) + { + #if OS_TYPE == OS_TYPE_WINDOWS + const _tinydir_char_t *libFileExtension = TINYDIR_STRING("lib"); + #elif OS_TYPE == OS_TYPE_LINUX + const _tinydir_char_t *libFileExtension = TINYDIR_STRING("so"); + #endif + + FileString libFile; + u64 libFileLastModified = 0; + + string buildPathUtf8 = toUtf8(buildPath); + nprintf("Searching for library generate by cmake in build path: %s\n", buildPathUtf8.c_str()); + walkDirFiles(buildPath.c_str(), [&libFileExtension, &libFile, &libFileLastModified](tinydir_file *file) + { + if(_tinydir_strcmp(file->extension, libFileExtension) == 0) + { + u32 fileLastModified = getFileLastModifiedTime(file->path); + if(fileLastModified > libFileLastModified) + { + libFileLastModified = fileLastModified; + libFile = file->path; + } + } + }); + + if(libFileLastModified == 0) + { + string errMsg = "Package "; + errMsg += config.getPackageName(); + errMsg += " was built using cmake but no generated library was found"; + return Result::Err(errMsg); + } + string libFileUtf8 = toUtf8(libFile); + nprintf("Library generated by cmake: %s\n", libFileUtf8.c_str()); + + switch(config.getPackageType()) + { + case PackageType::STATIC: + { + string libFileCmd = "\""; + libFileCmd += libFileUtf8; + libFileCmd += "\""; + staticLinkerFlagCallbackFunc(libFileCmd); + break; + } + case PackageType::DYNAMIC: + case PackageType::LIBRARY: + { + string libFileCmd = "\""; + libFileCmd += libFileUtf8; + libFileCmd += "\""; + dynamicLinkerFlagCallbackFunc(libFileCmd); + break; + } + } + + // TODO: Clean this up. The below code is indentical to code in Ninja.cpp....... + string projectPathUtf8 = toUtf8(config.getProjectPath()); + printf("BUILD CMAKE MODULE!, num global include dirs: %d\n", config.getGlobalIncludeDirs().size()); + for (const string &globalIncludeDir : config.getGlobalIncludeDirs()) + { + string globalIncludeDirFull = projectPathUtf8; + globalIncludeDirFull += "/"; + globalIncludeDirFull += globalIncludeDir; + if(globalIncludeDirCallback) + globalIncludeDirCallback(globalIncludeDirFull); + } + } + + return Result::Ok(true); + } +} -- cgit v1.2.3