Project

General

Profile

1 8291 aaronmk
#!/bin/bash -e
2
shopt -s expand_aliases
3 8272 aaronmk
# run scripts: a bash-based replacement for make
4
# unlike make, supports full bash functionality including multiline commands
5
# usage: path/to/dir/run cmd args
6
7
if false; then #### run script template:
8 8291 aaronmk
#!/bin/bash -e
9 8272 aaronmk
. "$(dirname "${BASH_SOURCE[0]}")"/path/to/util.run or file_including_util.run
10
. "$(dirname "${BASH_SOURCE[0]}")"/other_includes
11
12
cmd ()
13
{
14 8463 aaronmk
	echo_func "$@"
15 8272 aaronmk
	"$(dirname "${BASH_SOURCE[0]}")"/path_relative_to_self
16
	"$(dirname "${BASH_SOURCE[1]}")"/path_relative_to_caller
17
	"$top_dir"/path_relative_to_outermost_script
18
}
19
fi ####
20
21 8691 aaronmk
reverse () # usage: array=($(reverse args...))
22
{
23
	local i
24
	for (( i=$#; i >= 1; i-- )); do printf '%q ' "${!i}"; done
25
}
26
27 8278 aaronmk
echo_cmd () { echo "$PS4$*" >&2; }
28 8272 aaronmk
29 8278 aaronmk
echo_run () { echo_cmd "$@"; "$@"; }
30
31 8646 aaronmk
canon_rel_path ()
32
{
33
	local path="$1"
34
	path="$(readlink -f -- "$path")" # canonicalize
35
	path="${path#$PWD/}" # remove any shared prefix with the current dir
36
	echo "$path"
37
}
38
39 8463 aaronmk
# usage: echo_func "$@"
40
echo_func ()
41
{
42 8647 aaronmk
	local script="$(canon_rel_path "${BASH_SOURCE[1]}")"
43
	echo_cmd "$script:${BASH_LINENO[0]}" "${FUNCNAME[1]}" "$@"
44 8463 aaronmk
}
45 8279 aaronmk
46 8275 aaronmk
echo_stdin () { tee -a /dev/stderr; } # usage: input|echo_stdin|cmd
47
48 8650 aaronmk
echo_vars () { declare -p "${@%%=*}" >&2; } # usage: echo_vars var...
49 8641 aaronmk
50
echo_export ()
51
{
52 8649 aaronmk
	export "$@"
53 8641 aaronmk
	echo_vars "$@"
54
}
55
56 8643 aaronmk
alias export="echo_export" # automatically echo env vars when they are set
57 8642 aaronmk
58 8272 aaronmk
usage () { echo "Usage: $1" >&2; (exit 2); }
59
60
top_dir="$(dirname "$0")" # outermost script
61
62 8465 aaronmk
run_args_cmd () # runs the command line args command
63 8272 aaronmk
{
64 8292 aaronmk
	test "$?" -eq 0 || return
65 8693 aaronmk
	eval set -- "$(reverse "${BASH_ARGV[@]}")"
66 8290 aaronmk
	test "$#" -ge 1 || set -- all
67 8648 aaronmk
	echo_cmd "$(canon_rel_path "$0")" "$@"; "$@"
68 8272 aaronmk
}
69
70 8464 aaronmk
# users can override this function to perform other commands (or no commands)
71
# after the script is read
72 8465 aaronmk
on_exit () { run_args_cmd; }
73 8464 aaronmk
trap on_exit EXIT
74
75 8284 aaronmk
fwd () # usage: subdirs=(...); fwd "$FUNCNAME" "$@"
76 8272 aaronmk
{
77 8463 aaronmk
	echo_func "$@"
78 8284 aaronmk
	: "${subdirs?}"
79
80 8272 aaronmk
	for subdir in "${subdirs[@]}"; do
81 8280 aaronmk
		"$(dirname "${BASH_SOURCE[1]}")"/"$subdir"/run "$@"
82 8272 aaronmk
	done
83
}
84
85 8280 aaronmk
make ()
86
{
87 8463 aaronmk
	echo_func "$@"
88 8280 aaronmk
	echo_run env make --directory="$top_dir" "$@"
89
}
90 8272 aaronmk
91 8276 aaronmk
if false; then ## usage:
92 8652 aaronmk
inline_make 3<<'EOF'
93 8276 aaronmk
target:
94
	$(self_dir)/cmd >$@
95
EOF
96
# target will be run automatically because it's first in the makefile
97
fi ##
98
inline_make ()
99
{
100 8653 aaronmk
	echo_func "$@"
101 8640 aaronmk
	local self="$(readlink -f "${BASH_SOURCE[1]}")"
102
	local self_dir="$(dirname "$self")"
103 8645 aaronmk
	export self self_dir
104 8640 aaronmk
105 8651 aaronmk
	make --makefile=<((
106 8652 aaronmk
		cat /dev/fd/3
107 8651 aaronmk
		echo -n "
108 8276 aaronmk
.SUFFIXES: # turn off built-in suffix rules
109
.SECONDARY: # don't automatically delete intermediate files
110
.DELETE_ON_ERROR: # delete target if recipe fails
111 8651 aaronmk
"
112
	)|echo_stdin) "$@"
113 8276 aaronmk
}
114 8658 aaronmk
115
alias zip="echo_run zip"
116
alias unzip="echo_run unzip"
117 8659 aaronmk
alias zip_newer="zip -u"
118
alias unzip_newer="unzip -u -o" # -o is safe b/c -u only extracts newer files