aboutsummaryrefslogtreecommitdiff
path: root/backend/ninja/Ninja.cpp
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2018-03-21 14:56:51 +0100
committerdec05eba <dec05eba@protonmail.com>2018-03-21 14:58:31 +0100
commit23117906c571714b0b55caf35cf9f876d1f9fa2e (patch)
tree21574306de1efb6eafd2af48f5188bf9e3550dd8 /backend/ninja/Ninja.cpp
parentb44ff4ec7d2c2458aab04b5daf79134e5d284f6e (diff)
Add sub projects (should be used with git submodules)
Fix issue where static lib dependencies are not built correctly because their dynamic lib dependencies are not propagated to dependant project
Diffstat (limited to 'backend/ninja/Ninja.cpp')
-rw-r--r--backend/ninja/Ninja.cpp88
1 files changed, 59 insertions, 29 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());