From 816e96e0f265cac638e9531b682b29e72e15d30e Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@esi-group.com>
Date: Wed, 25 Mar 2020 10:41:29 +0100
Subject: [PATCH] ENH: tuning wmake behaviour (#1647)

- preferentially handle Allwmake.override, which allows packaging
  tools to define alternative make scripts, or selectively disable
  components.

- remove legacy handling of 'Optional' directory.
  Conditionals have since migrated into scripts themselves and/or
  use the wmake/scripts/have_* framework.

BUG: missed passing -debug for Allwmake scripts
---
 Allwmake                             |  15 +++-
 wmake/scripts/AllwmakeParseArguments |  22 +++--
 wmake/scripts/wmakeFunctions         |  11 +--
 wmake/wclean                         |  48 +++++-----
 wmake/wmake                          | 127 ++++++++++++++++-----------
 wmake/wmakeLnInclude                 |   2 +-
 6 files changed, 135 insertions(+), 90 deletions(-)

diff --git a/Allwmake b/Allwmake
index 431140a92de..c2529d54a90 100755
--- a/Allwmake
+++ b/Allwmake
@@ -46,11 +46,20 @@ echo
 "${WM_DIR:-wmake}"/src/Allmake
 
 # Compile ThirdParty libraries and applications
-if [ -d "$WM_THIRD_PARTY_DIR" ] && [ -x "$WM_THIRD_PARTY_DIR/Allwmake" ]
+if [ -d "$WM_THIRD_PARTY_DIR" ]
 then
-    "$WM_THIRD_PARTY_DIR"/Allwmake
+    if [ -e "$WM_THIRD_PARTY_DIR"/Allwmake.override ]
+    then
+        if [ -x "$WM_THIRD_PARTY_DIR"/Allwmake.override ]
+        then    "$WM_THIRD_PARTY_DIR"/Allwmake.override
+        fi
+    elif [ -x "$WM_THIRD_PARTY_DIR"/Allwmake ]
+    then      "$WM_THIRD_PARTY_DIR"/Allwmake
+    else
+        echo "Skip ThirdParty (no Allwmake* files)"
+    fi
 else
-    echo "No ThirdParty directory, or missing Allwmake - skipping"
+    echo "Skip ThirdParty (no directory)"
 fi
 
 echo "========================================"
diff --git a/wmake/scripts/AllwmakeParseArguments b/wmake/scripts/AllwmakeParseArguments
index eaac63e1a93..a8f8651c3aa 100644
--- a/wmake/scripts/AllwmakeParseArguments
+++ b/wmake/scripts/AllwmakeParseArguments
@@ -36,8 +36,11 @@
 # Check environment
 [ -d "$WM_PROJECT_DIR" ] || {
     exec 1>&2
-    echo "$Script error: The OpenFOAM environment not set or incorrect."
-    echo "    Check OpenFOAM entries in your dot-files and source them."
+    echo "$0"
+    echo "Error encountered:"
+    echo "    The OpenFOAM environment not set or incorrect."
+    echo "    Check your setup."
+    echo
     exit 1
 }
 
@@ -54,10 +57,11 @@ Executing ${0##*/} is equivalent to
 With these additional options:
    -l | -log | -log=name
 
-USAGE
+See
+   wmake -help (or wmake -help-full)
 
-    wmake -help
-    exit 0
+USAGE
+    exit 0  # clean exit
 }
 
 
@@ -86,17 +90,17 @@ do
         continue    # Permanently remove arg
         ;;
     -l | -log)
-        optLog="log.${WM_OPTIONS:-Allwmake}"
+        optLog="log.${WM_OPTIONS:-build}"
         continue    # Permanently remove arg
         ;;
     -log=*)
         optLog="${arg##*=}"
         if [ -d "$optLog" ]
         then
-            optLog="${optLog%/}/log.${WM_OPTIONS:-Allwmake}"
+            optLog="${optLog%/}/log.${WM_OPTIONS:-build}"
         elif [ -z "$optLog" ]
         then
-            optLog="log.${WM_OPTIONS:-Allwmake}"
+            optLog="log.${WM_OPTIONS:-build}"
         fi
         continue    # Permanently remove arg
         ;;
