diff options
-rw-r--r-- | .gitignore | 16 | ||||
-rw-r--r-- | CMakeLists.txt | 24 | ||||
-rw-r--r-- | README.md | 5 | ||||
-rw-r--r-- | backend/ninja/Ninja.cpp | 75 | ||||
-rw-r--r-- | backend/ninja/Ninja.hpp | 5 | ||||
-rw-r--r-- | include/Conf.hpp | 11 | ||||
-rwxr-xr-x | install.sh | 12 | ||||
-rw-r--r-- | project.conf | 8 | ||||
-rw-r--r-- | src/Conf.cpp | 23 | ||||
-rw-r--r-- | src/GlobalLib.cpp | 23 | ||||
-rw-r--r-- | src/main.cpp | 25 | ||||
-rw-r--r-- | tests/project.conf | 2 | ||||
-rw-r--r-- | tests/src/confTest/confTest.cpp | 26 | ||||
-rw-r--r-- | tests/src/confTest/project.conf | 8 | ||||
-rw-r--r-- | tests/src/main.cpp | 2 |
15 files changed, 167 insertions, 98 deletions
@@ -1,12 +1,4 @@ -CMakeCache.txt -CMakeFiles -CMakeScripts -Testing -Makefile -cmake_install.cmake -install_manifest.txt -compile_commands.json -CTestTestfile.cmake -cmake-build-debug -.idea -build +sibs-build +.idea/ +.kdev4/ +sibs.kdev4 diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index a636daa..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -cmake_minimum_required(VERSION 3.0.2) -project(sibs) - -set(CMAKE_CXX_STANDARD 11) - -set(SOURCE_FILES - external/xxhash.c - backend/ninja/Ninja.cpp - src/main.cpp - src/FileUtil.cpp - src/Conf.cpp - src/PkgConfig.cpp - src/Exec.cpp - src/GlobalLib.cpp - src/curl.cpp - src/Archive.cpp) - -find_package(CURL REQUIRED) -find_package(LibArchive REQUIRED) - -add_executable(sibs ${SOURCE_FILES}) - -include_directories(${CURL_INCLUDE_DIR} ${LibArchive_INCLUDE_DIR}) -target_link_libraries(sibs ${CURL_LIBRARIES} ${LibArchive_LIBRARIES})
\ No newline at end of file @@ -1,2 +1,7 @@ # Simple Build System for Native Languages sibs can currently create ninja build files from very simple c++ projects. More to be added soon. + +# Installation +Newest version of sibs builds itself. If you don't already have sibs installed, you need to download an old version first: https://github.com/DEC05EBA/sibs/releases/tag/0.1.0 +After you've download release 0.1.0, you can install it by running install.sh +When you have sibs 0.1.0 installed, you can install latest version of sibs by running install.sh. New install script uses sibs. diff --git a/backend/ninja/Ninja.cpp b/backend/ninja/Ninja.cpp index b2a073b..49bda4f 100644 --- a/backend/ninja/Ninja.cpp +++ b/backend/ninja/Ninja.cpp @@ -42,7 +42,29 @@ namespace backend ++i; } - return move(result); + return result; + } + + bool endsWith(const string &str, const string &endWithStr) + { + if(endWithStr.size() > str.size()) + return false; + else + return strncmp(&str[str.size() - endWithStr.size()], &endWithStr[0], endWithStr.size()) == 0; + } + + 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; + } } string getIncludeOptionFlag(Compiler compiler, const string &filepath) @@ -117,8 +139,7 @@ namespace backend } } - Ninja::Ninja(LibraryType _libraryType) : - libraryType(_libraryType) + Ninja::Ninja() { } @@ -183,7 +204,7 @@ namespace backend } return false; } - + #if OS_FAMILY == OS_FAMILY_POSIX Result<bool> validatePkgConfigPackageVersionExists(const Dependency &dependency) { @@ -299,6 +320,8 @@ namespace backend if(createBuildDirResult.isErr()) return createBuildDirResult; + LibraryType libraryType = getNinjaLibraryType(config.getPackageType()); + string savePathUtf8 = toUtf8(savePath); FileString ninjaBuildFilePath = savePath; @@ -325,6 +348,19 @@ namespace backend } 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 compilerName; switch (config.getCompiler()) { @@ -431,6 +467,9 @@ namespace backend objectNames.reserve(sourceFiles.size()); for(const string &sourceFile : sourceFiles) { + string sourceFileLanguage = "c++"; + if(endsWith(sourceFile, ".c")) + sourceFileLanguage = "c"; //string sourceFileEncoded = sourceFile; //replace(sourceFileEncoded, '/', '@'); string objectName = config.getPackageName() + "@exe/" + sourceFile; @@ -440,7 +479,9 @@ namespace backend result += ": cpp_COMPILER ../../"; result += sourceFile; result += "\n"; - result += " ARGS = $globalIncDir"; + result += " ARGS = $globalIncDir "; + if(!defines.empty()) + result += defines; if(config.getCompiler() != Compiler::MSVC) result += " '-I" + config.getPackageName() + "@exe' '-I..' '-fdiagnostics-color=always' '-pipe' '-D_FILE_OFFSET_BITS=64' '-Wall' '-Winvalid-pch' '-Wnon-virtual-dtor' " + optimizationFlags + " '-g'"; result += "\n\n"; @@ -508,7 +549,7 @@ namespace backend break; } } - + if(!allLinkerFlags.empty()) { result += allLinkerFlags; @@ -592,7 +633,7 @@ namespace backend if(!buildResult) return buildResult; - Result<bool> buildTestResult = buildTests(config, projectGeneratedBinary); + Result<bool> buildTestResult = buildTests(projectGeneratedBinary, config, savePath); if(!buildTestResult) return buildTestResult; @@ -614,14 +655,24 @@ namespace backend return false; } - Result<bool> Ninja::buildTests(const SibsConfig &parentConfig, const std::string &projectGeneratedBinary) + Result<bool> Ninja::buildTests(const std::string &projectGeneratedBinary, const SibsConfig &config, const char *savePath) { if(testSourceDirs.empty()) return Result<bool>::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<bool>::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) { @@ -635,7 +686,7 @@ namespace backend projectConfFilePath += TINYDIR_STRING("/project.conf"); FileType projectConfFileType = getFileType(projectConfFilePath.c_str()); - SibsTestConfig sibsTestConfig(parentConfig.getCompiler(), testSourceDirNative); + SibsTestConfig sibsTestConfig(config.getCompiler(), testSourceDirNative); if(projectConfFileType == FileType::REGULAR) { Result<bool> result = Config::readFromFile(projectConfFilePath.c_str(), sibsTestConfig); diff --git a/backend/ninja/Ninja.hpp b/backend/ninja/Ninja.hpp index e37a5ca..36a57ff 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<std::string>& getSourceFiles() const; sibs::Result<bool> build(const sibs::SibsConfig &config, const _tinydir_char_t *savePath, sibs::LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc = nullptr, sibs::LinkerFlagCallbackFunc dynamicLinkerFlagCallback = nullptr); private: - sibs::Result<bool> buildTests(const sibs::SibsConfig &parentConfig, const std::string &projectGeneratedBinary); + sibs::Result<bool> 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<std::string> sourceFiles; std::vector<std::string> testSourceDirs; std::vector<std::string> binaryDependencies; - LibraryType libraryType; }; } diff --git a/include/Conf.hpp b/include/Conf.hpp index 0ad1090..d147fca 100644 --- a/include/Conf.hpp +++ b/include/Conf.hpp @@ -8,6 +8,7 @@ #include "Dependency.hpp" #include "Package.hpp" #include <vector> +#include <unordered_map> #include <cassert> #include <stdexcept> @@ -147,6 +148,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<std::string, std::string>& getDefines() const; protected: virtual void processObject(StringView name) override; virtual void processField(StringView name, const ConfigValue &value) override; @@ -160,6 +170,7 @@ namespace sibs PackageType packageType; std::vector<Dependency> dependencies; std::vector<std::string> includeDirs; + std::unordered_map<std::string, std::string> defines; OptimizationLevel optimizationLevel; bool finishedProcessing; }; @@ -2,10 +2,8 @@ set -e -scriptpath="$(dirname "$0")" -mkdir -p "$scriptpath/build/release" -cd "$scriptpath/build/release" -cmake -G Ninja -DCMAKE_BUILD_TYPE=Release ../../ -ninja -sudo cp sibs /usr/bin/ -echo "Copied $scriptpath/build/release/sibs to /usr/bin/sibs" +project_dir=`dirname $0` +sibs build $project_dir --release +sudo cp "$project_dir/sibs-build/release/sibs" "/usr/bin/sibs" +echo "Copied $project_dir/sibs-build/release/sibs to /usr/bin/sibs" +echo "Installation successful!"
\ No newline at end of file diff --git a/project.conf b/project.conf index 96bb9b9..3f46ea9 100644 --- a/project.conf +++ b/project.conf @@ -1,8 +1,10 @@ [package] name = "sibs" +type = "executable" version = "0.1.0" -authors = ["Aleksi Lindeman <aleksi_888@hotmail.com>"] +authors = ["DEC05EBA <0xdec05eba@gmail.com>"] +tests = "tests" [dependencies] -sfml-all = "2.4" -xxhash = "0.1.0"
\ No newline at end of file +libcurl = "7" +libarchive = "3.3" diff --git a/src/Conf.cpp b/src/Conf.cpp index 743942a..5282bb5 100644 --- a/src/Conf.cpp +++ b/src/Conf.cpp @@ -339,6 +339,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<std::string, std::string>& SibsConfig::getDefines() const + { + return defines; + } void SibsConfig::processObject(StringView name) { @@ -497,4 +518,4 @@ namespace sibs { finishedProcessing = true; } -}
\ No newline at end of file +} diff --git a/src/GlobalLib.cpp b/src/GlobalLib.cpp index db85abd..fde7797 100644 --- a/src/GlobalLib.cpp +++ b/src/GlobalLib.cpp @@ -138,22 +138,7 @@ namespace sibs return Result<string>::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<string>::Err("Unexpected error"); - } - - backend::Ninja ninja(libraryType); + backend::Ninja ninja; FileWalkCallbackFunc collectSourceFiles = [&ninja, &sibsConfig, &collectSourceFiles](tinydir_file *file) { if(file->is_reg) @@ -201,7 +186,7 @@ namespace sibs buildPath += TINYDIR_STRING("release"); break; } - + string libPath = toUtf8(buildPath); switch (sibsConfig.getCompiler()) { @@ -209,7 +194,7 @@ namespace sibs { libPath += "/lib"; libPath += name; - if (libraryType == backend::Ninja::LibraryType::STATIC) + if (sibsConfig.getPackageType() == PackageType::STATIC) { libPath += ".a"; string libPathCmd = "'"; @@ -231,7 +216,7 @@ namespace sibs { libPath += "/"; libPath += name; - if (libraryType == backend::Ninja::LibraryType::STATIC) + if (sibsConfig.getPackageType() == PackageType::STATIC) { libPath += ".lib"; string libPathCmd = "\""; diff --git a/src/main.cpp b/src/main.cpp index f49ba59..855b1dc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,7 @@ #include <cstdio> #include <iostream> #include <unordered_set> +#include <chrono> #include "../include/FileUtil.hpp" #include "../include/Conf.hpp" #include "../include/Exec.hpp" @@ -8,6 +9,7 @@ using namespace std; using namespace sibs; +using namespace std::chrono; // TODO: Fail if multiple versions of the same dependency is used // as linking will fail because of multiple definitions of the same thing @@ -20,6 +22,8 @@ using namespace sibs; // TODO: Places that use PATH_MAX should be modified. A path CAN be longer than PATH_MAX... (does this include replacing tinydir.h?) +// TODO: Remove install.sh when sibs supports installation of packages (so it can install itself) + #if OS_FAMILY == OS_FAMILY_POSIX #define ferr std::cerr #else @@ -207,23 +211,7 @@ int buildProject(int argc, const _tinydir_char_t **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) @@ -263,12 +251,15 @@ int buildProject(int argc, const _tinydir_char_t **argv) break; } + auto startTime = high_resolution_clock::now(); Result<bool> buildFileResult = ninja.build(sibsConfig, buildPath.c_str()); if(buildFileResult.isErr()) { ferr << "Failed to build ninja file: " << toFileString(buildFileResult.getErrMsg()) << endl; exit(7); } + auto elapsedTime = duration_cast<duration<double>>(high_resolution_clock::now() - startTime); + printf("Build finished in %fs\n", elapsedTime.count()); return 0; } 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/confTest/confTest.cpp b/tests/src/confTest/confTest.cpp new file mode 100644 index 0000000..38b4971 --- /dev/null +++ b/tests/src/confTest/confTest.cpp @@ -0,0 +1,26 @@ +#include "catch2/0.1.0/catch.hpp" +#include "../../../include/Conf.hpp" + +using namespace sibs; + +TEST_CASE("parse config") +{ + SibsConfig sibsConfig("tests/src/confTest"); + Result<bool> result = Config::readFromFile("tests/src/confTest/project.conf", sibsConfig); + if(result.isErr()) + { + fprintf(stderr, "%s", result.getErrMsg().c_str()); + exit(1); + } + REQUIRE(sibsConfig.getPackageName() == "confTest"); + REQUIRE(sibsConfig.getPackageType() == PackageType::LIBRARY); + REQUIRE(sibsConfig.getDependencies().size() == 2); + + const auto &xxhashDependency = sibsConfig.getDependencies()[0]; + REQUIRE(xxhashDependency.name == "xxhash"); + REQUIRE(xxhashDependency.version == "0.1.0"); + + const auto &catch2Dependency = sibsConfig.getDependencies()[1]; + REQUIRE(catch2Dependency.name == "catch2"); + REQUIRE(catch2Dependency.version == "1.0.0"); +} diff --git a/tests/src/confTest/project.conf b/tests/src/confTest/project.conf new file mode 100644 index 0000000..e50ad9c --- /dev/null +++ b/tests/src/confTest/project.conf @@ -0,0 +1,8 @@ +[package] +name = "confTest" +version = "0.1.0" +type = "library" + +[dependencies] +xxhash = "0.1.0" +catch2 = "1.0.0" 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" |