#!/bin/bash #------------------------------------------------------------------------------ # ========= | # \\ / F ield | OpenFOAM: The Open Source CFD Toolbox # \\ / O peration | # \\ / A nd | www.openfoam.com # \\/ M anipulation | #------------------------------------------------------------------------------ # Copyright (C) 2011-2016 OpenFOAM Foundation # Copyright (C) 2017-2020 OpenCFD Ltd. #------------------------------------------------------------------------------ # 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 . # # Script # wmake # # Description # General, wrapped make system for multi-platform development. # # Intermediate object and dependency files retain the tree structure # of the original source files, with its location depending on the # build context. # # 1. Building within the OpenFOAM project: # The tree is located under $WM_PROJECT_DIR/build/$WM_OPTIONS/ # # 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. # # Environment # FOAM_EXTRA_CFLAGS FOAM_EXTRA_CXXFLAGS FOAM_EXTRA_LDFLAGS # FOAM_MODULE_PREFIX # # See also # wmakeLnInclude, wmakeLnIncludeAll, wmakeCollect, wdep, wrmdep, wrmo, # wclean, wcleanLnIncludeAll # #------------------------------------------------------------------------------ Script="${0##*/}" # Need 'Script' for wmakeFunctions messages scriptsDir="${0%/*}"/scripts # wmake/scripts directory . "$scriptsDir"/wmakeFunctions # Source wmake functions printHelp() { cat<&2 echo echo "Error encountered:" while [ "$#" -ge 1 ]; do echo " $1"; shift; done echo echo "See '${0##*/} -help' for usage" echo exit 1 } # Default make is the "make" in the path make="make" #------------------------------------------------------------------------------ # Set nCores to the number of cores on the machine allCores() { nCores=$(getconf _NPROCESSORS_ONLN 2>/dev/null) || nCores=1 echo "${nCores:-1}" } #------------------------------------------------------------------------------ # Parse arguments and options #------------------------------------------------------------------------------ # Default to compiling the local target only unset optAll optUpdate optDebug optQuiet optShow optPwd # Consistency with inherited values if [ "$WM_QUIET" = true ] then optQuiet=true fi while [ "$#" -gt 0 ] do case "$1" in -help-f*) # Full help printHelp -full ;; -h | -help*) # Short help printHelp ;; # Forward to scripts/wmake-build-info -build-info) shift exec "$scriptsDir/wmake-build-info" "$@" exit $? ;; # Forward to scripts/wmake-check-dir # Out of order options: (-quiet) -check-dir) shift exec "$scriptsDir/wmake-check-dir" \ ${optQuiet:+-silent} "$@" exit $? ;; -s | -silent | -quiet) optQuiet=true export WM_QUIET=true ;; -debug) optDebug="-DFULLDEBUG -g -O0" ;; -module-prefix=*) optPrefix="${1#*=}" case "$optPrefix" in # Prefix: user (u | user) export FOAM_MODULE_PREFIX="${FOAM_USER_LIBBIN%/*}" ;; # Prefix: group (g | group) export FOAM_MODULE_PREFIX="${FOAM_SITE_LIBBIN%/*}" ;; # Prefix: openfoam (other) (o | openfoam) export FOAM_MODULE_PREFIX="${FOAM_LIBBIN%/*}" ;; # Prefix: custom (absolute or relative) (*) export FOAM_MODULE_PREFIX="$optPrefix" : "${FOAM_MODULE_PREFIX:=/usr/local}" # Default (autoconf) # Require absolute path [ "${FOAM_MODULE_PREFIX#/}" != "${FOAM_MODULE_PREFIX}" ] || \ FOAM_MODULE_PREFIX="${PWD}/${FOAM_MODULE_PREFIX}" ;; esac unset FOAM_MODULE_APPBIN FOAM_MODULE_LIBBIN echo "Module prefix = $FOAM_MODULE_PREFIX" 1>&2 ;; -show-api | -show-ext-so | \ -show-compile-c | -show-c | -show-cflags | -show-cflags-arch | \ -show-compile-cxx | -show-cxx | -show-cxxflags | -show-cxxflags-arch ) $make -f $WM_DIR/makefiles/info "${1#-show-}" optShow=true ;; -show-path-c | -show-path-cxx ) command -v $($make -f $WM_DIR/makefiles/info "${1#-show-path-}") optShow=true ;; -a | -all | all) optAll=all ;; -q | -queue | queue) optAll=queue ;; # Parallel compilation on all cores (or specified number of cores) -j) 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}" echo "Compiling enabled on $WM_NCOMPPROCS cores" 1>&2 ;; # Keep going, ignoring errors -k | -keep-going | -non-stop) export WM_CONTINUE_ON_ERROR=true ;; # Disable scheduled parallel compilation -no-scheduler) unset WM_SCHEDULER ;; # Print root directory containing a Make/ directory and exit -pwd) optPwd=true ;; # Meant to be used following a pull, this will: # - remove dep files that depend on deleted files; # - remove stale dep files; # - update lnInclude directories; # - remove empty directories, along with deprecated object directories # and respective binaries. -update) optUpdate=true : "${optAll:=all}" # implies 'all', unless previously set ;; -version | --version) $make -f $WM_DIR/makefiles/info api optShow=true break; ;; --) shift break ;; -*) die "unknown option: '$1'" ;; *) break ;; esac shift done if [ "$optShow" = true ] then exit 0 fi #------------------------------------------------------------------------------ # Check environment variables #------------------------------------------------------------------------------ checkEnv # 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 not set" echo " while building project library" exit 1 fi #------------------------------------------------------------------------------ # Setup parallel compilation #------------------------------------------------------------------------------ if [ -n "$WM_NCOMPPROCS" ] then parOpt="-j $WM_NCOMPPROCS" if [ "$WM_NCOMPPROCS" -gt 1 ] && [ -z "$MAKEFLAGS" ] then make="$make --no-print-directory $parOpt" fi fi #------------------------------------------------------------------------------ # Check arguments and change to the directory in which to run wmake. # The variables 'targetType' and 'MakeDir' are considered global #------------------------------------------------------------------------------ unset targetType MakeDir=Make unset dir if [ -n "$optPwd" ] then if [ $# -ge 1 ] then if [ -d "$1" ] then dir="${1%/}" elif [ -f "$1" ] then dir="${1%/*}" : "${dir:=.}" [ "$dir" != "$1" ] || dir="." else echo "$Script error: not a file or directory" 1>&2 exit 1 fi cd "$dir" 2>/dev/null || { echo "$Script error: could not change to directory '$dir'" 1>&2 exit 1 } fi # Locate target with Make/ directory if dir="$(findTarget .)" then (cd "$dir" && pwd -L) exit 0 else exit 2 fi else if [ $# -ge 1 ] then if [ -d "$1" ] then dir="${1%/}" elif [ -f "$1" ] then dir="${1%/*}" : "${dir:=.}" if [ "$dir" = "$1" ] then dir="." fi else targetType="$1" fi # Specified directory name: [ $# -ge 2 ] && dir="${2%/}" # Specified alternative name for the Make sub-directory: [ $# -ge 3 ] && MakeDir="${3%/}" if [ -n "$dir" ] then cd "$dir" 2>/dev/null || { echo "$Script error: could not change to directory '$dir'" 1>&2 exit 1 } elif [ -f "$MakeDir/files" ] then dir="(${PWD##*/})" # Implicit directory information fi # Print command echo "$Script $targetType${targetType:+ }$dir" unset dir fi fi unset dir #------------------------------------------------------------------------------ # Recurse the source tree to update all #------------------------------------------------------------------------------ if [ "$optUpdate" = true ] then wrmdep -update wrmdep -old wmakeLnIncludeAll -update $parOpt wclean empty export WM_UPDATE_DEPENDENCIES=yes fi unset exitCode #------------------------------------------------------------------------------ # Recurse the source tree to compile "all" targets #------------------------------------------------------------------------------ if [ "$optAll" = all ] then 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 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 case "$d" in (Make) ;; # Do not make within Make/ dir (*) [ -d "$d" ] && echo "$d" ;; esac done | xargs) if [ -n "$FOAM_APPS" ] then # Compile all applications in sub-directories $make ${WM_CONTINUE_ON_ERROR:+-k} \ -f $WM_DIR/makefiles/apps \ ${optDebug:+c++DBUG="$optDebug"} \ TARGET="$targetType" FOAM_APPS="$FOAM_APPS" exitCode=$? fi # Exit on error, or if current directory does not have a 'Make' directory if [ ! -d "$MakeDir" ] || [ "$exitCode" -ne 0 ] then exit "$exitCode" fi fi #------------------------------------------------------------------------------ # Recurse source tree to compile "all" targets using wmakeCollect #------------------------------------------------------------------------------ if [ "$optAll" = queue ] then [ "$optUpdate" = true ] || wmakeLnIncludeAll $parOpt ( export WM_COLLECT_DIR="$WM_PROJECT_DIR/build/${WM_OPTIONS}/${PWD////_}" export WM_SCHEDULER="$WM_DIR/wmakeCollect" trap '$WM_SCHEDULER -kill' TERM INT "$WM_SCHEDULER" -clean \ && wmake -all objects \ && "$WM_SCHEDULER" ) && wmake -all ${optDebug:+-debug} exit $? fi #------------------------------------------------------------------------------ # Search up the directory tree for the Make sub-directory, # check the existence of the 'files' file and build there if present #------------------------------------------------------------------------------ cdSource #------------------------------------------------------------------------------ # Transform options #------------------------------------------------------------------------------ # Transform no option to "libso" if that looks appropriate or remove it # so that the call to make builds the application if [ -z "$targetType" ] then if grep -qe '^ *LIB *=' "$MakeDir/files" 2>/dev/null then targetType=libso fi elif grep -qe '^ *EXE *=' "$MakeDir/files" 2>/dev/null then # Application. Remove any nonsense targetType case "$targetType" in lib*) unset targetType ;; esac fi #------------------------------------------------------------------------------ # Spawn a sub-shell and unset MAKEFLAGS in that sub-shell to avoid # files and options being built in parallel #------------------------------------------------------------------------------ # Mini-version of findObjectDir unset objectsDir # Handle project/{applications,src} as out-of-source build relativeDir="${PWD#${WM_PROJECT_DIR}/}" if [ "$relativeDir" != "$PWD" ] then [ -w "$WM_PROJECT_DIR" ] && \ objectsDir="${WM_PROJECT_DIR}/build/${WM_OPTIONS}/${relativeDir}" fi # Default (local) build directory if [ -z "$objectsDir" ] then objectsDir="$MakeDir/$WM_OPTIONS" fi ( unset MAKEFLAGS mkdir -p "$objectsDir" # Pre-build the $WM_OPTIONS/options file # which is included when building the $WM_OPTIONS/files file $make -s -f $WM_DIR/makefiles/files \ MAKE_DIR="$MakeDir" OBJECTS_DIR="$objectsDir" "$objectsDir"/options $make -s -f $WM_DIR/makefiles/files \ MAKE_DIR=$MakeDir OBJECTS_DIR=$objectsDir ) #------------------------------------------------------------------------------ # Check the $objectsDir/sourceFiles file was created successfully #------------------------------------------------------------------------------ [ -r $objectsDir/sourceFiles ] || { echo "$Script error: file '$objectsDir/sourceFiles'" \ "could not be created in $PWD" 1>&2 exit 1 } #------------------------------------------------------------------------------ # Make the dependency files #------------------------------------------------------------------------------ # For libraries create lnInclude, but only if 'LIB' is declared in 'Make/files' case "$targetType" in (lib | libo | libso | dep) if grep -qe '^ *LIB *=' "$MakeDir/files" 2>/dev/null then $make -s -f $WM_DIR/makefiles/general \ MAKE_DIR=$MakeDir OBJECTS_DIR=$objectsDir lnInclude fi ;; esac #------------------------------------------------------------------------------ # When WM_UPDATE_DEPENDENCIES is set, use forced dependency files update #------------------------------------------------------------------------------ if [ -n "$WM_UPDATE_DEPENDENCIES" ] then $make -f $WM_DIR/makefiles/general \ MAKE_DIR=$MakeDir OBJECTS_DIR=$objectsDir updatedep exitCode="$?" [ "$exitCode" -eq 0 ] || exit "$exitCode" fi #------------------------------------------------------------------------------ # Make the dependency files or object files and link #------------------------------------------------------------------------------ exec $make -f $WM_DIR/makefiles/general \ ${optDebug:+c++DBUG="$optDebug"} \ MAKE_DIR=$MakeDir OBJECTS_DIR=$objectsDir $targetType exit 0 # clean exit #------------------------------------------------------------------------------