- give precedence to ~openmp (-no-openmp) over +openmp (-openmp) in the general rules and in the Makefile. This makes it robuster when specifying +openmp in general, but ~openmp for specific build components. - disable openmp for OSspecific and Pstream components. Neither should contain any openmp code anyhow. Additionally, since OSspecific is generally built as a static object, it can become problematic (eg, with AMD ROCm) if the compiler generates information that openmp is required but then uses static linkage.
467 lines
11 KiB
Bash
467 lines
11 KiB
Bash
#----------------------------------*-sh-*--------------------------------------
|
|
# ========= |
|
|
# \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
# \\ / O peration |
|
|
# \\ / A nd | www.openfoam.com
|
|
# \\/ M anipulation |
|
|
#------------------------------------------------------------------------------
|
|
# Copyright (C) 2015-2016 OpenFOAM Foundation
|
|
# Copyright (C) 2018-2023 OpenCFD Ltd.
|
|
#------------------------------------------------------------------------------
|
|
# License
|
|
# This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
|
|
#
|
|
# Script
|
|
# wmakeFunctions
|
|
#
|
|
# Description
|
|
# Support functions for wmake infrastructure.
|
|
# For example, check environment, find .dep and .o files, various
|
|
# wrappers when making libraries.
|
|
#
|
|
#------------------------------------------------------------------------------
|
|
|
|
# Ensure these variables are always defined
|
|
MakeDir=Make
|
|
: "${Script:=wmakeFunctions}"
|
|
|
|
# Environment defaults
|
|
if [ -z "$WM_DIR" ] && [ -n "$WM_PROJECT_DIR" ]
|
|
then
|
|
WM_DIR="$WM_PROJECT_DIR/wmake"
|
|
fi
|
|
[ -n "$WM_DIR" ] && export WM_DIR
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
# Check environment variables
|
|
checkEnv()
|
|
{
|
|
local check failed
|
|
|
|
# Possibly redundant check for WM_DIR
|
|
for check in WM_PROJECT_DIR WM_DIR WM_OPTIONS
|
|
do
|
|
eval test -n "\$$check" || failed="$failed $check"
|
|
done
|
|
|
|
if [ -n "$failed" ]
|
|
then
|
|
echo "$Script error: OpenFOAM environment variable(s) not set" 1>&2
|
|
echo " $failed" 1>&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
|
|
# (api) from WM_DIR/rules/General/general
|
|
# - extract WM_VERSION = OPENFOAM=<digits>
|
|
getApiOpenFOAM()
|
|
{
|
|
local rulesFile="$WM_DIR/rules/General/general"
|
|
local value
|
|
|
|
if [ -n "$WM_DIR" ] && [ -f "$rulesFile" ]
|
|
then
|
|
value="$(sed -ne 's@^ *WM_VERSION *= *OPENFOAM=\([0-9][0-9]*\).*@\1@p' "$rulesFile" 2>/dev/null)"
|
|
fi
|
|
|
|
if [ -n "$value" ]
|
|
then
|
|
echo "$value"
|
|
else
|
|
echo "Could not extract OpenFOAM API value" 1>&2
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
|
|
# Set FOAM_MODULE_PREFIX according to
|
|
# - absolute/relative path
|
|
# - predefined type (u,user | g,group | o,openfoam)
|
|
setModulePrefix()
|
|
{
|
|
export FOAM_MODULE_PREFIX="$1"
|
|
case "$FOAM_MODULE_PREFIX" in
|
|
# Prefix: user
|
|
(u | user) FOAM_MODULE_PREFIX="${FOAM_USER_LIBBIN%/*}" ;;
|
|
|
|
# Prefix: group
|
|
(g | group) FOAM_MODULE_PREFIX="${FOAM_SITE_LIBBIN%/*}" ;;
|
|
|
|
# Prefix: openfoam (other)
|
|
(o | openfoam) FOAM_MODULE_PREFIX="${FOAM_LIBBIN%/*}" ;;
|
|
|
|
# Prefix: false | none (ie, 'disabled')
|
|
(false | none) FOAM_MODULE_PREFIX=false ;;
|
|
|
|
# Prefix: directory (absolute or relative)
|
|
(*)
|
|
: "${FOAM_MODULE_PREFIX:=/usr/local}" # Fallback (autoconf-like)
|
|
|
|
# Require absolute path
|
|
[ "${FOAM_MODULE_PREFIX#/}" != "${FOAM_MODULE_PREFIX}" ] || \
|
|
FOAM_MODULE_PREFIX="${PWD}/${FOAM_MODULE_PREFIX}"
|
|
;;
|
|
esac
|
|
|
|
# Avoid potential conflicts
|
|
unset FOAM_MODULE_APPBIN FOAM_MODULE_LIBBIN
|
|
echo "Module prefix = ${FOAM_MODULE_PREFIX:-[]}" 1>&2
|
|
}
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
# Return the absolute (physical) path for a directory or
|
|
# for a file's parent directory
|
|
# expandPath dirName
|
|
# expandPath fileName
|
|
#
|
|
# Output:
|
|
# - the expanded path name
|
|
expandPath()
|
|
{
|
|
if [ -d "$1" ]
|
|
then
|
|
(cd "$1" && pwd -P)
|
|
elif [ -n "$1" ]
|
|
then
|
|
(cd "$(dirname "$1")" && pwd -P)
|
|
else
|
|
pwd -P
|
|
fi
|
|
}
|
|
|
|
|
|
# Find the target directory, which contains a Make/ directory
|
|
# search upwards in its parent directories, but stopping
|
|
# when it hits the project root, home, or the file-system root
|
|
#
|
|
# findTarget dirName
|
|
#
|
|
# Output:
|
|
# - the relative target directory
|
|
#
|
|
# Global variables used:
|
|
# - WM_PROJECT_DIR, HOME
|
|
findTarget()
|
|
{
|
|
local project=$(expandPath "$WM_PROJECT_DIR")
|
|
local home=$(expandPath "$HOME")
|
|
local reldir="${1:-.}"
|
|
local absdir=$(expandPath "$reldir")
|
|
|
|
while [ -n "$absdir" ]
|
|
do
|
|
case "$absdir" in
|
|
("$project" | "$home" | /)
|
|
break
|
|
;;
|
|
esac
|
|
|
|
if [ -d "$reldir/Make" ]
|
|
then
|
|
echo "$reldir"
|
|
return 0
|
|
else
|
|
# Check parent directory
|
|
absdir="${absdir%/*}"
|
|
reldir="$reldir/.."
|
|
fi
|
|
done
|
|
|
|
echo "Error: no Make directory for $(expandPath "$1")" 1>&2
|
|
echo 1>&2
|
|
return 1
|
|
}
|
|
|
|
|
|
# Change to 'MakeDir' parent
|
|
# - uses 'MakeDir' for its input
|
|
#
|
|
# Side-effects:
|
|
# - unsets targetType
|
|
cdSource()
|
|
{
|
|
local dir
|
|
if [ ! -d "$MakeDir" ]
|
|
then
|
|
echo "$Script: '$MakeDir' directory does not exist in $PWD" 1>&2
|
|
echo " Searching up directories tree for Make directory" 1>&2
|
|
|
|
dir=$(findTarget .) || exit 1 # Fatal
|
|
cd "$dir" 2>/dev/null || {
|
|
echo "$Script error: could not change to directory '$dir'" 1>&2
|
|
exit 1
|
|
}
|
|
unset targetType
|
|
fi
|
|
|
|
[ -r "$MakeDir"/files ] || {
|
|
echo "$Script error: file '$MakeDir/files' does not exist in $PWD" 1>&2
|
|
exit 1
|
|
}
|
|
}
|
|
|
|
|
|
# Find the object directory
|
|
# findObjectDir dirName
|
|
# findObjectDir fileName
|
|
#
|
|
# Output:
|
|
# - the objectsDir
|
|
#
|
|
# Global variables used:
|
|
# - FOAM_BUILDROOT, WM_PROJECT_DIR, WM_OPTIONS
|
|
findObjectDir()
|
|
{
|
|
local project="$(expandPath "$WM_PROJECT_DIR")"
|
|
local absdir="$(expandPath "${1:-.}")"
|
|
local appDir relativeDir objectsDir
|
|
|
|
# Treat project/ builds as out-of-source
|
|
relativeDir="${absdir#${project}/}"
|
|
if [ "$relativeDir" != "$absdir" ]
|
|
then
|
|
if [ -n "$FOAM_BUILDROOT" ] && [ -w "$FOAM_BUILDROOT" ]
|
|
then
|
|
objectsDir="${FOAM_BUILDROOT}/build/${WM_OPTIONS}/${relativeDir}"
|
|
elif [ -w "$WM_PROJECT_DIR" ]
|
|
then
|
|
objectsDir="${WM_PROJECT_DIR}/build/${WM_OPTIONS}/${relativeDir}"
|
|
fi
|
|
fi
|
|
|
|
# Default (local) build directory
|
|
if [ -z "$objectsDir" ]
|
|
then
|
|
if [ -d "$absdir/Make" ]
|
|
then
|
|
objectsDir="${absdir}/Make/${WM_OPTIONS}"
|
|
else
|
|
relativeDir="$absdir"
|
|
appDir=.
|
|
[ -d Make ] || appDir=$(findTarget .) || exit 1 # Fatal
|
|
absdir=$(expandPath "$appDir"/.)
|
|
|
|
relativeDir="${relativeDir#${absdir}}"
|
|
objectsDir="${appDir}/Make/${WM_OPTIONS}${relativeDir}"
|
|
fi
|
|
fi
|
|
|
|
echo "$objectsDir"
|
|
}
|
|
|
|
|
|
# Find the object directory and remove it
|
|
# removeObjectDir dirName
|
|
# removeObjectDir fileName
|
|
#
|
|
# Output:
|
|
# - NONE
|
|
#
|
|
# Global variables used:
|
|
# - WM_PROJECT_DIR, WM_OPTIONS
|
|
removeObjectDir()
|
|
{
|
|
local objectsDir="$(findObjectDir "${1:-.}")"
|
|
if [ -d "$objectsDir" ]
|
|
then
|
|
rm -rf "$objectsDir" 2>/dev/null
|
|
fi
|
|
}
|
|
|
|
|
|
# Save build/configure parameter information (dependency) into sentinel file
|
|
#
|
|
# 1 - sentinelFile
|
|
# 2... build/configure parameters
|
|
#
|
|
storeDependency()
|
|
{
|
|
local sentinel="$1"
|
|
local depend
|
|
shift
|
|
|
|
if [ -n "$sentinel" ]
|
|
then
|
|
mkdir -p "$(dirname "$sentinel")"
|
|
|
|
echo '# Build/configure parameters' >| "$sentinel"
|
|
|
|
for depend
|
|
do
|
|
echo "-- $depend"
|
|
done >> "$sentinel"
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
|
|
# Check sentinel file(s) to handle changed build/configure parameters
|
|
# such as paraview / vtk version changes
|
|
#
|
|
# 1 - sourceDir
|
|
# 2... build/configure parameters
|
|
#
|
|
# The additional test for "CMakeCache.txt" helps for cmake projects and
|
|
# has no adverse affect for others
|
|
#
|
|
sameDependency()
|
|
{
|
|
local sourceDir="$1"
|
|
shift
|
|
local objectsDir
|
|
local compare=0
|
|
|
|
# Where generated files are stored
|
|
objectsDir=$(findObjectDir "$sourceDir") || exit 1 # Fatal
|
|
local sentinel="$objectsDir/ConfigParameters"
|
|
|
|
if [ -f "$sentinel" ]
|
|
then
|
|
# Create an .update version for comparison
|
|
storeDependency "${sentinel}.update" $@
|
|
cmp "${sentinel}" "${sentinel}.update" >/dev/null 2>&1
|
|
compare=$?
|
|
|
|
if [ "$compare" -ne 0 ]
|
|
then
|
|
echo "build/configure parameters changed between builds" 1>&2
|
|
## cat "${sentinel}.update" 1>&2
|
|
fi
|
|
|
|
else
|
|
# No sentinel file: First time, or failed compilation?
|
|
if [ -f "$objectsDir/CMakeCache.txt" ]
|
|
then
|
|
echo "previous build was incomplete" 1>&2
|
|
compare=1
|
|
fi
|
|
fi
|
|
|
|
echo "$sentinel"
|
|
return "$compare"
|
|
}
|
|
|
|
|
|
# Build a mpi-versioned library (targetType)
|
|
# compile into MPI-qualified directory
|
|
# use sentinel file(s) to handle version changes
|
|
# 1 - libName
|
|
# 2... build/configure information
|
|
#
|
|
# Global variables used:
|
|
# - WM_OPTIONS, WM_MPLIB, FOAM_MPI
|
|
# - targetType
|
|
#
|
|
# Requires that WM_MPLIB contain an "MPI" string
|
|
#
|
|
# Has very simple option handling (bool options only!) that allow
|
|
# things like "wmakeLibMpi -debug -no-openmp" etc.
|
|
#
|
|
wmakeLibMpi()
|
|
{
|
|
local libName
|
|
local wmakeCmd="wmake"
|
|
|
|
# Very simple option handling (bool options only!)
|
|
while [ "$#" -gt 0 ]
|
|
do
|
|
case "$1" in
|
|
(- | --) # Stop option parsing
|
|
shift
|
|
break
|
|
;;
|
|
(-*) # Any bool option
|
|
wmakeCmd="$wmakeCmd $1"
|
|
;;
|
|
(*)
|
|
break # Done
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
libName="$1"
|
|
shift
|
|
|
|
case "$WM_MPLIB" in (*MPI* | *mpi*)
|
|
(
|
|
WM_OPTIONS="$WM_OPTIONS$WM_MPLIB"
|
|
|
|
# Where generated files are stored
|
|
objectsDir="$(findObjectDir "$libName")" || exit 1 # Fatal
|
|
|
|
# Something changed
|
|
sentinel=$(sameDependency "$libName" "MPLIB=$WM_MPLIB" "MPI=$FOAM_MPI" $@) || \
|
|
wclean "$libName"
|
|
|
|
echo "$wmakeCmd $targetType${targetType:+ }(mpi=$WM_MPLIB:$FOAM_MPI)"
|
|
$wmakeCmd $targetType "$libName" && \
|
|
storeDependency "$sentinel" "MPLIB=$WM_MPLIB" "MPI=$FOAM_MPI" $@
|
|
)
|
|
;;
|
|
esac
|
|
}
|
|
|
|
|
|
# Clean an mpi-versioned library
|
|
#
|
|
# Global variables used:
|
|
# - WM_OPTIONS, WM_MPLIB
|
|
#
|
|
# Requires that WM_MPLIB contain an "MPI" string
|
|
wcleanLibMpi()
|
|
{
|
|
case "$WM_MPLIB" in (*MPI* | *mpi*)
|
|
(
|
|
WM_OPTIONS="$WM_OPTIONS$WM_MPLIB"
|
|
|
|
for libName
|
|
do
|
|
wclean "$libName"
|
|
done
|
|
)
|
|
;;
|
|
esac
|
|
}
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
# depToSource depFile
|
|
#
|
|
# Output:
|
|
# - the sourceFile corresponding to depFile
|
|
#
|
|
# Global variables used:
|
|
# - WM_OPTIONS
|
|
# - WM_MPLIB
|
|
if [ -n "$BASH_VERSION" ]
|
|
then
|
|
depToSource()
|
|
{
|
|
local sourceFile="${1%.dep}"
|
|
sourceFile="${sourceFile/build\/${WM_OPTIONS}\//}"
|
|
sourceFile="${sourceFile/build\/${WM_OPTIONS}${WM_MPLIB}\//}"
|
|
sourceFile="${sourceFile/Make\/${WM_OPTIONS}\//}"
|
|
sourceFile="${sourceFile/Make\/${WM_OPTIONS}${WM_MPLIB}\//}"
|
|
|
|
echo "$sourceFile"
|
|
}
|
|
else
|
|
depToSource()
|
|
{
|
|
echo "${1%.dep}" | sed \
|
|
-e "s%build/${WM_OPTIONS}/%%" \
|
|
-e "s%build/${WM_OPTIONS}${WM_MPLIB}/%%" \
|
|
-e "s%Make/${WM_OPTIONS}/%%" \
|
|
-e "s%Make/${WM_OPTIONS}${WM_MPLIB}/%%"
|
|
}
|
|
fi
|
|
|
|
|
|
#------------------------------------------------------------------------------
|