From ad3b5099263e5977d1de9bfcff715a92009e8355 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sat, 6 Jan 2018 09:38:59 +0100 Subject: Add define.static, define.dynamic --- include/Conf.hpp | 5 +++ src/Conf.cpp | 63 +++++++++++++++++++++++++++++++++++ src/main.cpp | 2 ++ tests/src/confTest/confTest.cpp | 30 +++++++++++++++++ tests/src/confTest/defineDynamic.conf | 17 ++++++++++ tests/src/confTest/defineStatic.conf | 17 ++++++++++ 6 files changed, 134 insertions(+) create mode 100644 tests/src/confTest/defineDynamic.conf create mode 100644 tests/src/confTest/defineStatic.conf diff --git a/include/Conf.hpp b/include/Conf.hpp index c661ca4..950b25a 100644 --- a/include/Conf.hpp +++ b/include/Conf.hpp @@ -331,11 +331,16 @@ namespace sibs virtual bool isDefined(const std::string &name) const; virtual bool define(const std::string &name, const std::string &value); virtual const std::unordered_map& getDefines() const; + + // Get define value by name. + // Return empty string if the value is empty or if the defined value doesn't exist + const std::string& getDefinedValue(const std::string &name) const; protected: virtual void processObject(StringView name) override; virtual void processField(StringView name, const ConfigValue &value) override; virtual void finished() override; void failInvalidFieldUnderObject(const StringView &fieldName) const; + void validatePackageTypeDefined() const; private: void parsePlatformConfigs(const StringView &fieldName, const ConfigValue &fieldValue); void parsePlatformConfig(const StringView &fieldName, const ConfigValue &fieldValue); diff --git a/src/Conf.cpp b/src/Conf.cpp index 75fdd02..f8b53e3 100644 --- a/src/Conf.cpp +++ b/src/Conf.cpp @@ -7,6 +7,8 @@ using u8string = utf8::unchecked::iterator; namespace sibs { + static const string EMPTY_STRING = ""; + class UnexpectedTokenException : public std::runtime_error { public: @@ -458,6 +460,14 @@ namespace sibs { return defines; } + + const string& SibsConfig::getDefinedValue(const string &name) const + { + auto it = defines.find(name); + if(it != defines.end()) + return it->second; + return EMPTY_STRING; + } void getLibFiles(const string &libPath, vector &outputFiles) { @@ -723,6 +733,53 @@ namespace sibs else throw ParserException("Expected field under define to be a single value, was a list"); } + else if(currentObject.equals("define.static")) + { + // TODO: Do same for cmake args and other objects where you have static and dynamic. + // Makes it easier to handle config (no need for switch for different libraryTypes) + validatePackageTypeDefined(); + + if(value.isSingle()) + { + if(packageType == PackageType::STATIC) + { + if(!isValidCIdentifier(name)) + { + string errMsg = "Definition \""; + errMsg.append(name.data, name.size); + errMsg += "\" is not in a valid format. The first character have to match [a-zA-Z_] and the next characters have to match [a-zA-Z0-9_]"; + throw ParserException(errMsg); + } + defines[string(name.data, name.size)] = string(value.asSingle().data, value.asSingle().size); + } + } + else + throw ParserException("Expected field under define.static to be a single value, was a list"); + } + else if(currentObject.equals("define.dynamic")) + { + validatePackageTypeDefined(); + + if(value.isSingle()) + { + // TODO: Remove `LIBRARY` from PackageType and if building a project where type is `library`, + // then convert it to dynamic. If a dependency has type `library`, then convert to dynamic + // unless build option includes to build dependencies as static libraries + if(packageType == PackageType::DYNAMIC || packageType == PackageType::LIBRARY) + { + if(!isValidCIdentifier(name)) + { + string errMsg = "Definition \""; + errMsg.append(name.data, name.size); + errMsg += "\" is not in a valid format. The first character have to match [a-zA-Z_] and the next characters have to match [a-zA-Z0-9_]"; + throw ParserException(errMsg); + } + defines[string(name.data, name.size)] = string(value.asSingle().data, value.asSingle().size); + } + } + else + throw ParserException("Expected field under define.dynamic to be a single value, was a list"); + } else if(currentObject.equals("cmake")) { parseCmake(name, value, cmakeDirGlobal, cmakeArgsGlobal); @@ -947,6 +1004,12 @@ namespace sibs throw ParserException(errMsg); } + void SibsConfig::validatePackageTypeDefined() const + { + if((int)packageType == -1) + throw ParserException("package.type type has not been defined yet. Expected to be either 'executable', 'static', 'dynamic' or 'library'"); + } + void SibsTestConfig::processObject(StringView name) { currentObject = name; diff --git a/src/main.cpp b/src/main.cpp index c626f11..f4d022e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -55,6 +55,8 @@ using namespace std::chrono; // and should this force static compilation so dependencies can also be built with protection and if dependencies dont exist // as static library/source, then fail build? +// TODO: Add support for common package managers (in distros). If package with the dependency version exists in package manager, install and use it instead + #if OS_FAMILY == OS_FAMILY_POSIX #define ferr std::cerr #else diff --git a/tests/src/confTest/confTest.cpp b/tests/src/confTest/confTest.cpp index 44bcab0..f3d9e2b 100644 --- a/tests/src/confTest/confTest.cpp +++ b/tests/src/confTest/confTest.cpp @@ -74,3 +74,33 @@ TEST_CASE("parse config - use different config for different platforms") #endif #endif } + +TEST_CASE("parse config - define static") +{ + SibsConfig sibsConfig(Compiler::GCC, TINYDIR_STRING("tests/src/confTest"), OPT_LEV_DEBUG, false); + Result result = Config::readFromFile(TINYDIR_STRING("tests/src/confTest/defineStatic.conf"), sibsConfig); + if(result.isErr()) + { + fprintf(stderr, "%s", result.getErrMsg().c_str()); + exit(1); + } + + REQUIRE(sibsConfig.getDefinedValue("GLOBAL_DEFINE") == "1"); + REQUIRE(sibsConfig.getDefinedValue("BUILD_STATIC") == "1"); + REQUIRE(sibsConfig.getDefinedValue("DEFINE_TYPE") == "STATIC"); +} + +TEST_CASE("parse config - define dynamic") +{ + SibsConfig sibsConfig(Compiler::GCC, TINYDIR_STRING("tests/src/confTest"), OPT_LEV_DEBUG, false); + Result result = Config::readFromFile(TINYDIR_STRING("tests/src/confTest/defineDynamic.conf"), sibsConfig); + if(result.isErr()) + { + fprintf(stderr, "%s", result.getErrMsg().c_str()); + exit(1); + } + + REQUIRE(sibsConfig.getDefinedValue("GLOBAL_DEFINE") == "1"); + REQUIRE(sibsConfig.getDefinedValue("BUILD_STATIC") == "0"); + REQUIRE(sibsConfig.getDefinedValue("DEFINE_TYPE") == "DYNAMIC"); +} diff --git a/tests/src/confTest/defineDynamic.conf b/tests/src/confTest/defineDynamic.conf new file mode 100644 index 0000000..fb08e5c --- /dev/null +++ b/tests/src/confTest/defineDynamic.conf @@ -0,0 +1,17 @@ +[package] +name = "glew" +version = "2.1.0" +type = "dynamic" +platforms = ["any"] + +[define] +GLOBAL_DEFINE = "1" +DEFINE_TYPE = "GLOBAL" + +[define.static] +BUILD_STATIC = "1" +DEFINE_TYPE = "STATIC" + +[define.dynamic] +BUILD_STATIC = "0" +DEFINE_TYPE = "DYNAMIC" diff --git a/tests/src/confTest/defineStatic.conf b/tests/src/confTest/defineStatic.conf new file mode 100644 index 0000000..8ec0d8c --- /dev/null +++ b/tests/src/confTest/defineStatic.conf @@ -0,0 +1,17 @@ +[package] +name = "glew" +version = "2.1.0" +type = "static" +platforms = ["any"] + +[define] +GLOBAL_DEFINE = "1" +DEFINE_TYPE = "GLOBAL" + +[define.static] +BUILD_STATIC = "1" +DEFINE_TYPE = "STATIC" + +[define.dynamic] +BUILD_STATIC = "0" +DEFINE_TYPE = "DYNAMIC" -- cgit v1.2.3