ENH: reimplement Foam::dlOpen() for macOS (#2801)
- The Apple SIP (System Integrity Protection) clears environment variables, which affects the behaviour of dynamic library loading (the DYLD_LIBRARY_PATH env variable). OpenFOAM shadows this variable as FOAM_LD_LIBRARY_PATH, which has been used to restore DYLD_LIBRARY_PATH (eg, in RunFunctions script). However, this solution is not quite complete, as it (a) requires sourcing of RunFunctions file, (b) additional errors appear depending on a user workflow. This changeset alleviates the problem by also iterating through paths stored in the shadow variable when loading dynamic libraries (if the DYLD_LIBRARY_PATH is empty).
This commit is contained in:
parent
83b1ebee6f
commit
f584ec97d0
@ -23,13 +23,6 @@
|
||||
# If dispatching via foamExec
|
||||
foamExec="$WM_PROJECT_DIR/bin/tools/foamExec"
|
||||
|
||||
# Darwin workaround - SIP clearing DYLD_LIBRARY_PATH variable
|
||||
if [ -n "$FOAM_LD_LIBRARY_PATH" ] && [ -z "$DYLD_LIBRARY_PATH" ]
|
||||
then
|
||||
export DYLD_LIBRARY_PATH="$FOAM_LD_LIBRARY_PATH"
|
||||
fi
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
usage() {
|
||||
|
@ -25,13 +25,6 @@
|
||||
# Basic sanity checks
|
||||
[ -d "$FOAM_TUTORIALS" ] || echo "No OpenFOAM tutorials? : $FOAM_TUTORIALS" 1>&2
|
||||
|
||||
# Darwin workaround - SIP clearing DYLD_LIBRARY_PATH variable
|
||||
if [ -n "$FOAM_LD_LIBRARY_PATH" ] && [ -z "$DYLD_LIBRARY_PATH" ]
|
||||
then
|
||||
export DYLD_LIBRARY_PATH="$FOAM_LD_LIBRARY_PATH"
|
||||
fi
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
#
|
||||
|
@ -41,6 +41,7 @@ Description
|
||||
#include "timer.H"
|
||||
#include "DynamicList.H"
|
||||
#include "CStringList.H"
|
||||
#include "stringOps.H"
|
||||
#include "IOstreams.H"
|
||||
#include "Pstream.H"
|
||||
|
||||
@ -108,6 +109,52 @@ static inline void redirects(const bool bg)
|
||||
}
|
||||
|
||||
|
||||
// Library loading is normally simply via dlopen(),
|
||||
// but SIP (System Integrity Protection) on Apple will generally
|
||||
// clear out the DYLD_LIBRARY_PATH set from shell scripts.
|
||||
// We thus have FOAM_LD_LIBRARY_PATH as a shadow parameter and use
|
||||
// that to attempt loading ourselves
|
||||
static inline void* loadLibrary(const Foam::fileName& libName)
|
||||
{
|
||||
constexpr int ldflags = (RTLD_LAZY|RTLD_GLOBAL);
|
||||
|
||||
#ifdef __APPLE__
|
||||
const char* normal = nullptr;
|
||||
const char* shadow = nullptr;
|
||||
|
||||
if
|
||||
(
|
||||
!libName.isAbsolute()
|
||||
&& ((normal = ::getenv("DYLD_LIBRARY_PATH")) == nullptr || !*normal)
|
||||
&& ((shadow = ::getenv("FOAM_LD_LIBRARY_PATH")) != nullptr && *shadow)
|
||||
)
|
||||
{
|
||||
// SIP appears to have cleared DYLD_LIBRARY_PATH but the
|
||||
// shadow parameter is available
|
||||
|
||||
const Foam::string ldPaths(shadow);
|
||||
const auto paths = Foam::stringOps::split<Foam::string>(ldPaths, ':');
|
||||
|
||||
for (const auto& p : paths)
|
||||
{
|
||||
if (p.length()) // Split removes empty, but be paranoid
|
||||
{
|
||||
const Foam::fileName fullPath(p.str()/libName);
|
||||
void* handle = ::dlopen(fullPath.c_str(), ldflags);
|
||||
if (handle)
|
||||
{
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Regular loading
|
||||
return ::dlopen(libName.c_str(), ldflags);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Local Classes * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
@ -1752,16 +1799,13 @@ int Foam::system(const Foam::UList<Foam::string>& command, const bool bg)
|
||||
|
||||
void* Foam::dlOpen(const fileName& libName, const bool check)
|
||||
{
|
||||
constexpr int ldflags = (RTLD_LAZY|RTLD_GLOBAL);
|
||||
|
||||
if (POSIX::debug)
|
||||
{
|
||||
std::cout
|
||||
<< "dlOpen(const fileName&)"
|
||||
<< " : dlopen of " << libName << std::endl;
|
||||
<< "dlopen() of " << libName << std::endl;
|
||||
}
|
||||
|
||||
void* handle = ::dlopen(libName.c_str(), ldflags);
|
||||
void* handle = loadLibrary(libName);
|
||||
|
||||
if (!handle)
|
||||
{
|
||||
@ -1771,13 +1815,12 @@ void* Foam::dlOpen(const fileName& libName, const bool check)
|
||||
{
|
||||
// Try with 'lib' prefix
|
||||
libso = "lib" + libName;
|
||||
handle = ::dlopen(libso.c_str(), ldflags);
|
||||
handle = loadLibrary(libso);
|
||||
|
||||
if (POSIX::debug)
|
||||
{
|
||||
std::cout
|
||||
<< "dlOpen(const fileName&)"
|
||||
<< " : dlopen of " << libso << std::endl;
|
||||
<< " dlopen() as " << libso << std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -1790,13 +1833,12 @@ void* Foam::dlOpen(const fileName& libName, const bool check)
|
||||
if (!handle && !libso.has_ext(EXT_SO))
|
||||
{
|
||||
libso.replace_ext(EXT_SO);
|
||||
handle = ::dlopen(libso.c_str(), ldflags);
|
||||
handle = loadLibrary(libso);
|
||||
|
||||
if (POSIX::debug)
|
||||
{
|
||||
std::cout
|
||||
<< "dlOpen(const fileName&)"
|
||||
<< " : dlopen of " << libso << std::endl;
|
||||
<< " dlopen() as " << libso << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1810,8 +1852,7 @@ void* Foam::dlOpen(const fileName& libName, const bool check)
|
||||
if (POSIX::debug)
|
||||
{
|
||||
std::cout
|
||||
<< "dlOpen(const fileName&)"
|
||||
<< " : dlopen of " << libName
|
||||
<< "dlopen() of " << libName
|
||||
<< " handle " << handle << std::endl;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user