1 # Makefile.sh - POSIX Makefile scripting adjunct for TopGit
2 # Copyright (C) 2017 Kyle J. McKay
6 # Set MAKEFILESH_DEBUG to get:
7 # 1. All defined environment variales saved to Makefile.var
9 # 3. set -v if MAKEFILESH_DEBUG contains "v"
11 if [ -n "$MAKEFILESH_DEBUG" ]; then
13 case "$MAKEFILESH_DEBUG" in *"v"*) _setcmd
="set -vx"; esac
14 eval "$_setcmd && unset _setcmd"
17 # prevent crazy "sh" implementations from exporting functions into environment
20 # common defines for all makefile(s)
24 # Update if you add any code that requires a newer version of git
25 : "${GIT_MINIMUM_VERSION:=1.8.5}"
27 # This avoids having this in no less than three different places!
28 TG_STATUS_HELP_USAGE
="st[atus] [-v] [--exit-code]"
30 # These are initialized here so config.sh or config.mak can change them
31 # They are deliberately left with '$(...)' constructs for make to expand
32 # so that if config.mak just sets prefix they all automatically change
33 [ -n "$prefix" ] || prefix
="$HOME"
34 [ -n "$bindir" ] || bindir
='$(prefix)/bin'
35 [ -n "$cmddir" ] || cmddir
='$(prefix)/libexec/topgit'
36 [ -n "$sharedir" ] || sharedir
='$(prefix)/share/topgit'
37 [ -n "$hooksdir" ] || hooksdir
='$(cmddir)/hooks'
40 # wrap it up for safe returns
41 # $1 is the current build target, if any
44 v_wildcard commands_in
'tg-[!-]*.sh'
45 v_wildcard utils_in
'tg--*.sh'
46 v_wildcard awk_in
'awk/*.awk'
47 v_wildcard hooks_in
'hooks/*.sh'
48 v_wildcard helpers_in
't/helper/*.sh'
50 v_strip_sfx commands_out .sh
$commands_in
51 v_strip_sfx utils_out .sh
$utils_in
52 v_strip_sfx awk_out .
awk $awk_in
53 v_strip_sfx hooks_out .sh
$hooks_in
54 v_strip_sfx helpers_out .sh
$helpers_in
56 v_stripadd_sfx help_out .sh .txt tg-help.sh tg-status.sh
$commands_in
57 v_stripadd_sfx html_out .sh .html tg-help.sh tg-status.sh tg-tg.sh
$commands_in
59 DEPFILE
="Makefile.dep"
61 write_auto_deps
'' '.sh' tg
$commands_out $utils_out $hooks_out $helpers_out
62 write_auto_deps
'' '.awk' $awk_out
65 : "${SHELL_PATH:=/bin/sh}" "${AWK_PATH:=awk}"
67 test -d .git && git describe --match "topgit-
[0-9]*" --abbrev=4 --dirty 2>/dev/null |
68 sed -e 's/^topgit-//')" ||
:
70 # config.sh is wrapped up for return safety
73 # config.sh may not unset these
74 : "${SHELL_PATH:=/bin/sh}" "${AWK_PATH:=awk}"
76 case "$AWK_PATH" in */*) AWK_PREFIX
=;; *) AWK_PREFIX
="/usr/bin/"; esac
77 quotevar SHELL_PATH SHELL_PATH_SQ
78 quotevar AWK_PATH AWK_PATH_SQ
80 v_strip version
"$version"
82 [ -z "$version" ] || version_arg
="-e 's/TG_VERSION=.*/TG_VERSION=\"$version\"/'"
85 [ -z "$DESTDIR" ] || DESTDIRBOOL
="Yes"
87 [ -z "$MAKEFILESH_DEBUG" ] ||
{
88 printenv | LC_ALL
=C
grep '^[_A-Za-z][_A-Za-z0-9]*=' | LC_ALL
=C
sort
91 # Force TG-BUILD-SETTINGS to be updated now if needed
92 ${MAKE:-make} -f Makefile.mak FORCE_SETTINGS_BUILD
=FORCE TG-BUILD-SETTINGS
101 # wrap it up for safety
103 ! [ -f "${MKTOP:+$MKTOP/}config.sh" ] ||
104 . .
/"${MKTOP:+$MKTOP/}config.sh"
105 # now set CONFIGMAK and make it an absolute path
106 [ -n "$CONFIGMAK" ] || CONFIGMAK
="${MKTOP:+$MKTOP/}config.mak"
107 [ -f "$CONFIGMAK" ] || CONFIGMAK
="${MKTOP:+$MKTOP/}Makefile.mt"
108 case "$CONFIGMAK" in */?
*);;*) CONFIGMAK
="./$CONFIGMAK"; esac
109 CONFIGMAK
="$(cd "${CONFIGMAK%/*}" && pwd)/${CONFIGMAK##*/}"
113 { "unset" -f command unset unalias "$1"; } >/dev
/null
2>&1 ||
:
114 { "unalias" -a ||
unalias -m "*"; } >/dev
/null
2>&1 ||
:
118 # stores the single-quoted value of the variable name passed as
119 # the first argument into the variable name passed as the second
120 # (use quotevar 3 varname "$value" to quote a value directly)
122 eval "set -- \"\${$1}\" \"$2\""
124 set -- "$(printf '%s\nZ\n' "$1" | sed "s
/'/'\\\''/g")" "$2"
125 set -- "${1%??}" "$2"
130 # The result(s) of stripping the second argument from the end of the
131 # third and following argument(s) is joined using a space and stored
132 # in the variable named by the first argument
138 for _item in "$@"; do
139 _result="$_result ${_item%$_sfx}"
141 eval "$_var="'"${_result# }"'
142 unset _var _sfx _result _item
145 # The result(s) of appending the second argument to the end of the
146 # third and following argument(s) is joined using a space and stored
147 # in the variable named by the first argument
153 for _item in "$@"; do
154 _result="$_result $_item$_sfx"
156 eval "$_var="'"${_result# }"'
157 unset _var _sfx _result _item
160 # The result(s) of stripping the second argument from the end of the
161 # fourth and following argument(s) and then appending the third argument is
162 # joined using a space and stored in the variable named by the first argument
168 v_strip_sfx _result2 "$_stripsfx" "$@"
169 v_add_sfx "$_var2" "$_addsfx" $_result2
170 unset _var2 _stripsfx _addsfx _result2
173 # The second and following argument(s) are joined with a space and
174 # stored in the variable named by the first argument
182 # The second and following argument(s) are joined with a space and then
183 # the result has leading and trailing whitespace removed and internal
184 # whitespace sequences replaced with a single space and is then stored
185 # in the variable named by the first argument and pathname expansion is
186 # disabled during the stripping process
195 # Expand the second and following argument(s) using pathname expansion but
196 # skipping any that have no match and join all the results using a space and
197 # store that in the variable named by the first argument
202 for _item in "$@"; do
203 eval "_exp=\"\$(printf ' %s
' $_item)\""
204 [ " $_item" = "$_exp" ] && ! [ -e "$_item" ] || _result="$_result$_exp"
206 eval "$_var="'"${_result# }"'
207 unset _var _result _item _exp
210 # Sort the second and following argument(s) removing duplicates and join all the
211 # results using a space and store that in the variable named by the first argument
218 set -- $(printf '%s
\n' "$@" | LC_ALL=C sort -u)
224 # Filter the fourth and following argument(s) according to the space-separated
225 # list of '%' pattern(s) in the third argument doing a "filter-out" instead of
226 # a "filter" if the second argument is true and join all the results using a
227 # space and store that in the variable named by the first argument
236 set -- $(awk -v "fo=$_fo" -f - "$_pat" "$*"<<'EOT'
238 gsub(/[][*?+.|{}()^$\\]/, "\\\\&", p)
242 if (match(p, /\\*%/)) {
243 return qr(substr(p, 1, RSTART - 1)) \
244 substr(p, RSTART, RLENGTH - (2 - RLENGTH % 2)) \
245 (RLENGTH % 2 ? ".*" : "%") \
246 qr(substr(p, RSTART + RLENGTH))
251 function qm(s, _l, _c, _a, _i, _g) {
252 if (!(_c = split(s, _l, " "))) return "^$"
253 if (_c == 1) return "^" qp(_l[1]) "$"
256 for (_i = 1; _i <= _c; ++_i) {
257 _a = _a _g qp(_l[_i])
267 cnt = split(vals, va, " ")
268 for (i=1; i<=cnt; ++i)
269 if ((va[i] ~ qpat) == !fo) print va[i]
275 unset _var _fo _pat _saveifs
278 # Filter the third and following argument(s) according to the space-separated
279 # list of '%' pattern(s) in the second argument and join all the results using
280 # a space and store that in the variable named by the first argument
284 v_filter_ "$_var" "" "$@"
287 # Filter out the third and following argument(s) according to the space-separated
288 # list of '%' pattern(s) in the second argument and join all the results using
289 # a space and store that in the variable named by the first argument
293 v_filter_ "$_var" "1" "$@"
296 # Write the third and following target arguments out as target with a dependency
297 # line(s) to standard output where each line is created by stripping the target
298 # argument suffix specified by the first argument ('' to strip nothing) and
299 # adding the suffix specified by the second argument ('' to add nothing).
300 # Does nothing if "$1" = "$2". (Set $1 = " " and $2 = "" to write out
301 # dependency lines with no prerequisites.)
303 [ "$1" != "$2" ] || return 0
307 for _targ in "$@"; do
308 printf '%s
: %s
\n' "$_targ" "${_targ%$_strip}$_add"
310 unset _strip _add _targ
314 ## Run "makefile" now unless MKTOP is set
319 [ -n "$MKTOP" ] || makefile "$@"