mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
COMP: force dlOpen for windows application binaries (#1238)
- when windows portable executables (.exe or .dll) files are loaded,
their dependent libraries not fully loaded. For OpenFOAM this means
that the static constructors which are responsible for populating
run-time selection tables are not triggered, and most of the run-time
selectable models will simply not be available.
Possible Solution
=================
Avoid this problem by defining an additional library symbol such as
the following:
extern "C" void libName_Load() {}
in the respective library, and tag this symbol as 'unresolved' for
the linker so that it will attempt to resolve it at run-time by
loading the known libraries until it finds it. The link line would
resemble the following:
-L/some/path -llibName -ulibName_Load
Pros:
- Allows precise control of forced library loading
Cons:
- Moderately verbose adjustment of some source files (even with macro
wrapping for the declaration).
- Adjustment of numerous Make/options files and somewhat ad hoc
in nature.
- Requires additional care when implementing future libraries and/or
applications.
- This is the solution taken by the symscape patches (Richard Smith)
Possible Solution
=================
Avoid this problem by simply force loading all linked libraries.
This is done by "scraping" the information out of the respective
Make/options file (after pre-processing) and using that to define
the library list that will be passed to Foam::dlOpen() at run-time.
Pros:
- One-time (very) minimal adjustment of the sources and wmake toolchain
- Automatically applies to future applications
Cons:
- Possibly larger memory footprint of application (since all dependent
libraries are loaded).
- Possible impact on startup time (while loading libraries)
- More sensitive to build failures. Since the options files are
read and modified based on the existence of the dependent
libraries as a preprocessor step, if the libraries are initially
unavailable for the first attempt at building the application,
the dependencies will be inaccurate for later (successful) builds.
- This is solution taken by the bluecape patches (Bruno Santos)
Adopted Solution
================
The approach taken by Bruno was adopted in a modified form since
this appears to be the most easily maintained.
Additional Notes
================
It is always possible to solve this problem by defining a corresponding
'libs (...)' entry in the case system/controlDict, which forces a dlOpen
of the listed libraries. This is obviously less than ideal for large-scale
changes, but can work to resolve an individual problem.
The peldd utility (https://github.com/gsauthof/pe-util), which is
also packaged as part of MXE could provide yet another alternative.
Like ldd it can be used to determine the library dependencies of
binaries or libraries. This information could be used to define an
additional load layer for Windows.
This commit is contained in:
committed by
Andrew Heather
parent
882d7310d1
commit
66a100997f
@ -2307,7 +2307,9 @@ int main(int argc, char *argv[])
|
|||||||
// ~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~
|
||||||
// (replacement for setRootCase that does not abort)
|
// (replacement for setRootCase that does not abort)
|
||||||
|
|
||||||
Foam::argList args(argc, argv);
|
argList args(argc, argv);
|
||||||
|
#include "foamDlOpenLibs.H"
|
||||||
|
|
||||||
const bool reconstruct = args.found("reconstruct");
|
const bool reconstruct = args.found("reconstruct");
|
||||||
const bool writeCellDist = args.found("cellDist");
|
const bool writeCellDist = args.found("cellDist");
|
||||||
const bool dryrun = args.found("dry-run");
|
const bool dryrun = args.found("dry-run");
|
||||||
|
|||||||
@ -276,11 +276,11 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
|
|
||||||
argList args(argc, argv);
|
argList args(argc, argv);
|
||||||
|
|
||||||
if (!args.check())
|
if (!args.check())
|
||||||
{
|
{
|
||||||
FatalError.exit();
|
FatalError.exit();
|
||||||
}
|
}
|
||||||
|
#include "foamDlOpenLibs.H"
|
||||||
|
|
||||||
fileName rootDirTarget(args.rootPath());
|
fileName rootDirTarget(args.rootPath());
|
||||||
fileName caseDirTarget(args.globalCaseName());
|
fileName caseDirTarget(args.globalCaseName());
|
||||||
|
|||||||
@ -208,6 +208,7 @@ int main(int argc, char *argv[])
|
|||||||
);
|
);
|
||||||
|
|
||||||
argList args(argc, argv);
|
argList args(argc, argv);
|
||||||
|
#include "foamDlOpenLibs.H"
|
||||||
|
|
||||||
fileName rootDirTarget(args.rootPath());
|
fileName rootDirTarget(args.rootPath());
|
||||||
fileName caseDirTarget(args.globalCaseName());
|
fileName caseDirTarget(args.globalCaseName());
|
||||||
|
|||||||
12
src/OpenFOAM/include/foamDlOpenLibs.H
Normal file
12
src/OpenFOAM/include/foamDlOpenLibs.H
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// Force dlOpen of FOAM_DLOPEN_LIBS,
|
||||||
|
// which is a comma-separated list of quoted library names
|
||||||
|
// (eg, "finiteVolume","fvOptions","meshTools")
|
||||||
|
//
|
||||||
|
// Principally for Windows applications where library loading may otherwise
|
||||||
|
// be incomplete.
|
||||||
|
|
||||||
|
#ifdef FOAM_DLOPEN_LIBS
|
||||||
|
|
||||||
|
Foam::dlOpen({ FOAM_DLOPEN_LIBS }, false); // Silent on errors
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -15,3 +15,6 @@ if (!args.checkRootCase())
|
|||||||
// {
|
// {
|
||||||
// Foam::FatalError.exit();
|
// Foam::FatalError.exit();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// Force dlOpen of FOAM_DLOPEN_LIBS (principally for Windows applications)
|
||||||
|
#include "foamDlOpenLibs.H"
|
||||||
|
|||||||
@ -35,6 +35,12 @@ SFILES = $(OBJECTS_DIR)/sourceFiles
|
|||||||
|
|
||||||
sinclude $(OPTIONS)
|
sinclude $(OPTIONS)
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
# Directory containing the wmake scripts
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
WM_SCRIPTS = $(WM_DIR)/scripts
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
# Declare dependency of all make system files on FILES
|
# Declare dependency of all make system files on FILES
|
||||||
@ -45,7 +51,9 @@ all : $(OPTIONS) $(SFILES) $(VARS)
|
|||||||
|
|
||||||
$(OPTIONS) : $(MAKE_DIR)/options
|
$(OPTIONS) : $(MAKE_DIR)/options
|
||||||
@$(CPP) $(GFLAGS) $(MAKE_DIR)/options | sed -e 's@ *@ @g' > $(OPTIONS)
|
@$(CPP) $(GFLAGS) $(MAKE_DIR)/options | sed -e 's@ *@ @g' > $(OPTIONS)
|
||||||
|
ifeq ("$(WM_OSTYPE)","MSwindows")
|
||||||
|
@$(WM_SCRIPTS)/wmakeWindowsDlOpenLibs $(OPTIONS) >> $(OPTIONS)
|
||||||
|
endif
|
||||||
|
|
||||||
$(SFILES): $(MAKE_DIR)/files
|
$(SFILES): $(MAKE_DIR)/files
|
||||||
@$(CPP) $(GFLAGS) $(MAKE_DIR)/files | sed -e 's@ *@ @g' > $(FILES)
|
@$(CPP) $(GFLAGS) $(MAKE_DIR)/files | sed -e 's@ *@ @g' > $(FILES)
|
||||||
|
|||||||
101
wmake/scripts/wmakeWindowsDlOpenLibs
Executable file
101
wmake/scripts/wmakeWindowsDlOpenLibs
Executable file
@ -0,0 +1,101 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
# ========= |
|
||||||
|
# \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
# \\ / O peration |
|
||||||
|
# \\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
|
||||||
|
# \\/ M anipulation |
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# | Copyright (C) 2011-2017 blueCAPE Lda
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
# License
|
||||||
|
# This file is part of OpenFOAM.
|
||||||
|
#
|
||||||
|
# OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
# for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# Script
|
||||||
|
# wmakeWindowsDlOpenLibs
|
||||||
|
#
|
||||||
|
# Usage
|
||||||
|
# wmakeWindowsDlOpenLibs <build/applications/.../options>
|
||||||
|
#
|
||||||
|
# Description
|
||||||
|
# Extract library dependencies from the EXE_LIBS entry for Windows
|
||||||
|
# applications and emit as FOAM_DLOPEN_LIBS for use with setRootCase.H
|
||||||
|
# Forcibly dlOpen'ing these libraries ensures that they are truly loaded
|
||||||
|
# for the windows application binary.
|
||||||
|
#
|
||||||
|
# An alternative means is to define external entry points into particular
|
||||||
|
# libraries and linking with '-u symbol', which would possibly have a lower
|
||||||
|
# overhead but is more code-intrusive and somewhat ad hoc.
|
||||||
|
#
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
optionsFile="$1"
|
||||||
|
|
||||||
|
[ "$#" -gt 0 ] || exit 1
|
||||||
|
[ -f "$optionsFile" ] || exit 2
|
||||||
|
[ -r "$optionsFile" ] || exit 2
|
||||||
|
|
||||||
|
# Representative exeName from the build path (for messages only)
|
||||||
|
# Eg, build/.../basic/laplacianFoam/options -> laplacianFoam
|
||||||
|
|
||||||
|
exeName="${optionsFile%/options}" # Strip trailing '/options'
|
||||||
|
exeName="${exeName##*/}" # Strip leading path
|
||||||
|
|
||||||
|
# Use only OpenFOAM-related libraries that we will can actually find
|
||||||
|
hasLib()
|
||||||
|
{
|
||||||
|
libFile="lib${1}.dll" # NB: Windows only (.dll)
|
||||||
|
|
||||||
|
[ -e "$FOAM_LIBBIN/$libFile" ] || \
|
||||||
|
[ -e "$FOAM_USER_LIBBIN/$libFile" ] || \
|
||||||
|
[ -e "$FOAM_LIBBIN/$FOAM_MPI/$libFile" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# After the cpp stage, the EXE_LIBS (if they exist) will be on a single line
|
||||||
|
# Extract EXE_LIBS = -labc ..., ignoring -L and .o entries
|
||||||
|
#
|
||||||
|
# The libNames output comprises comma-separated quoted strings
|
||||||
|
# "lib1","lib2","libN"
|
||||||
|
# these are suitable for C-code or a std::initializer_list<fileName> etc.
|
||||||
|
|
||||||
|
# The $() sub-shell is unquoted to ensure we get whitespace splitting
|
||||||
|
# and read individual words, not lines.
|
||||||
|
unset libNames
|
||||||
|
for lib in $(sed -ne 's@^.*EXE\_LIBS.*=[ ]*@@p' "$optionsFile")
|
||||||
|
do
|
||||||
|
case "$lib" in
|
||||||
|
(*.o | *')'*)
|
||||||
|
;;
|
||||||
|
|
||||||
|
(-l[0-9A-Za-z]*)
|
||||||
|
lib="${lib#-l}"
|
||||||
|
hasLib "$lib" && libNames="$libNames${libNames:+,}\"$lib\""
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
## Debugging: echo "$exeName: libNames=$libNames" 1>&2
|
||||||
|
|
||||||
|
# Emit define for using with Foam::dlOpen()
|
||||||
|
if [ -n "$libNames" ]
|
||||||
|
then
|
||||||
|
echo "Adding dlOpen(dll) list for $exeName" 1>&2
|
||||||
|
echo "EXE_INC += -DFOAM_DLOPEN_LIBS='$libNames'"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0 # clean exit
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
Reference in New Issue
Block a user