diff options
Diffstat (limited to 'backend/ninja')
-rw-r--r-- | backend/ninja/Ninja.cpp | 68 |
1 files changed, 66 insertions, 2 deletions
diff --git a/backend/ninja/Ninja.cpp b/backend/ninja/Ninja.cpp index 8b92af1..4495bd4 100644 --- a/backend/ninja/Ninja.cpp +++ b/backend/ninja/Ninja.cpp @@ -6,6 +6,7 @@ #include "../../include/PkgConfig.hpp" #include "../../include/GlobalLib.hpp" #include <ninja/Ninja.hpp> +#include <algorithm> using namespace std; using namespace sibs; @@ -636,6 +637,62 @@ namespace backend return result; } +#if OS_FAMILY == OS_FAMILY_WINDOWS + struct PathSeperatorMatcher + { + bool operator()(char c) const + { + return c == '/' || c == '\\'; + } + }; +#else + struct PathSeperatorMatcher + { + bool operator()(char c) const + { + return c == '/'; + } + }; +#endif + + static FileString getFileParentDirectory(const FileString &filepath) + { + auto it = find_if(filepath.rbegin(), filepath.rend(), PathSeperatorMatcher()); + if(it == filepath.rend()) + return TINYDIR_STRING(""); + else + return filepath.substr(0, it.base().base() - &filepath[0]); + } + + static string extractDynamicLibDirsFromLinkerFlags(const vector<string> &linkerFlags) + { + string result; + for(const string &flag : linkerFlags) + { + FileString flagNative; + if(flag.size() >= 2 && (flag[0] == '\'' || flag[0] == '"') && (flag.back() == '\'' || flag.back() == '"')) + flagNative = toFileString(StringView(&flag[1], flag.size() - 2)); + else + flagNative = toFileString(flag); + + if(getFileType(flagNative.c_str()) == FileType::REGULAR) + { + Result<FileString> libFullPath = getRealPath(flagNative.c_str()); + if(libFullPath) + { + FileString libDir = getFileParentDirectory(libFullPath.unwrap()); + if(!libDir.empty()) + { + if(!result.empty()); + result += ":"; + result += toUtf8(libDir); + } + } + } + } + return result; + } + Result<bool> Ninja::build(const SibsConfig &config, const _tinydir_char_t *savePath, LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallback, GlobalIncludeDirCallbackFunc globalIncludeDirCallback) { bool isCCompilerClang = false; @@ -723,6 +780,7 @@ namespace backend } vector<string> linkerFlags; + vector<string> dynamicLinkerFlags; auto parentProjStaticLinkerFlagCallbackFunc = staticLinkerFlagCallbackFunc; if (!staticLinkerFlagCallbackFunc || libraryType == LibraryType::DYNAMIC) @@ -736,11 +794,12 @@ namespace backend auto parentProjDynamicLinkerFlagCallbackFunc = dynamicLinkerFlagCallback; if(!dynamicLinkerFlagCallback || libraryType != LibraryType::STATIC) { - dynamicLinkerFlagCallback = [&linkerFlags, &parentProjDynamicLinkerFlagCallbackFunc](const string &linkerFlag) + dynamicLinkerFlagCallback = [&linkerFlags, &dynamicLinkerFlags, &parentProjDynamicLinkerFlagCallbackFunc](const string &linkerFlag) { if(parentProjDynamicLinkerFlagCallbackFunc) parentProjDynamicLinkerFlagCallbackFunc(linkerFlag); linkerFlags.push_back(linkerFlag); + dynamicLinkerFlags.push_back(linkerFlag); }; } @@ -1161,6 +1220,7 @@ namespace backend { case Compiler::GCC: { + string rpath = extractDynamicLibDirsFromLinkerFlags(dynamicLinkerFlags); buildExeArgs.insert(buildExeArgs.end(), { ninja::NinjaArg::createRaw("ccache"), ninja::NinjaArg::createRaw(usesCppFiles ? "c++" : "cc"), @@ -1170,6 +1230,9 @@ namespace backend ninja::NinjaArg::createRaw(noUndefinedFlag) }); + if(!rpath.empty()) + buildExeArgs.push_back(ninja::NinjaArg("-Wl,-rpath," + rpath)); + if(config.getSanitize()) { buildExeArgs.insert(buildExeArgs.end(), { @@ -1364,7 +1427,8 @@ namespace backend ninja::NinjaArg::createRaw("ccache"), ninja::NinjaArg::createRaw(usesCppFiles ? "c++" : "cc"), ninja::NinjaArg::createRaw("$in"), - ninja::NinjaArg::createRaw("-shared"), + ninja::NinjaArg::createRaw("-shared"), + ninja::NinjaArg("-Wl,-soname," + generatedFile), ninja::NinjaArg::createRaw("-o"), ninja::NinjaArg::createRaw("$out"), ninja::NinjaArg::createRaw(noUndefinedFlag) |