From 1f6ee990275f412d4cc84483051fd549710da634 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Mon, 1 Jan 2018 09:40:08 +0100 Subject: Add config parsing for cmake cmake has not integrated yet, but it will parse... Add test script to easily run tests --- README.md | 24 +++++++++++ include/Conf.hpp | 79 +++++++++++++++++++++++++++++++++++- include/FileUtil.hpp | 2 + src/Conf.cpp | 64 +++++++++++++++++++++++++++++ src/FileUtil.cpp | 12 ++++++ test.sh | 7 ++++ tests/src/confTest/confTest.cpp | 11 +++++ tests/src/confTest/validProject.conf | 12 ++++++ 8 files changed, 210 insertions(+), 1 deletion(-) create mode 100755 test.sh diff --git a/README.md b/README.md index 7f43ccd..f328152 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,17 @@ lib = "windows/x86/static/release" [config.win64.static.debug] lib = "windows/x64/static/debug" + +# cmake building is currrently not implemented, but it is intended to work like this +[cmake] +dir = "." +args = ["ENTITYX_RUN_BENCHMARKS=0"] + +[cmake.static] +args = ["ENTITYX_BUILD_SHARED=0"] + +[cmake.dynamic] +args = ["ENTITYX_BUILD_SHARED=1"] ``` ## package ### name @@ -75,3 +86,16 @@ Optional. The name is structured in the following way: config.platform.libraryTy where platform is any of the platforms specified under \[package] (or if package contains "any", then it can be any other platform). LibraryType is either "static" or "dynamic" - different configurations depending on if the package is included as a static or dynamic library by a dependant package. OptimizationLevel is either "debug" or "release", depending on which optimization level the "root" package was built with ("root" package is usually the project which is an executable) ### lib Optional. A directory which contains .lib or .dll files which should be included in dependant projects that uses this project +## cmake +Optional. Using this allows you to build cmake projects. If a project contains cmake in the project.conf file, then sibs wont build the project itself +and will use cmake instead. Sibs will put the built executable and library files into the same location they would be if sibs build them, +meaning you can have dependency to a cmake project from a sibs project and it will automatically use the dependency library files +### dir +Optional. Directory that contains CMakeLists.txt. If this is not specified, the project root will be used (same location where project.conf is located) +### args +Optional. List of arguments to cmake. The arguments should be in the same format as "-D" arguments (options) in cmake, except they should exclude "-D". +Do not use CMAKE_BUILD_TYPE as sibs will automatically use it depending on the optimization level the user specifies when building project. +## cmake.* +Optional. The name is structured in the following way: config.libraryType +where libraryType is either "static" or "dynamic" - different configurations depending on if the package is included as a static or dynamic library by a dependant package. +Args specified under \[cmake.static] or \[cmake.dynamic] are appended to the args specified under \[cmake] diff --git a/include/Conf.hpp b/include/Conf.hpp index 75076fa..d3d80f9 100644 --- a/include/Conf.hpp +++ b/include/Conf.hpp @@ -146,7 +146,28 @@ namespace sibs class SibsConfig : public ConfigCallback { public: - SibsConfig(Compiler _compiler, const FileString &_projectPath, OptimizationLevel _optimizationLevel = OPT_LEV_DEBUG) : compiler(_compiler), projectPath(_projectPath), packageType((PackageType)-1), optimizationLevel(_optimizationLevel), finishedProcessing(false) {} + SibsConfig(Compiler _compiler, const FileString &_projectPath, OptimizationLevel _optimizationLevel = OPT_LEV_DEBUG) : + compiler(_compiler), + projectPath(_projectPath), + packageType((PackageType)-1), + optimizationLevel(_optimizationLevel), + finishedProcessing(false), + useCmake(false) + { + cmakeDirGlobal = projectPath; + cmakeDirStatic = cmakeDirGlobal; + cmakeDirDynamic = cmakeDirGlobal; + switch(optimizationLevel) + { + case OPT_LEV_DEBUG: + cmakeArgsGlobal = "\"-DCMAKE_BUILD_TYPE=Debug\""; + break; + case OPT_LEV_RELEASE: + cmakeArgsGlobal = "\"-DCMAKE_BUILD_TYPE=Release\""; + break; + } + } + virtual ~SibsConfig(){} Compiler getCompiler() const @@ -216,6 +237,54 @@ namespace sibs return ignoreDirs; } + const FileString& getCmakeDir() const + { + return cmakeDirGlobal; + } + + const FileString& getCmakeDirStatic() const + { + return cmakeDirStatic; + } + + const FileString& getCmakeDirDynamic() const + { + return cmakeDirDynamic; + } + + // Get cmake args for all builds. This is args under [cmake] only + const std::string& getCmakeArgs() const + { + return cmakeArgsGlobal; + } + + // Get cmake args for static build. This is a combination of args under [cmake] and under [cmake.static] + std::string getCmakeArgsStatic() const + { + std::string result; + result.reserve(cmakeArgsGlobal.size() + 1 + cmakeArgsStatic.size()); + result += cmakeArgsGlobal; + result += " "; + result += cmakeArgsStatic; + return result; + } + + // Get cmake args for dynamic build. This is a combination of args under [cmake] and under [cmake.dynamic] + std::string getCmakeArgsDynamic() const + { + std::string result; + result.reserve(cmakeArgsGlobal.size() + 1 + cmakeArgsDynamic.size()); + result += cmakeArgsGlobal; + result += " "; + result += cmakeArgsDynamic; + return result; + } + + bool shouldUseCmake() const + { + return useCmake; + } + void setPackageType(PackageType packageType) { this->packageType = packageType; @@ -230,6 +299,7 @@ namespace sibs virtual void finished() override; void failInvalidFieldUnderObject(const StringView &fieldName) const; private: + void parseCmake(const StringView &fieldName, const ConfigValue &fieldValue, std::string &cmakeDir, std::string &cmakeArgs); void validatePackageName() const; protected: StringView currentObject; @@ -247,6 +317,13 @@ namespace sibs OptimizationLevel optimizationLevel; std::vector debugStaticLibs; std::vector releaseStaticLibs; + FileString cmakeDirGlobal; + FileString cmakeDirStatic; + FileString cmakeDirDynamic; + std::string cmakeArgsGlobal; + std::string cmakeArgsStatic; + std::string cmakeArgsDynamic; + bool useCmake; bool finishedProcessing; }; diff --git a/include/FileUtil.hpp b/include/FileUtil.hpp index 90b9ca3..64d0c99 100644 --- a/include/FileUtil.hpp +++ b/include/FileUtil.hpp @@ -23,12 +23,14 @@ namespace sibs #if OS_FAMILY == OS_FAMILY_POSIX #define toUtf8(input) input FileString toFileString(const std::string &utf8Str); + FileString toFileString(const StringView &utf8Str); #else std::string toUtf8(const sibs::FileString &input); std::string toUtf8(const TCHAR *input); FileString utf8To16(const StringView &utf8Str); FileString utf8To16(const std::string &utf8Str); FileString toFileString(const std::string &utf8Str); + FileString toFileString(const StringView &utf8Str); FileString getLastErrorAsString(); void replaceChar(FileString &input, wchar_t charToReplace, wchar_t charToReplaceWith); #endif diff --git a/src/Conf.cpp b/src/Conf.cpp index 27713d8..39a8c1d 100644 --- a/src/Conf.cpp +++ b/src/Conf.cpp @@ -456,6 +456,8 @@ namespace sibs void SibsConfig::processObject(StringView name) { currentObject = name; + if(currentObject.equals("cmake") || currentObject.equals("cmake.static") || currentObject.equals("cmake.dynamic")) + useCmake = true; //printf("Process object: %.*s\n", name.size, name.data); } @@ -730,6 +732,18 @@ namespace sibs else throw ParserException("Expected field under dependencies to be a single value, was a list"); } + else if(currentObject.equals("cmake")) + { + parseCmake(name, value, cmakeDirGlobal, cmakeArgsGlobal); + } + else if(currentObject.equals("cmake.static")) + { + parseCmake(name, value, cmakeDirStatic, cmakeArgsStatic); + } + else if(currentObject.equals("cmake.dynamic")) + { + parseCmake(name, value, cmakeDirDynamic, cmakeArgsDynamic); + } else { string errMsg = "Invalid config object \""; @@ -738,6 +752,56 @@ namespace sibs throw ParserException(errMsg); } } + + void SibsConfig::parseCmake(const StringView &fieldName, const ConfigValue &fieldValue, string &cmakeDir, string &cmakeArgs) + { + if(fieldName.equals("dir")) + { + if(fieldValue.isSingle()) + { + cmakeDir = projectPath; + cmakeDir += TINYDIR_STRING("/"); + cmakeDir += toFileString(fieldValue.asSingle()); + // No need to validate if CMakeLists.txt exists here, cmake will tell us if the file doesn't exist + } + else + { + string errMsg = "Expected "; + errMsg.append(currentObject.data, currentObject.size); + errMsg += "."; + errMsg.append(fieldName.data, fieldName.size); + errMsg += " to be a single value, was a list"; + throw ParserException(errMsg); + } + } + else if(fieldName.equals("args")) + { + if(fieldValue.isList()) + { + for(const StringView &arg : fieldValue.asList()) + { + bool prependSpace = !cmakeArgs.empty(); + cmakeArgs.reserve(cmakeArgs.size() + 4 + (prependSpace ? 1 : 0) + arg.size); + if(prependSpace) + cmakeArgs += " "; + cmakeArgs += "\"-D"; + cmakeArgs.append(arg.data, arg.size); + cmakeArgs += "\""; + } + } + else + { + string errMsg = "Expected "; + errMsg.append(currentObject.data, currentObject.size); + errMsg += "."; + errMsg.append(fieldName.data, fieldName.size); + errMsg += " to be a list, was a single value"; + throw ParserException(errMsg); + } + } + else + failInvalidFieldUnderObject(fieldName); + } void SibsConfig::finished() { diff --git a/src/FileUtil.cpp b/src/FileUtil.cpp index e53aa85..2626ee3 100644 --- a/src/FileUtil.cpp +++ b/src/FileUtil.cpp @@ -23,6 +23,11 @@ namespace sibs { return utf8Str; } + + FileString toFileString(const StringView &utf8Str) + { + return FileString(utf8Str.data, utf8Str.size); + } #else std::string toUtf8(const sibs::FileString &input) { @@ -57,6 +62,13 @@ namespace sibs { return utf8To16(utf8Str); } + + FileString toFileString(const StringView &utf8Str) + { + FileString result; + utf8::utf8to16(utf8Str.data, utf8Str.data + utf8Str.size, std::back_inserter(result)); + return result; + } FileString getLastErrorAsString() { diff --git a/test.sh b/test.sh new file mode 100755 index 0000000..6806e13 --- /dev/null +++ b/test.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +set -e + +sibs build +./sibs-build/debug/sibs build +./tests/sibs-build/debug/test diff --git a/tests/src/confTest/confTest.cpp b/tests/src/confTest/confTest.cpp index 17b5995..e508e84 100644 --- a/tests/src/confTest/confTest.cpp +++ b/tests/src/confTest/confTest.cpp @@ -27,6 +27,17 @@ TEST_CASE("parse config") const auto &catch2Dependency = sibsConfig.getDependencies()[1]; REQUIRE(catch2Dependency.name == "catch2"); REQUIRE(catch2Dependency.version == "1.0.0"); + + REQUIRE(sibsConfig.shouldUseCmake()); + + REQUIRE(sibsConfig.getCmakeDir() == TINYDIR_STRING("tests/src/confTest/cmakeGlobal")); + REQUIRE(sibsConfig.getCmakeArgs() == "\"-DCMAKE_BUILD_TYPE=Debug\" \"-DENTITYX_RUN_BENCHMARKS=0\""); + + REQUIRE(sibsConfig.getCmakeDirStatic() == TINYDIR_STRING("tests/src/confTest/cmakeStatic")); + REQUIRE(sibsConfig.getCmakeArgsStatic() == "\"-DCMAKE_BUILD_TYPE=Debug\" \"-DENTITYX_RUN_BENCHMARKS=0\" \"-DENTITYX_BUILD_TESTING=0\""); + + REQUIRE(sibsConfig.getCmakeDirDynamic() == TINYDIR_STRING("tests/src/confTest/cmakeDynamic")); + REQUIRE(sibsConfig.getCmakeArgsDynamic() == "\"-DCMAKE_BUILD_TYPE=Debug\" \"-DENTITYX_RUN_BENCHMARKS=0\" \"-DENTITYX_BUILD_TESTING=0\" \"-DENTITYX_BUILD_SHARED=1\""); } TEST_CASE("parse config - invalid object") diff --git a/tests/src/confTest/validProject.conf b/tests/src/confTest/validProject.conf index de5112d..eab258b 100644 --- a/tests/src/confTest/validProject.conf +++ b/tests/src/confTest/validProject.conf @@ -7,3 +7,15 @@ platforms = ["linux64", "win64"] [dependencies] xxhash = "0.1.0" catch2 = "1.0.0" + +[cmake] +dir = "cmakeGlobal" +args = ["ENTITYX_RUN_BENCHMARKS=0"] + +[cmake.static] +dir = "cmakeStatic" +args = ["ENTITYX_BUILD_TESTING=0"] + +[cmake.dynamic] +dir = "cmakeDynamic" +args = ["ENTITYX_BUILD_TESTING=0", "ENTITYX_BUILD_SHARED=1"] -- cgit v1.2.3