diff options
Diffstat (limited to 'backend/ninja')
-rw-r--r-- | backend/ninja/Ninja.cpp | 88 | ||||
-rw-r--r-- | backend/ninja/Ninja.hpp | 23 |
2 files changed, 81 insertions, 30 deletions
diff --git a/backend/ninja/Ninja.cpp b/backend/ninja/Ninja.cpp index fb081de..614d08c 100644 --- a/backend/ninja/Ninja.cpp +++ b/backend/ninja/Ninja.cpp @@ -1,4 +1,5 @@ #include <cstring> +#include "../BackendUtils.hpp" #include "Ninja.hpp" #include "../../include/FileUtil.hpp" #include "../../include/Exec.hpp" @@ -237,6 +238,11 @@ namespace backend if(!containsDependency(binaryFile)) binaryDependencies.emplace_back(binaryFile); } + + void Ninja::addSubProject(Ninja *subProject, SibsConfig *config, sibs::FileString &&buildPath) + { + subProjects.emplace_back(NinjaSubProject{ subProject, config, move(buildPath) }); + } const std::vector<std::string>& Ninja::getSourceFiles() const { @@ -318,7 +324,7 @@ namespace backend else { const PkgConfigFlags &pkgConfigFlag = pkgConfigFlagsResult.unwrap(); - if (dynamicLinkerFlagCallback && !pkgConfigFlag.linkerFlags.empty()) + if (!pkgConfigFlag.linkerFlags.empty()) dynamicLinkerFlagCallback(pkgConfigFlag.linkerFlags); if(!pkgConfigFlag.cflags.empty()) cflagsCallbackFunc(pkgConfigFlag.cflags); @@ -338,6 +344,26 @@ namespace backend C, CPP }; + + Result<bool> Ninja::buildSubProjects(LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallback, GlobalIncludeDirCallbackFunc globalIncludeDirCallback) + { + for(auto &subProject : subProjects) + { + if(subProject.config->getPackageType() == PackageType::EXECUTABLE) + { + string errMsg = "The sub project "; + errMsg += toUtf8(subProject.buildPath); + errMsg += " is an executable. Only libraries can be sub projects"; + return Result<bool>::Err(errMsg); + } + + Result<bool> buildResult = subProject.subProject->build(*subProject.config, subProject.buildPath.c_str(), staticLinkerFlagCallbackFunc, dynamicLinkerFlagCallback, globalIncludeDirCallback); + if(!buildResult) + return buildResult; + } + + return Result<bool>::Ok(true); + } Result<bool> Ninja::build(const SibsConfig &config, const _tinydir_char_t *savePath, LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallback, GlobalIncludeDirCallbackFunc globalIncludeDirCallback) { @@ -405,7 +431,7 @@ namespace backend #endif // TODO: Somehow check loading order, because it has to be correct to work.. Or does it for dynamic libraries? - // Anyways it's required for static libraries (especially on Windows) + // Anyways it's required for static libraries for (const string &binaryDependency : binaryDependencies) { allLinkerFlags += " "; @@ -413,6 +439,7 @@ namespace backend } string staticLinkerFlags; + auto parentProjStaticLinkerFlagCallbackFunc = staticLinkerFlagCallbackFunc; if (!staticLinkerFlagCallbackFunc || libraryType == LibraryType::DYNAMIC) { staticLinkerFlagCallbackFunc = [&staticLinkerFlags](const string &linkerFlag) @@ -423,8 +450,8 @@ namespace backend } string dynamicLinkerFlags; - // TODO: Do same for cmake - if (!sourceFiles.empty()) + auto parentProjDynamicLinkerFlagCallbackFunc = dynamicLinkerFlagCallback; + if(!dynamicLinkerFlagCallback || libraryType != LibraryType::STATIC) { dynamicLinkerFlagCallback = [&dynamicLinkerFlags](const string &linkerFlag) { @@ -439,6 +466,10 @@ namespace backend cflags += " "; cflags += dependencyCflags; }; + + Result<bool> buildSubProjectResult = buildSubProjects(staticLinkerFlagCallbackFunc, dynamicLinkerFlagCallback, globalIncludeDirCallback); + if(!buildSubProjectResult) + return buildSubProjectResult; Result<bool> linkerFlags = getLinkerFlags(config, staticLinkerFlagCallbackFunc, dynamicLinkerFlagCallback, globalIncludeDirCallback, cflagsCallbackFunc); if (linkerFlags.isErr()) @@ -739,13 +770,13 @@ namespace backend objectNames.emplace_back(objectName); } - string projectGeneratedBinary; + string projectGeneratedBinaryFlags; if (!sourceFiles.empty()) { - projectGeneratedBinary = allLinkerFlags; - projectGeneratedBinary += " \""; + string projectGeneratedBinary = "\""; projectGeneratedBinary += savePathUtf8; projectGeneratedBinary += "/"; + switch (libraryType) { case LibraryType::EXECUTABLE: @@ -776,7 +807,11 @@ namespace backend result += allLinkerFlags; } result += "\n\n"; + projectGeneratedBinary += config.getPackageName(); + #if OS_FAMILY == OS_FAMILY_WINDOWS + projectGeneratedBinary += ".exe"; + #endif break; } case LibraryType::STATIC: @@ -804,6 +839,11 @@ namespace backend break; } } + + projectGeneratedBinary += "\""; + if(parentProjStaticLinkerFlagCallbackFunc) + parentProjStaticLinkerFlagCallbackFunc(projectGeneratedBinary); + break; } case LibraryType::DYNAMIC: @@ -841,13 +881,19 @@ namespace backend //result += " '-Wl,--no-whole-archive'"; } result += "\n\n"; + + projectGeneratedBinary += "\""; + if(parentProjDynamicLinkerFlagCallbackFunc) + parentProjDynamicLinkerFlagCallbackFunc(projectGeneratedBinary); + break; } default: assert(false); return Result<bool>::Err("Unexpected error"); } - projectGeneratedBinary += "\""; + + projectGeneratedBinaryFlags = allLinkerFlags + " " + projectGeneratedBinary; Result<bool> fileOverwriteResult = sibs::fileOverwrite(ninjaBuildFilePath.c_str(), sibs::StringView(result.data(), result.size())); if (fileOverwriteResult.isErr()) @@ -863,30 +909,14 @@ namespace backend // TODO: If tests are being run (sibs test) and root project is an executable, do not run compile (above code) as executable. // Sibs test will compile root project as dynamic library so you end up compiling the project twice, first as an executable and then as a dynamic library. // Even if the root project has been built before and there is cached object, it will take a few seconds to run compile - Result<bool> buildTestResult = buildTests(projectGeneratedBinary, config, savePath, dependencyExportIncludeDirs); + Result<bool> buildTestResult = buildTests(projectGeneratedBinaryFlags, config, savePath, dependencyExportIncludeDirs); if(!buildTestResult) return buildTestResult; return Result<bool>::Ok(true); } - // TODO: Add "c++" file extension, seems to be used in some places? - const _tinydir_char_t *sourceFileExtensions[] = { TINYDIR_STRING("c"), TINYDIR_STRING("cc"), TINYDIR_STRING("cpp"), TINYDIR_STRING("cxx") }; - bool isSourceFile(tinydir_file *file) - { - if(!file->is_reg) - return false; - - for(const _tinydir_char_t *sourceFileExtension : sourceFileExtensions) - { - if(_tinydir_strcmp(sourceFileExtension, file->extension) == 0) - return true; - } - - return false; - } - - Result<bool> Ninja::buildTests(const std::string &projectGeneratedBinary, const SibsConfig &config, const _tinydir_char_t *savePath, const string &parentDependencyExportIncludeDirs) + Result<bool> Ninja::buildTests(const std::string &projectGeneratedBinaryFlags, const SibsConfig &config, const _tinydir_char_t *savePath, const string &parentDependencyExportIncludeDirs) { if(testSourceDirs.empty() || !config.shouldBuildTests()) return Result<bool>::Ok(true); @@ -940,12 +970,12 @@ namespace backend backend::Ninja ninja; ninja.addGlobalIncludeDirs(parentExportIncludeDirs); - if(!projectGeneratedBinary.empty()) - ninja.addDependency(projectGeneratedBinary); + if(!projectGeneratedBinaryFlags.empty()) + ninja.addDependency(projectGeneratedBinaryFlags); // TODO: Use same source file finder as in main.cpp walkDirFilesRecursive(testSourceDirNative.c_str(), [&ninja, &sibsTestConfig](tinydir_file *file) { - if (isSourceFile(file)) + if (backend::BackendUtils::isSourceFile(file)) { string filePathUtf8 = toUtf8(file->path + sibsTestConfig.getProjectPath().size() + 1); ninja.addSourceFile(filePathUtf8.c_str()); diff --git a/backend/ninja/Ninja.hpp b/backend/ninja/Ninja.hpp index 8411137..7bbff51 100644 --- a/backend/ninja/Ninja.hpp +++ b/backend/ninja/Ninja.hpp @@ -11,6 +11,24 @@ namespace backend { + class Ninja; + + struct NinjaSubProject + { + Ninja *subProject; + sibs::SibsConfig *config; + sibs::FileString buildPath; + + NinjaSubProject() : subProject(nullptr), config(nullptr) {} + NinjaSubProject(Ninja *_subProject, sibs::SibsConfig *_config, sibs::FileString &&_buildPath) : + subProject(_subProject), + config(_config), + buildPath(move(_buildPath)) + { + + } + }; + class Ninja { public: @@ -27,10 +45,12 @@ namespace backend void addSourceFile(const char *filepath); void addTestSourceDir(const char *dir); void addDependency(const std::string &binaryFile); + void addSubProject(Ninja *subProject, sibs::SibsConfig *config, sibs::FileString &&buildPath); 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, sibs::GlobalIncludeDirCallbackFunc globalIncludeDirCallback = nullptr); private: - sibs::Result<bool> buildTests(const std::string &projectGeneratedBinary, const sibs::SibsConfig &config, const _tinydir_char_t *savePath, const std::string &parentDependencyExportIncludeDirs); + sibs::Result<bool> buildSubProjects(sibs::LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, sibs::LinkerFlagCallbackFunc dynamicLinkerFlagCallback, sibs::GlobalIncludeDirCallbackFunc globalIncludeDirCallback); + sibs::Result<bool> buildTests(const std::string &projectGeneratedBinaryFlags, const sibs::SibsConfig &config, const _tinydir_char_t *savePath, const std::string &parentDependencyExportIncludeDirs); bool containsSourceFile(const std::string &filepath) const; bool containsTestSourceDir(const std::string &dir) const; bool containsDependency(const std::string &dependency) const; @@ -41,6 +61,7 @@ namespace backend std::vector<std::string> sourceFiles; std::vector<std::string> testSourceDirs; std::vector<std::string> binaryDependencies; + std::vector<NinjaSubProject> subProjects; }; } |