openfoam/wmake/scripts/wmakeFunctions
Mark Olesen d086cc5a0e COMP: stricter handling of openmp vs no-openmp
- 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.
2023-12-11 15:56:00 +01:00

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
#------------------------------------------------------------------------------