- initial split of wmake-related commands into "plumbing" and "porcelain" akin to how git handles things. - wmakeBuildInfo (very low-level), now relocated to the wmake/scripts and accessible for the user as "wmake -build-info". This satisfies a long-standing desire to access build information in a fashion similar to the api/patch information. CONFIG: avoid git information when building with a debian/ directory - when a 'debian/' directory exists, there is a high probability that the '.git/' directory is from debian and not from OpenFOAM (ie, useless here). This corresponds to an implicit '-no-git', which has no effect when building from pristine sources. ENH: wmakeCheckPwd becomes scripts/wmake-check-dir - accessible for the user as "wmake -check-dir" and with 1 or 2 directory names. A wmakeCheckPwd symlink left for compatibility.
624 lines
15 KiB
Bash
Executable File
624 lines
15 KiB
Bash
Executable File
#!/bin/sh
|
|
#------------------------------------------------------------------------------
|
|
# ========= |
|
|
# \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
# \\ / O peration |
|
|
# \\ / A nd | www.openfoam.com
|
|
# \\/ M anipulation |
|
|
#------------------------------------------------------------------------------
|
|
# Copyright (C) 2018-2020 OpenCFD Ltd.
|
|
#------------------------------------------------------------------------------
|
|
# License
|
|
# This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
|
|
#
|
|
# Script
|
|
# wmake/scripts/wmake-build-info
|
|
# Backend for "wmake -build-info"
|
|
#
|
|
# Description
|
|
# Print the api/version and other build information for the project.
|
|
#
|
|
# Environment
|
|
# - WM_PROJECT_DIR
|
|
# - WM_PROJECT_VERSION
|
|
# - WM_DIR (unset defaults to WM_PROJECT_DIR/wmake)
|
|
#
|
|
# Files
|
|
# - META-INFO/{api-info,build-info}
|
|
# - wmake/rules/General/general
|
|
# - debian : implicitly disables git queries
|
|
#
|
|
# Note
|
|
# When a 'debian/' directory exists, the '.git/' directory is most
|
|
# likely from debian and not from OpenFOAM (ie, useless here).
|
|
# This corresponds to an implicit '-no-git', which has no effect
|
|
# when building from pristine sources.
|
|
#
|
|
# SeeAlso
|
|
# META-INFO/README.md for other routines that also use META-INFO.
|
|
#
|
|
#------------------------------------------------------------------------------
|
|
# Locations
|
|
rulesFile="${WM_DIR:-$WM_PROJECT_DIR/wmake}/rules/General/general"
|
|
META_INFO="$WM_PROJECT_DIR/META-INFO"
|
|
FOAM_GIT_DIR="$WM_PROJECT_DIR/.git"
|
|
|
|
printHelp() {
|
|
cat<<USAGE
|
|
|
|
Usage: ${0##*/} [OPTION]
|
|
${0##*/} [-update] -filter FILE
|
|
options:
|
|
-cmp, -check Compare make and meta information (exit 0 for no changes)
|
|
-diff Display differences between make and meta information
|
|
(exit code 0 for no changes)
|
|
-dry-run In combination with -update
|
|
-filter FILE Filter @API@, @BUILD@ tags in file with make information
|
|
-no-git Disable use of git for obtaining information
|
|
-remove Remove meta-info build information and exit
|
|
-update Update meta-info from make information
|
|
-query Report make-info and meta-info
|
|
-query-make Report make-info values (api, branch, build)
|
|
-query-meta Report meta-info values (api, branch, build)
|
|
-show-api Print api value from wmake/rules, or meta-info and exit
|
|
-show-patch Print patch value from meta-info and exit
|
|
-help Print the usage
|
|
|
|
Query/manage status of {api,branch,build} information.
|
|
Default without any arguments is the same as '-query-make'.
|
|
|
|
USAGE
|
|
exit 1
|
|
}
|
|
|
|
# Report error and exit
|
|
die()
|
|
{
|
|
exec 1>&2
|
|
echo
|
|
echo "Error encountered:"
|
|
while [ "$#" -ge 1 ]; do echo " $1"; shift; done
|
|
echo
|
|
echo "See '${0##*/} -help' for usage"
|
|
echo
|
|
exit 1
|
|
}
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Parse arguments and options
|
|
#------------------------------------------------------------------------------
|
|
unset optCheck optDryRun optUpdate optQuery optFilter
|
|
|
|
while [ "$#" -gt 0 ]
|
|
do
|
|
case "$1" in
|
|
-h | -help*)
|
|
printHelp
|
|
;;
|
|
-cmp | -check)
|
|
optCheck=true
|
|
;;
|
|
-diff)
|
|
optCheck=verbose
|
|
;;
|
|
-dry-run)
|
|
optDryRun=true
|
|
;;
|
|
-remove)
|
|
optUpdate=remove
|
|
break # Stop now
|
|
;;
|
|
-update)
|
|
optUpdate=true
|
|
;;
|
|
-query)
|
|
optQuery="make:meta"
|
|
;;
|
|
-query-make | -query-meta)
|
|
optQuery="$optQuery:${1##*-}"
|
|
;;
|
|
-show-api)
|
|
optQuery="api"
|
|
;;
|
|
-show-patch)
|
|
optQuery="patch"
|
|
;;
|
|
-filter)
|
|
optFilter=true
|
|
shift # Stop here, a file name follows
|
|
break
|
|
;;
|
|
-no-git)
|
|
unset FOAM_GIT_DIR
|
|
;;
|
|
*)
|
|
die "Unknown option/argument: '$1'"
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
# Check environment variables
|
|
[ -d "$WM_PROJECT_DIR" ] || \
|
|
die "Bad or unset environment variable: \$WM_PROJECT_DIR"
|
|
|
|
[ -d "$META_INFO" ] || \
|
|
die "No ${META_INFO##*/}/ directory for project"
|
|
|
|
# Disable git queries for debian packaging (see notes above)
|
|
if [ -d "$WM_PROJECT_DIR/debian" ]
|
|
then
|
|
unset FOAM_GIT_DIR
|
|
fi
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
if [ "$optUpdate" = remove ]
|
|
then
|
|
|
|
if [ -f "$META_INFO/build-info" ]
|
|
then
|
|
echo "Removing project ${META_INFO##*/}/build-info" 1>&2
|
|
rm -f "$META_INFO/build-info"
|
|
else
|
|
echo "Already removed project ${META_INFO##*/}/build-info" 1>&2
|
|
fi
|
|
exit 0
|
|
|
|
elif [ "$optFilter" = true ]
|
|
then
|
|
|
|
[ -f "$1" ] || {
|
|
echo "Error in ${0##*/}: file not found '$1'" 1>&2
|
|
exit 2
|
|
}
|
|
|
|
# Disable other methods that generate output to stdout
|
|
unset optCheck optQuery
|
|
|
|
else
|
|
|
|
[ "$#" -eq 0 ] || die "Unexpected option/arguments $*"
|
|
|
|
# Nothing specified? Default to -query-make
|
|
if [ -z "$optCheck$optUpdate$optQuery" ]
|
|
then
|
|
optQuery="make"
|
|
fi
|
|
|
|
fi
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
# Variables - for portability, avoiding bash associative arrays
|
|
unset make_info meta_info
|
|
|
|
|
|
# Populate make_* variables
|
|
#
|
|
# - api : from rules/General/general
|
|
# - patch : cached value from previous make
|
|
# - branch : from git
|
|
# - build : from git
|
|
#
|
|
# Failure modes:
|
|
# - No api information (can't find file etc).
|
|
# -> FATAL: should never happen.
|
|
#
|
|
# - No git installed or no git repo
|
|
# -> branch and build are populated as empty strings
|
|
#
|
|
# - Working on detached head.
|
|
# -> branch has value "HEAD" instead of something more readable.
|
|
getMakeInfo()
|
|
{
|
|
if [ -n "$make_info" ]
|
|
then
|
|
##echo "use cached value for make info" 1>&2
|
|
return 0
|
|
fi
|
|
##echo "get make info" 1>&2
|
|
|
|
local api patch build branch
|
|
unset make_api make_patch make_branch make_build
|
|
|
|
# (api) from WM_DIR/rules/General/general
|
|
# - extract WM_VERSION = OPENFOAM=<digits>
|
|
|
|
api="$(sed -ne '/^ *#/!{ /WM_VERSION.*OPENFOAM=/{ s@^.*OPENFOAM= *\([0-9][0-9]*\).*@\1@p; q }}' "$rulesFile" 2>/dev/null)"
|
|
|
|
if [ -d "$META_INFO" ]
|
|
then
|
|
# (patch) from build-info - not from api-info
|
|
patch="$(sed -ne 's@^patch *= *\([0-9][0-9]*\).*@\1@p' "$META_INFO/build-info" 2>/dev/null)"
|
|
fi
|
|
|
|
# Build info from git. Use short date format (YYYY-MM-DD) and sed instead
|
|
# of the newer --date='format:%y%m%d'
|
|
if [ -d "$FOAM_GIT_DIR" ]
|
|
then
|
|
build="$(git --git-dir="$FOAM_GIT_DIR" log -1 --date=short --format='%h=%ad' 2>/dev/null|sed 's/-//g;s/=/-/')"
|
|
|
|
# Branch info from git
|
|
if [ -n "$build" ]
|
|
then
|
|
branch="$(git --git-dir="$FOAM_GIT_DIR" rev-parse --abbrev-ref HEAD 2>/dev/null)"
|
|
fi
|
|
fi
|
|
|
|
make_api="$api"
|
|
make_patch="${patch:-0}" # Default is 0 (unpatched)
|
|
make_branch="$branch"
|
|
make_build="$build"
|
|
make_info=true
|
|
}
|
|
|
|
|
|
# Populate meta_* variables
|
|
#
|
|
# - api : from META-INFO/api-info
|
|
# - patch : from META-INFO/api-info
|
|
# - branch : from META-INFO/build-info
|
|
# - build : from META-INFO/build-info
|
|
#
|
|
# Failure modes:
|
|
# - Directory, file or entry not found.
|
|
# -> corresponding entries are empty strings
|
|
getMetaInfo()
|
|
{
|
|
if [ -n "$meta_info" ]
|
|
then
|
|
##echo "use cached value for meta info" 1>&2
|
|
return 0
|
|
fi
|
|
##echo "get meta info" 1>&2
|
|
|
|
local api patch build branch
|
|
unset meta_api meta_patch meta_branch meta_build
|
|
|
|
if [ -d "$META_INFO" ]
|
|
then
|
|
# (api, patch) from api-info
|
|
# (branch, build) from build-info
|
|
|
|
api="$(sed -ne 's@^api *= *\([0-9][0-9]*\).*@\1@p' "$META_INFO/api-info" 2>/dev/null)"
|
|
patch="$(sed -ne 's@^patch *= *\([0-9][0-9]*\).*@\1@p' "$META_INFO/api-info" 2>/dev/null)"
|
|
branch="$(sed -ne 's@^branch *= *\([^ ]*\).*@\1@p' "$META_INFO/build-info" 2>/dev/null)"
|
|
build="$(sed -ne 's@^build *= *\([^ ]*\).*@\1@p' "$META_INFO/build-info" 2>/dev/null)"
|
|
fi
|
|
|
|
meta_api="$api"
|
|
meta_patch="${patch:-0}" # Default is 0 (unpatched)
|
|
meta_branch="$branch"
|
|
meta_build="$build"
|
|
meta_info=true
|
|
}
|
|
|
|
|
|
# Get api from rules/General/general
|
|
#
|
|
# Failure modes:
|
|
# - No api information (can't find file etc).
|
|
# -> Fatal for building, but could be OK for a stripped down version
|
|
#
|
|
# Fallback. Get from api-info
|
|
getApi()
|
|
{
|
|
getMakeInfo
|
|
|
|
# Local copy
|
|
local api="${make_api}"
|
|
|
|
if [ -z "$api" ]
|
|
then
|
|
getMetaInfo
|
|
api="${meta_api}"
|
|
fi
|
|
|
|
if [ -n "$api" ]
|
|
then
|
|
echo "$api"
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
|
|
# Get patch from meta-info / api-info
|
|
#
|
|
# Failure modes:
|
|
# - No patch information (can't find file etc).
|
|
getPatchLevel()
|
|
{
|
|
getMetaInfo
|
|
|
|
# Local copy
|
|
local patch="${meta_patch}"
|
|
|
|
if [ -n "$patch" ]
|
|
then
|
|
echo "$patch"
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
|
|
#
|
|
# Report make info
|
|
#
|
|
reportMakeInfo()
|
|
{
|
|
getMakeInfo
|
|
getMetaInfo
|
|
|
|
echo "make"
|
|
echo " api = ${make_api}"
|
|
echo " patch = ${meta_patch:-0}" # <- From meta-info only
|
|
echo " branch = ${make_branch}"
|
|
echo " build = ${make_build}"
|
|
}
|
|
|
|
|
|
#
|
|
# Report meta info
|
|
#
|
|
reportMetaInfo()
|
|
{
|
|
getMetaInfo
|
|
|
|
echo "meta"
|
|
echo " api = ${meta_api}"
|
|
echo " patch = ${meta_patch:-0}" # <- From meta-info only
|
|
echo " branch = ${meta_branch}"
|
|
echo " build = ${meta_build}"
|
|
}
|
|
|
|
|
|
# Report diff between make and meta info (single key).
|
|
# Set diff_header prior to the first call.
|
|
# $1 == key
|
|
# $2 == make value
|
|
# $3 == meta value
|
|
unset diff_header
|
|
_reportDiff()
|
|
{
|
|
if [ -n "$diff_header" ]
|
|
then
|
|
echo "$diff_header"
|
|
unset diff_header
|
|
fi
|
|
echo "$1:"
|
|
echo " make $2"
|
|
echo " meta $3"
|
|
}
|
|
|
|
|
|
# Test make vs meta info.
|
|
# Return 0 for no differences, 1 otherwise
|
|
# $1 == verbose, print as diff. Silent otherwise
|
|
checkDiff()
|
|
{
|
|
local diff verbose
|
|
|
|
if [ "$1" = "verbose" ]
|
|
then
|
|
diff_header="Differences"
|
|
verbose=true
|
|
fi
|
|
|
|
getMakeInfo
|
|
getMetaInfo
|
|
|
|
# api
|
|
if [ "${make_api}" != "${meta_api}" ]
|
|
then
|
|
diff=true
|
|
|
|
if [ -n "$verbose" ]
|
|
then
|
|
_reportDiff "api" "${make_api}" "${meta_api}"
|
|
fi
|
|
fi
|
|
|
|
# patch
|
|
if [ "${make_patch}" != "${meta_patch}" ]
|
|
then
|
|
diff=true
|
|
|
|
if [ -n "$verbose" ]
|
|
then
|
|
_reportDiff "patch" "${make_patch}" "${meta_patch}"
|
|
fi
|
|
fi
|
|
|
|
# branch - only test when make info is non-empty
|
|
if [ -n "${make_branch}" ] && [ "${make_branch}" != "${meta_branch}" ]
|
|
then
|
|
diff=true
|
|
|
|
if [ -n "$verbose" ]
|
|
then
|
|
_reportDiff "branch" "${make_branch}" "${meta_branch}"
|
|
fi
|
|
fi
|
|
|
|
# build - only test when make info is non-empty
|
|
if [ -n "${make_build}" ] && [ "${make_build}" != "${meta_build}" ]
|
|
then
|
|
diff=true
|
|
|
|
if [ -n "$verbose" ]
|
|
then
|
|
_reportDiff "build" "${make_build}" "${meta_build}"
|
|
fi
|
|
fi
|
|
|
|
# No diffs, but never permit entirely empty values for build.
|
|
test -z "$diff" || test -z "${make_build}${meta_build}"
|
|
}
|
|
|
|
|
|
#
|
|
# Update meta info (on disk) based on the make info
|
|
#
|
|
performUpdate()
|
|
{
|
|
getMakeInfo
|
|
getMetaInfo
|
|
|
|
# Local copies of the make info
|
|
local api="${make_api}"
|
|
local branch="${make_branch}"
|
|
local build="${make_build}"
|
|
local patch="${make_patch}"
|
|
|
|
# If any of the make-info are empty (bad),
|
|
# use the meta-info to avoid spurious changes
|
|
[ -n "$api" ] || api="${meta_api}"
|
|
[ -n "$branch" ] || branch="${meta_branch}"
|
|
[ -n "$build" ] || build="${meta_build}"
|
|
|
|
# Fallback to WM_PROJECT_VERSION alone
|
|
[ -n "$build" ] || build="${WM_PROJECT_VERSION:-unknown}"
|
|
|
|
local outputFile
|
|
|
|
# build-info
|
|
outputFile="$META_INFO/build-info"
|
|
if [ "$branch" != "${meta_branch}" ] || \
|
|
[ "$build" != "${meta_build}" ] || \
|
|
[ "$patch" != "${meta_patch}" ]
|
|
then
|
|
patch="${meta_patch:-0}" # <- From meta-info only
|
|
|
|
if [ -n "$optDryRun" ]
|
|
then
|
|
echo "dry-run (update) ${outputFile##*/} branch=${branch}" 1>&2
|
|
echo "dry-run (update) ${outputFile##*/} build=${build}" 1>&2
|
|
echo "dry-run (update) ${outputFile##*/} patch=${patch}" 1>&2
|
|
else
|
|
echo "branch=${branch}" >| "$outputFile"
|
|
echo "build=${build}" >> "$outputFile"
|
|
echo "patch=${patch}" >> "$outputFile"
|
|
fi
|
|
fi
|
|
|
|
|
|
# api-info
|
|
outputFile="$META_INFO/api-info"
|
|
if [ "$api" != "${meta_api}" ]
|
|
then
|
|
patch="${meta_patch:-0}" # <- From meta-info only
|
|
|
|
if [ -n "$optDryRun" ]
|
|
then
|
|
echo "dry-run (update) ${outputFile##*/} api=${api}" 1>&2
|
|
echo "dry-run (update) ${outputFile##*/} patch=${patch}" 1>&2
|
|
else
|
|
echo "api=${api}" >| "$outputFile"
|
|
echo "patch=${patch}" >> "$outputFile"
|
|
fi
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
|
|
#
|
|
# Update meta info (on disk) based on the make info
|
|
#
|
|
performFiltering()
|
|
{
|
|
local input="$1"
|
|
|
|
[ -f "$input" ] || {
|
|
echo "Error in ${0##*/}: file not found '$1'" 1>&2
|
|
exit 2
|
|
}
|
|
|
|
getMakeInfo
|
|
getMetaInfo
|
|
|
|
# Local copies of the make info
|
|
local api="${make_api}"
|
|
local branch="${make_branch}"
|
|
local build="${make_build}"
|
|
local patch="${meta_patch:-0}" # <- From meta-info only
|
|
|
|
|
|
# If any of the make-info are empty (bad),
|
|
# conjure up something from the meta-info
|
|
|
|
# api is not normally needed (available directly from -Ddefine)
|
|
# but we may wish to filter other types of files
|
|
|
|
if [ -z "$api" ]
|
|
then
|
|
api="${meta_api}"
|
|
api="${api:-0}" # integer value
|
|
fi
|
|
|
|
# branch/build could be missing for non-git
|
|
if [ -z "$branch" ]
|
|
then
|
|
branch="${meta_branch}"
|
|
branch="${branch:-unknown}"
|
|
fi
|
|
|
|
if [ -z "$build" ]
|
|
then
|
|
build="${meta_build}"
|
|
# Fallback to WM_PROJECT_VERSION
|
|
build="${build:-${WM_PROJECT_VERSION:-unknown}}"
|
|
fi
|
|
|
|
sed \
|
|
-e 's!@API@!'"${api}"'!g' \
|
|
-e 's!@PATCH@!'"${patch:-0}"'!g' \
|
|
-e 's!@BRANCH@!'"${branch}"'!g' \
|
|
-e 's!@BUILD@!'"${build}"'!g' \
|
|
-e 's!@VERSION@!'"${WM_PROJECT_VERSION}"'!g' \
|
|
"$input"
|
|
|
|
return 0
|
|
}
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
# Dispatch
|
|
|
|
if [ -n "$optCheck" ]
|
|
then
|
|
checkDiff $optCheck
|
|
exit $?
|
|
elif [ "$optQuery" = api ]
|
|
then
|
|
# Show API and exit
|
|
getApi
|
|
exit $?
|
|
elif [ "$optQuery" = patch ]
|
|
then
|
|
# Show patch level and exit
|
|
getPatchLevel
|
|
exit $?
|
|
else
|
|
# Other queries
|
|
case "$optQuery" in (*make*) reportMakeInfo ;; esac
|
|
case "$optQuery" in (*meta*) reportMetaInfo ;; esac
|
|
fi
|
|
|
|
[ -n "$optUpdate" ] && performUpdate
|
|
|
|
if [ -n "$optFilter" ]
|
|
then
|
|
# Perform filter on file
|
|
performFiltering "$1"
|
|
fi
|
|
|
|
exit 0 # clean exit
|
|
|
|
#------------------------------------------------------------------------------
|