From 179c5baaa2b24be61f65daad0e4d415914af4c71 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Thu, 28 Dec 2017 22:55:50 +0100 Subject: Add support for tests in a package where type is executable --- .gitignore | 4 +++- backend/ninja/Ninja.cpp | 59 +++++++++++++++++++++++++++++++++++++++++-------- backend/ninja/Ninja.hpp | 5 ++--- include/Conf.hpp | 11 +++++++++ project.conf | 3 ++- src/Conf.cpp | 23 ++++++++++++++++++- src/GlobalLib.cpp | 21 +++--------------- src/main.cpp | 18 +-------------- tests/project.conf | 2 ++ tests/src/function.cpp | 6 +++++ tests/src/main.cpp | 2 ++ 11 files changed, 104 insertions(+), 50 deletions(-) create mode 100644 tests/project.conf create mode 100644 tests/src/function.cpp create mode 100644 tests/src/main.cpp diff --git a/.gitignore b/.gitignore index 5dc9509..2a323e3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ sibs-build -.idea/ \ No newline at end of file +.idea/ +.kdev4/ +sibs.kdev4 diff --git a/backend/ninja/Ninja.cpp b/backend/ninja/Ninja.cpp index 43ded44..dda4aa4 100644 --- a/backend/ninja/Ninja.cpp +++ b/backend/ninja/Ninja.cpp @@ -36,11 +36,24 @@ namespace backend ++i; } - return move(result); + return result; + } + + Ninja::LibraryType getNinjaLibraryType(PackageType packageType) + { + switch(packageType) + { + case PackageType::EXECUTABLE: + return Ninja::LibraryType::EXECUTABLE; + case PackageType::STATIC: + return Ninja::LibraryType::STATIC; + case PackageType::DYNAMIC: + case PackageType::LIBRARY: + return Ninja::LibraryType::DYNAMIC; + } } - Ninja::Ninja(LibraryType _libraryType) : - libraryType(_libraryType) + Ninja::Ninja() { } @@ -209,6 +222,8 @@ namespace backend Result createBuildDirResult = createDirectoryRecursive(savePath); if(createBuildDirResult.isErr()) return createBuildDirResult; + + LibraryType libraryType = getNinjaLibraryType(config.getPackageType()); string ninjaBuildFilePath = savePath; ninjaBuildFilePath += "/build.ninja"; @@ -229,6 +244,19 @@ namespace backend result += "'"; } result += "\n\n"; + + string defines; + for(const auto &definePair : config.getDefines()) + { + defines += " '-D"; + defines += definePair.first; + defines += "="; + defines += definePair.second; + defines += "'"; + } + + if(!defines.empty()) + printf("Custom define: %s\n", defines.c_str()); string buildJob; switch(libraryType) @@ -295,7 +323,10 @@ namespace backend result += ": cpp_COMPILER ../../"; result += sourceFile; result += "\n"; - result += " ARGS = $globalIncDir '-I" + config.getPackageName() + "@exe' '-I..' '-fdiagnostics-color=always' '-pipe' '-D_FILE_OFFSET_BITS=64' '-Wall' '-Winvalid-pch' '-Wnon-virtual-dtor' " + optimizationFlags + " '-g'\n\n"; + result += " ARGS = $globalIncDir '-I" + config.getPackageName() + "@exe' '-I..' "; + if(!defines.empty()) + result += defines; + result += " '-fdiagnostics-color=always' '-pipe' '-D_FILE_OFFSET_BITS=64' '-Wall' '-Winvalid-pch' '-Wnon-virtual-dtor' " + optimizationFlags + " '-g'\n\n"; objectNames.emplace_back(objectName); } @@ -395,7 +426,7 @@ namespace backend if(!buildResult) return buildResult; - Result buildTestResult = buildTests(projectGeneratedBinary); + Result buildTestResult = buildTests(projectGeneratedBinary, config, savePath); if(!buildTestResult) return buildTestResult; @@ -417,14 +448,24 @@ namespace backend return false; } - Result Ninja::buildTests(const std::string &projectGeneratedBinary) + Result Ninja::buildTests(const std::string &projectGeneratedBinary, const SibsConfig &config, const char *savePath) { if(testSourceDirs.empty()) return Result::Ok(true); - // TODO: Include executable as dependency??? or compile project as dynamic library even if it's not a library - if(libraryType == LibraryType::EXECUTABLE) - return Result::Err("Unit tests are currently only supported in projects that compile to static/dynamic library"); + // Tests need parent project as dependency. Executables can't be included as dependency so we build it as dynamic library. + // `build` also builds tests + if(getNinjaLibraryType(config.getPackageType()) == LibraryType::EXECUTABLE) + { + SibsConfig parentProjConfigLib = config; + parentProjConfigLib.setPackageType(PackageType::DYNAMIC); + // HACK: We can build a package that is defined as executable and contains main function by redefining `main` + // as something else. + // TODO: Do not allow defining `main` in project.conf or as program argument to sibs (when sibs supports defines). + // It's ok if `define` fails. It could fail if `main` has already been replaced by other tests somehow. + parentProjConfigLib.define("main", "sibs_lib_ignore_main"); + return build(parentProjConfigLib, savePath, nullptr, nullptr); + } for(const string &testSourceDir : testSourceDirs) { diff --git a/backend/ninja/Ninja.hpp b/backend/ninja/Ninja.hpp index fddcaf3..17649aa 100644 --- a/backend/ninja/Ninja.hpp +++ b/backend/ninja/Ninja.hpp @@ -22,7 +22,7 @@ namespace backend DYNAMIC, }; - Ninja(LibraryType libraryType = LibraryType::EXECUTABLE); + Ninja(); void addSourceFile(const char *filepath); void addTestSourceDir(const char *dir); @@ -30,7 +30,7 @@ namespace backend const std::vector& getSourceFiles() const; sibs::Result build(const sibs::SibsConfig &config, const char *savePath, sibs::LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc = nullptr, sibs::LinkerFlagCallbackFunc dynamicLinkerFlagCallback = nullptr); private: - sibs::Result buildTests(const std::string &projectGeneratedBinary); + sibs::Result buildTests(const std::string &projectGeneratedBinary, const sibs::SibsConfig &config, const char *savePath); bool containsSourceFile(const std::string &filepath) const; bool containsTestSourceDir(const std::string &dir) const; bool containsDependency(const std::string &dependency) const; @@ -40,7 +40,6 @@ namespace backend std::vector sourceFiles; std::vector testSourceDirs; std::vector binaryDependencies; - LibraryType libraryType; }; } diff --git a/include/Conf.hpp b/include/Conf.hpp index 1f680e8..5e3ed87 100644 --- a/include/Conf.hpp +++ b/include/Conf.hpp @@ -7,6 +7,7 @@ #include "Dependency.hpp" #include "Package.hpp" #include +#include #include #include @@ -135,6 +136,15 @@ namespace sibs { return optimizationLevel; } + + void setPackageType(PackageType packageType) + { + this->packageType = packageType; + } + + 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; protected: virtual void processObject(StringView name) override; virtual void processField(StringView name, const ConfigValue &value) override; @@ -147,6 +157,7 @@ namespace sibs PackageType packageType; std::vector dependencies; std::vector includeDirs; + std::unordered_map defines; OptimizationLevel optimizationLevel; bool finishedProcessing; }; diff --git a/project.conf b/project.conf index a6e811c..3f46ea9 100644 --- a/project.conf +++ b/project.conf @@ -3,7 +3,8 @@ name = "sibs" type = "executable" version = "0.1.0" authors = ["DEC05EBA <0xdec05eba@gmail.com>"] +tests = "tests" [dependencies] libcurl = "7" -libarchive = "3.3" \ No newline at end of file +libarchive = "3.3" diff --git a/src/Conf.cpp b/src/Conf.cpp index d6aee2c..6d5834e 100644 --- a/src/Conf.cpp +++ b/src/Conf.cpp @@ -341,6 +341,27 @@ namespace sibs case OPT_LEV_RELEASE: return "release"; } } + + bool SibsConfig::isDefined(const std::string &name) const + { + return defines.find(name) != defines.end(); + } + + bool SibsConfig::define(const std::string &name, const std::string &value) + { + if(isDefined(name)) + return false; + else + { + defines[name] = value; + return true; + } + } + + const std::unordered_map& SibsConfig::getDefines() const + { + return defines; + } void SibsConfig::processObject(StringView name) { @@ -495,4 +516,4 @@ namespace sibs { finishedProcessing = true; } -} \ No newline at end of file +} diff --git a/src/GlobalLib.cpp b/src/GlobalLib.cpp index d994a27..cbc27bc 100644 --- a/src/GlobalLib.cpp +++ b/src/GlobalLib.cpp @@ -126,22 +126,7 @@ namespace sibs return Result::Err(errMsg); } - backend::Ninja::LibraryType libraryType; - switch(sibsConfig.getPackageType()) - { - case PackageType::STATIC: - libraryType = backend::Ninja::LibraryType::STATIC; - break; - case PackageType::DYNAMIC: - case PackageType::LIBRARY: - libraryType = backend::Ninja::LibraryType::DYNAMIC; - break; - default: - assert(false); - return Result::Err("Unexpected error"); - } - - backend::Ninja ninja(libraryType); + backend::Ninja ninja; FileWalkCallbackFunc collectSourceFiles = [&ninja, &sibsConfig, &collectSourceFiles](tinydir_file *file) { if(file->is_reg) @@ -189,7 +174,7 @@ namespace sibs string libPath = buildPath; libPath += "/lib"; libPath += name; - if(libraryType == backend::Ninja::LibraryType::STATIC) + if(sibsConfig.getPackageType() == PackageType::STATIC) { libPath += ".a"; string libPathCmd = "'"; @@ -255,4 +240,4 @@ namespace sibs return Archive::extract(libArchivedFilePath.c_str(), libPath.c_str()); } -} \ No newline at end of file +} diff --git a/src/main.cpp b/src/main.cpp index 9e84521..26cab5c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -197,23 +197,7 @@ int buildProject(int argc, const char **argv) //string projectSrcPath = projectPath + "/src"; //validateDirectoryPath(projectSrcPath.c_str()); - PackageType packageType = sibsConfig.getPackageType(); - backend::Ninja::LibraryType libraryType; - switch(packageType) - { - case PackageType::EXECUTABLE: - libraryType = backend::Ninja::LibraryType::EXECUTABLE; - break; - case PackageType::STATIC: - libraryType = backend::Ninja::LibraryType::STATIC; - break; - case PackageType::DYNAMIC: - case PackageType::LIBRARY: - libraryType = backend::Ninja::LibraryType::DYNAMIC; - break; - } - - backend::Ninja ninja(libraryType); + backend::Ninja ninja; FileWalkCallbackFunc collectSourceFiles = [&ninja, &sibsConfig, &collectSourceFiles](tinydir_file *file) { if(file->is_reg) diff --git a/tests/project.conf b/tests/project.conf new file mode 100644 index 0000000..6a33314 --- /dev/null +++ b/tests/project.conf @@ -0,0 +1,2 @@ +[dependencies] +catch2 = "0.1.0" diff --git a/tests/src/function.cpp b/tests/src/function.cpp new file mode 100644 index 0000000..5f14f33 --- /dev/null +++ b/tests/src/function.cpp @@ -0,0 +1,6 @@ +#include "catch2/0.1.0/catch.hpp" + +TEST_CASE("dummy") +{ + +} diff --git a/tests/src/main.cpp b/tests/src/main.cpp new file mode 100644 index 0000000..d29d915 --- /dev/null +++ b/tests/src/main.cpp @@ -0,0 +1,2 @@ +#define CATCH_CONFIG_MAIN +#include "catch2/0.1.0/catch.hpp" -- cgit v1.2.3