@@ -127,7 +131,7 @@ if [ -z "$fromWmake" ]
 then
     if [ -z "$optLog" ]
     then
-        exec wmake -all $optQueue $*
+        exec wmake -all $optDebug $optQueue $*
         exit $? # Unneeded, but just in case something went wrong
     else
         echo "Logging wmake -all output to '$optLog'" 1>&2
diff --git a/wmake/scripts/wmakeFunctions b/wmake/scripts/wmakeFunctions
index e9edf8853d4..7fdef11fe1c 100644
--- a/wmake/scripts/wmakeFunctions
+++ b/wmake/scripts/wmakeFunctions
@@ -6,11 +6,10 @@
 #    \\/     M anipulation  |
 #------------------------------------------------------------------------------
 #     Copyright (C) 2015-2016 OpenFOAM Foundation
-#     Copyright (C) 2018 OpenCFD Ltd.
+#     Copyright (C) 2018-2020 OpenCFD Ltd.
 #------------------------------------------------------------------------------
 # License
-#     This file is part of OpenFOAM, licensed under GNU General Public License
-#     <http://www.gnu.org/licenses/>.
+#     This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
 #
 # Script
 #     wmakeFunctions
@@ -39,9 +38,11 @@ checkEnv()
 {
     local check failed
 
-    for check in WM_PROJECT_DIR WM_OPTIONS WM_DIR
+    # Default for WM_DIR already provided above
+
+    for check in WM_PROJECT_DIR WM_OPTIONS
     do
-        eval test "\$$check" || failed="$failed $check"
+        eval test -n "\$$check" || failed="$failed $check"
     done
 
     [ -z "$failed" ] || {
diff --git a/wmake/wclean b/wmake/wclean
index 3317a802fee..1d771fcabbd 100755
--- a/wmake/wclean
+++ b/wmake/wclean
@@ -38,7 +38,7 @@
 #
 #------------------------------------------------------------------------------
 Script="${0##*/}"           # Use 'Script' for error messages in wmakeFunctions
-. "${0%/*}/scripts/wmakeFunctions"              # Source wmake functions
+. "${0%/*}"/scripts/wmakeFunctions              # Source wmake functions
 
 printHelp() {
     cat<<HELP_INFO
@@ -128,9 +128,9 @@ then
     elif [ -f "$1" ]
     then
         dir="${1%/*}"
-        : ${dir:=.}
+        : "${dir:=.}"
     else
-        targetType=$1
+        targetType="$1"
     fi
 
     # Specified directory name:
@@ -141,7 +141,7 @@ then
 
     if [ -n "$dir" ]
     then
-        cd $dir 2>/dev/null || {
+        cd "$dir" 2>/dev/null || {
             echo "$Script error: could not change to directory '$dir'" 1>&2
             exit 1
         }
@@ -188,7 +188,7 @@ then
         then
             echo "    Removing redundant object directories in $objectsDir"
 
-            find $objectsDir -name 'variables' -print | \
+            find "$objectsDir" -name 'variables' -print | \
             while read variablesFile
             do
                 # Hack'ish way of getting the original source code path
@@ -217,13 +217,13 @@ then
                     binaryFile=$(eval echo $binaryFile)
 
                     # Verbosely remove binary file
-                    if [ -n "$binaryFile" -a -e "$binaryFile" ]
+                    if [ -n "$binaryFile" ] && [ -e "$binaryFile" ]
                     then
-                        rm -vf $binaryFile 2>/dev/null
+                        rm -vf "$binaryFile" 2>/dev/null
                     fi
 
                     # Remove the deprecated object directory
-                    rm -rvf $depFile 2>/dev/null
+                    rm -rvf "$depFile" 2>/dev/null
                 fi
             done
         fi
@@ -237,31 +237,39 @@ fi
 # Recurse the directories tree
 #------------------------------------------------------------------------------
 
+unset exitCode
+
 if [ "$targetType" = all ]
 then
-    if [ -e Allwclean ]       # Consistent with Allwmake
+    if [ -e Allwclean ]       # Symmetric with Allwmake
     then
         ./Allwclean
-        exit $?
-    elif [ -e Allclean ]      # Often used for tutorial cases
+        exitCode="$?"
+    elif [ -e Allclean ]      # Tutorial cases
     then
         ./Allclean
-        exit $?
+        exitCode="$?"
     fi
 
+    if [ -n "$exitCode" ]
+    then
+        exit "$exitCode"
+    fi
+
+
     # For all directories containing a 'Make' directory, or an 'Allwclean' file
     for dir in $(find . -name Allwclean -o -name Make)
     do
-        echo ${dir%/*}
+        echo "${dir%/*}"
     done | sort | uniq | while read dir
     do
         # Use Allwclean if it exists, otherwise wclean
-        if [ -e "$dir/Allwclean" ]
+        if [ -e "$dir"/Allwclean ]
         then
-            $dir/Allwclean
-        elif [ -d "$dir/Make" ]
+            "$dir"/Allwclean
+        elif [ -d "$dir"/Make ]
         then
-            $0 $dir
+            $0 "$dir"
         fi
     done
 fi
@@ -273,14 +281,14 @@ fi
 
 if [ -d "$MakeDir" ]
 then
-    objectsDir=$MakeDir/$WM_OPTIONS
+    objectsDir="$MakeDir/$WM_OPTIONS"
     case "$PWD" in
     ("$WM_PROJECT_DIR"/*)
-        buildPath=$WM_PROJECT_DIR/build/${WM_OPTIONS}
+        buildPath="$WM_PROJECT_DIR/build/${WM_OPTIONS}"
         objectsDir=$buildPath$(echo $PWD | sed s%$WM_PROJECT_DIR%% )
         ;;
     esac
-    rm -rf $objectsDir 2>/dev/null
+    rm -rf "$objectsDir" 2>/dev/null
 fi
 
 #------------------------------------------------------------------------------
diff --git a/wmake/wmake b/wmake/wmake
index 438dce9e23d..832aeaa9838 100755
--- a/wmake/wmake
+++ b/wmake/wmake
@@ -29,27 +29,26 @@
 #     wmake
 #
 # Description
-#     General, easy to use make system for multi-platform development
-#     with support for local and network parallel compilation.
+#     General, wrapped make system for multi-platform development with
+#     support for local and network parallel compilation.
 #
-#     This updated wmake supports out-of-tree object and dependency files to
-#     avoid the clutter which accumulates in the source-tree with the original
-#     wmake system.  Now when building the OpenFOAM package both the object and
-#     dependency files are now located in a tree with the same structure as the
-#     source tree but in the platforms/$WM_OPTIONS sub-directory of
-#     $WM_PROJECT_DIR.
+#     Intermediate object and dependency files retain the tree structure
+#     of the original source files, with its location depending on the
+#     build context.
 #
-#     When building user libraries and applications which are not located in the
-#     OpenFOAM source-tree the object and dependency files are located in a tree
-#     with the same structure as the source tree but in the Make/$WM_OPTIONS
-#     sub-directory.
+#       1. Building within the OpenFOAM project:
+#          The tree is located under $WM_PROJECT_DIR/build/$WM_OPTIONS/
 #
-#     The disadvantage of the out-of-tree compilation is that the dependency
-#     files are harder to find but are sometimes useful to study which header
-#     files are included.  For those who need access to the dependency files the
-#     new wdep script is provided to locate them.  See the wdep script header or
-#     run:
-#         wdep -h
+#       2. Building applications or libraries outside the OpenFOAM project:
+#          The tree is located under its local Make/$WM_OPTIONS/
+#
+#     The `wdep` script can be used to locate the dependency file
+#     corresponding to a given source file.
+#
+#     When `wmake -all` is used, the following rules are applied:
+#     1. If `Allwmake.override` exists, use it.
+#     2. (OR) If `Allwmake` exists, use it.
+#     3. (OR) descend into each sub-directory and repeat.
 #
 # See also
 #     wmakeLnInclude, wmakeLnIncludeAll, wmakeCollect, wdep, wrmdep, wrmo,
@@ -57,16 +56,15 @@
 #
 #------------------------------------------------------------------------------
 Script="${0##*/}"           # Use 'Script' for error messages in wmakeFunctions
-. "${0%/*}/scripts/wmakeFunctions"              # Source wmake functions
+. "${0%/*}"/scripts/wmakeFunctions              # Source wmake functions
 
-# Print help to stdout so that it can be captured
 printHelp() {
     cat<<HELP_HEAD
 
 Usage: $Script [OPTION] [dir]
        $Script [OPTION] target [dir [MakeDir]]
 options:
-  -s | -silent      Quiet mode (does not echo commands)
+  -s | -silent      Silent mode (does not echo commands)
   -a | -all         wmake all sub-directories, running Allwmake if present
   -q | -queue       wmakeCollect sub-directories, running Allwmake if present
   -k | -keep-going  Keep going even when errors occur (-non-stop)
@@ -156,11 +154,10 @@ make="make"
 #------------------------------------------------------------------------------
 
 # Set nCores to the number of cores on the machine
-nCores=0
 allCores()
 {
     nCores=$(getconf _NPROCESSORS_ONLN 2>/dev/null) || nCores=1
-    : ${nCores:=1}
+    echo "${nCores:-1}"
 }
 
 
@@ -204,17 +201,21 @@ do
             ;;
         # Parallel compilation on all cores (or specified number of cores)
         -j)
-            nCores=0
-            test $# -ge 2 && expr $2 + 1 > /dev/null 2>&1 \
-                && shift && nCores=$1
-
-            [ "$nCores" = 0 ] && allCores
-            export WM_NCOMPPROCS=$nCores
+            export WM_NCOMPPROCS=0
+            case "$2" in
+            [0-9]*)
+                if WM_NCOMPPROCS="$(expr 0 + "$2" 2>/dev/null)"
+                then
+                    shift
+                fi
+                ;;
+            esac
+            [ "${WM_NCOMPPROCS:=0}" -gt 0 ] || WM_NCOMPPROCS=$(allCores)
             echo "Compiling enabled on $WM_NCOMPPROCS cores" 1>&2
             ;;
         # Parallel compilation on specified number of cores
         -j[1-9]*)
-            export WM_NCOMPPROCS=${1#-j}
+            export WM_NCOMPPROCS="${1#-j}"
             echo "Compiling enabled on $WM_NCOMPPROCS cores" 1>&2
             ;;
         # Keep going, ignoring errors
@@ -237,7 +238,7 @@ do
         #   and respective binaries.
         -update)
             update=true
-            : ${all:=all}  # implies 'all', unless previous set to 'queue' etc.
+            : "${all:=all}" # implies 'all', unless previous set to 'queue' etc.
             ;;
         -version | --version)
             $make -f $WM_DIR/makefiles/info api
@@ -270,15 +271,16 @@ fi
 
 checkEnv
 
-# When compiling anything but a standalone exe WM_PROJECT and WM_PROJECT_DIR
-# must be set
-[ "$1" = exe -o \( "$WM_PROJECT" -a "$WM_PROJECT_DIR" \) ] || {
+# Require WM_PROJECT for anything except a standalone exe.
+# The WM_PROJECT_DIR was already tested in checkEnv.
+if [ -z "$WM_PROJECT" ] && [ "$1" != exe ]
+then
     exec 1>&2
     echo "$Script error:"
-    echo "    environment variable \$WM_PROJECT or \$WM_PROJECT_DIR not set"
+    echo "    environment variable \$WM_PROJECT not set"
     echo "    while building project library"
     exit 1
-}
+fi
 
 
 #------------------------------------------------------------------------------
@@ -289,7 +291,7 @@ if [ -n "$WM_NCOMPPROCS" ]
 then
     parOpt="-j $WM_NCOMPPROCS"
 
-    if [ "$WM_NCOMPPROCS" -gt 1 -a -z "$MAKEFLAGS" ]
+    if [ "$WM_NCOMPPROCS" -gt 1 ] && [ -z "$MAKEFLAGS" ]
     then
         make="$make --no-print-directory $parOpt"
     fi
@@ -368,7 +370,7 @@ else
 
         if [ -n "$dir" ]
         then
-            cd $dir 2>/dev/null || {
+            cd "$dir" 2>/dev/null || {
                 echo "$Script error: could not change to directory '$dir'" 1>&2
                 exit 1
             }
@@ -404,19 +406,43 @@ fi
 # Recurse the source tree to compile "all" targets
 #------------------------------------------------------------------------------
 
+unset exitCode
+
 if [ "$all" = all ]
 then
-    if [ -e Allwmake ]
+    if [ -e Allwmake.override ]
+    then
+        if [ -x Allwmake.override ]
+        then
+            ./Allwmake.override -fromWmake ${optDebug:+-debug} $targetType
+            exitCode="$?"
+        else
+            # Allow empty or non-executable file (eg, touch Allwmake.override)
+            exitCode=0
+        fi
+    elif [ -e Allwmake ]
     then
         ./Allwmake -fromWmake ${optDebug:+-debug} $targetType
-        exit $?
+        exitCode="$?"
+    fi
+
+    if [ -n "$exitCode" ]
+    then
+        exit "$exitCode"
     fi
 
+    exitCode=0  # For fall-through
+
+
     # Find all the sub-directories containing a 'Make' directory
     # (xargs is just used to flatten the list)
     FOAM_APPS=$(
         for d in *
-        do [ -d "$d" -a "$d" != Optional -a "$d" != Make ] && echo "$d"
+        do
+            case "$d" in
+                (Make) ;;  # Do not make within Make/ dir
+                (*) [ -d "$d" ] && echo "$d" ;;
+            esac
         done | xargs)
 
     if [ -n "$FOAM_APPS" ]
@@ -426,16 +452,13 @@ then
               -f $WM_DIR/makefiles/apps \
               ${optDebug:+c++DBUG="$optDebug"} \
               TARGET="$targetType" FOAM_APPS="$FOAM_APPS"
-        makeExitCode=$?
-    else
-        makeExitCode=0 # For fall-through
+        exitCode=$?
     fi
 
-    # Exit if current directory does not contains a 'Make' directory or
-    # an error was previously encountered
-    if [ ! -d "$MakeDir" -o $makeExitCode -ne 0 ]
+    # Exit on error, or if current directory does not have a 'Make' directory
+    if [ ! -d "$MakeDir" ] || [ "$exitCode" -ne 0 ]
     then
-        exit $makeExitCode
+        exit "$exitCode"
     fi
 fi
 
@@ -496,10 +519,10 @@ fi
 # files and options being built in parallel
 #------------------------------------------------------------------------------
 
-objectsDir=$MakeDir/$WM_OPTIONS
+objectsDir="$MakeDir/$WM_OPTIONS"
 case "$PWD" in
 ("$WM_PROJECT_DIR"/*)
-    buildPath=$WM_PROJECT_DIR/build/${WM_OPTIONS}
+    buildPath="$WM_PROJECT_DIR/build/${WM_OPTIONS}"
     objectsDir=$buildPath$(echo $PWD | sed s%$WM_PROJECT_DIR%% )
     ;;
 esac
@@ -554,9 +577,9 @@ then
 
     $make -f $WM_DIR/makefiles/general \
         MAKE_DIR=$MakeDir OBJECTS_DIR=$objectsDir updatedep
-    makeExitCode=$?
+    exitCode="$?"
 
-    [ $makeExitCode -eq 0 ] || exit $makeExitCode
+    [ "$exitCode" -eq 0 ] || exit "$exitCode"
 fi
 
 
diff --git a/wmake/wmakeLnInclude b/wmake/wmakeLnInclude
index 0b013cce328..1123b8c7209 100755
--- a/wmake/wmakeLnInclude
+++ b/wmake/wmakeLnInclude
@@ -50,7 +50,7 @@ Usage: $Script [OPTION] [-pwd | dir]
 
 options:
   -u | -update      Update
-  -s | -silent      Use 'silent' mode (do not echo command)
+  -s | -silent      Silent mode (do not echo command)
   -pwd              Locate root directory containing a Make/ directory.
   -h | -help        Print the usage
 
-- 
GitLab