Skip to content
Snippets Groups Projects
Commit f584ec97 authored by Alexey Matveichev's avatar Alexey Matveichev Committed by Mark OLESEN
Browse files

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).
parent 83b1ebee
Branches
Tags
No related merge requests found
......@@ -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;
}
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment