Project

General

Profile

1
#!/bin/bash -e
2
# run scripts: a bash-based replacement for make
3
# unlike make, supports full bash functionality including multiline commands
4
# usage: path/to/dir/run cmd args
5

    
6
if false; then #### run script template:
7
#!/bin/bash -e
8
. "$(dirname "${BASH_SOURCE[0]}")"/path/to/util.run or file_including_util.run
9
. "$(dirname "${BASH_SOURCE[0]}")"/other_includes
10

    
11
cmd ()
12
{
13
	echo_func "$@"
14
	"$(dirname "${BASH_SOURCE[0]}")"/path_relative_to_self
15
	"$(dirname "${BASH_SOURCE[1]}")"/path_relative_to_caller
16
	"$top_dir"/path_relative_to_outermost_script
17
}
18
fi ####
19

    
20
: "${verbose=2}"
21

    
22
include_guard_var () { readlink -f -- "$1"|sed 's/[^a-zA-Z0-9_]/_/g'; }
23

    
24
self_not_included () # usage: if self_not_included; then ... fi
25
{
26
	test "$#" -ge 1 || set -- "${BASH_SOURCE[1]}"
27
	local include_guard="$(include_guard_var "$1")"
28
	test -z "${!include_guard+t}" && eval "$include_guard"=1
29
}
30

    
31
if self_not_included "${BASH_SOURCE[0]}"; then
32

    
33
shopt -s expand_aliases
34

    
35
set_var () { eval "$1"'="$2"'; }
36

    
37
reverse () # usage: array=($(reverse args...))
38
{
39
	local i
40
	for (( i=$#; i >= 1; i-- )); do printf '%q ' "${!i}"; done
41
}
42

    
43
: "${verbose:=0}"
44

    
45
echo_cmd () { echo "$PS4$*" >&2; }
46

    
47
echo_run () { echo_cmd "$@"; "$@"; }
48

    
49
canon_rel_path ()
50
{
51
	local path="$1"
52
	path="$(readlink -f -- "$path")" # canonicalize
53
	path="${path#$PWD/}" # remove any shared prefix with the current dir
54
	echo "$path"
55
}
56

    
57
# usage: echo_func "$@"
58
echo_func ()
59
{
60
	local script="$(canon_rel_path "${BASH_SOURCE[1]}")"
61
	echo_cmd "$script:${BASH_LINENO[0]}" "${FUNCNAME[1]}" "$@"
62
}
63

    
64
echo_stdin () # usage: input|echo_stdin|cmd
65
{
66
	echo ----- >&2
67
	tee -a /dev/stderr;
68
	echo ----- >&2
69
}
70

    
71
echo_vars () { declare -p "${@%%=*}" >&2; } # usage: echo_vars var...
72

    
73
echo_export ()
74
{
75
	builtin export "$@"
76
	echo_vars "$@"
77
}
78

    
79
if test "$verbose" -ge 2; then
80
	alias export="echo_export" # automatically echo env vars when they are set
81
fi
82

    
83
usage () { echo "Usage: $1" >&2; (exit 2); }
84

    
85
top_dir="$(dirname "$0")" # outermost script
86

    
87
run_args_cmd () # runs the command line args command
88
{
89
	test "$?" -eq 0 || return
90
	eval set -- "$(reverse "${BASH_ARGV[@]}")"
91
	test "$#" -ge 1 || set -- all
92
	echo_cmd "$(canon_rel_path "$0")" "$@"; "$@"
93
}
94

    
95
# users can override this function to perform other commands (or no commands)
96
# after the script is read
97
on_exit () { run_args_cmd; }
98
trap on_exit EXIT
99

    
100
fwd () # usage: subdirs=(...); fwd "$FUNCNAME" "$@"
101
{
102
	echo_func "$@"
103
	: "${subdirs?}"
104
	
105
	for subdir in "${subdirs[@]}"; do
106
		"$(dirname "${BASH_SOURCE[1]}")"/"$subdir"/run "$@"
107
	done
108
}
109

    
110
make ()
111
{
112
	echo_func "$@"
113
	echo_run env make --directory="$top_dir" "$@"
114
}
115

    
116
if false; then ## usage:
117
inline_make 3<<'EOF'
118
target:
119
	$(self_dir)/cmd >$@
120
EOF
121
# target will be run automatically because it's first in the makefile
122
fi ##
123
inline_make ()
124
{
125
	echo_func "$@"
126
	local self="$(readlink -f "${BASH_SOURCE[1]}")"
127
	local self_dir="$(dirname "$self")"
128
	export self self_dir
129
	
130
	make --makefile=<((
131
		cat /dev/fd/3
132
		echo -n "
133
.SUFFIXES: # turn off built-in suffix rules
134
.SECONDARY: # don't automatically delete intermediate files
135
.DELETE_ON_ERROR: # delete target if recipe fails
136
"
137
	)|echo_stdin) "$@"
138
}
139

    
140
alias zip="echo_run zip"
141
alias unzip="echo_run unzip"
142
alias zip_newer="zip -u"
143
alias unzip_newer="unzip -u -o" # -o is safe b/c -u only extracts newer files
144

    
145
fi
(47-47/52)