aboutsummaryrefslogtreecommitdiff
path: root/src/CmakeModule.cpp
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2018-01-02 17:38:18 +0100
committerdec05eba <dec05eba@protonmail.com>2018-01-02 20:10:53 +0100
commit87a65f6913429b26e63fdee17cb8cfe93990db35 (patch)
treec2cfac67fc09f9c364869a107a140c34c5b73fd8 /src/CmakeModule.cpp
parente8afe1630280335e5c7f4938f7c265b8798049d1 (diff)
Add support for cmake
Not working fully yet, will investigate why
Diffstat (limited to 'src/CmakeModule.cpp')
-rw-r--r--src/CmakeModule.cpp206
1 files changed, 206 insertions, 0 deletions
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<bool> CmakeModule::compile(const SibsConfig &config, const FileString &buildPath, LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallbackFunc, GlobalIncludeDirCallbackFunc globalIncludeDirCallback)
+ {
+ Result<FileString> globalLibDirResult = getHomeDir();
+ if (!globalLibDirResult)
+ return Result<bool>::Err(globalLibDirResult);
+ FileString globalLibDir = globalLibDirResult.unwrap();
+ globalLibDir += TINYDIR_STRING("/.sibs/lib");
+ Result<bool> 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<bool> 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<bool> 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<bool>::Err(globalLibLinkerFlagsResult);
+ }
+ else
+ {
+ return Result<bool>::Err(globalLibLinkerFlagsResult);
+ }
+ }
+ }
+
+ Result<bool> 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> execResult = exec(cmd.c_str(), true);
+ if(execResult.isOk())
+ {
+ if(execResult.unwrap().exitCode != 0)
+ return Result<bool>::Err(execResult.unwrap().execStdout);
+ }
+ else
+ return Result<bool>::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<bool>::Err(execResult.unwrap().execStdout);
+ }
+ else
+ return Result<bool>::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<bool>::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<bool>::Ok(true);
+ }
+}