2014-06-10 20:25:35 +00:00
|
|
|
#!/usr/bin/env bash
|
2014-10-15 18:00:44 +00:00
|
|
|
#
|
|
|
|
# TROUBLESHOOTING
|
2014-11-18 12:32:17 +00:00
|
|
|
# - If you see 'undefined reference to `AES_encrypt'',
|
|
|
|
# make sure you have openssl installed.
|
2014-11-18 14:56:53 +00:00
|
|
|
# If libcrypto.a is in a non-standard directory, try ./build -L[your-lib-dir]
|
2014-10-23 02:29:05 +00:00
|
|
|
# - If you see 'undefined reference to `clock_gettime'',
|
|
|
|
# try ./build -lrt instead.
|
|
|
|
# - If you see 'x86.S:202: Error: junk at end of line, first unrecognized character is `,'',
|
|
|
|
# try commenting the line in lib/bcrypt/x86.S.
|
2014-11-21 13:06:29 +00:00
|
|
|
# - Take a look at the "Optional features" section. Some features have dependencies,
|
|
|
|
# either make sure you have them or disable those features.
|
2017-03-06 23:18:25 +00:00
|
|
|
# eg. mpw_color=0 ./build
|
2014-10-15 18:00:44 +00:00
|
|
|
#
|
|
|
|
# BUGS
|
|
|
|
# masterpassword@lyndir.com
|
|
|
|
#
|
|
|
|
# AUTHOR
|
|
|
|
# Maarten Billemont
|
|
|
|
#
|
2014-10-15 12:44:41 +00:00
|
|
|
cd "${BASH_SOURCE%/*}"
|
2014-10-16 02:17:49 +00:00
|
|
|
shopt -s extglob
|
2014-10-15 12:44:41 +00:00
|
|
|
set -e
|
2014-06-07 05:27:18 +00:00
|
|
|
|
2014-10-19 00:56:28 +00:00
|
|
|
|
|
|
|
### CONFIGURATION
|
|
|
|
|
|
|
|
# Targets to build.
|
|
|
|
if [[ $targets ]]; then
|
|
|
|
read -ra targets <<< "$targets"
|
|
|
|
else
|
|
|
|
# Default targets.
|
|
|
|
# Modify here or override using targets='mpw mpw-bench' ./build
|
|
|
|
targets=(
|
|
|
|
mpw # C CLI version of Master Password.
|
2014-12-05 22:56:50 +00:00
|
|
|
mpw-bench # C CLI Master Password benchmark utility.
|
2014-12-22 04:45:19 +00:00
|
|
|
mpw-tests # C Master Password algorithm tester.
|
2014-10-19 00:56:28 +00:00
|
|
|
)
|
|
|
|
fi
|
2014-10-15 18:00:44 +00:00
|
|
|
|
2014-11-21 13:06:29 +00:00
|
|
|
# Optional features.
|
2017-03-06 23:18:25 +00:00
|
|
|
mpw_color=${mpw_color:-1} # Colorized Identicon, requires libncurses-dev
|
2014-11-21 13:06:29 +00:00
|
|
|
|
2017-04-08 18:25:54 +00:00
|
|
|
# Default build flags.
|
|
|
|
export CFLAGS="-O3 $CFLAGS"
|
|
|
|
export LDFLAGS="$LDFLAGS"
|
|
|
|
|
2017-04-08 20:20:58 +00:00
|
|
|
# Distribution specific configuration.
|
|
|
|
# Homebrew - openssl for scrypt
|
|
|
|
if hash brew 2>/dev/null; then
|
|
|
|
opensslPath=$(brew --prefix openssl)
|
|
|
|
CFLAGS+=" -I$opensslPath/include"
|
|
|
|
LDFLAGS+=" -L$opensslPath/lib"
|
|
|
|
fi
|
2014-10-15 18:00:44 +00:00
|
|
|
|
|
|
|
### DEPENDENCIES
|
|
|
|
|
2014-10-23 01:17:02 +00:00
|
|
|
digest() {
|
2014-10-23 16:03:19 +00:00
|
|
|
openssl sha -sha256 -binary < "$1" | od -t x1 -An -v | tr -d '[:space:]'
|
2014-10-23 01:17:02 +00:00
|
|
|
}
|
2014-10-16 02:17:49 +00:00
|
|
|
fetch() {
|
|
|
|
if hash wget 2>/dev/null; then
|
|
|
|
wget -O "${1##*/}" "$1"
|
|
|
|
elif hash curl 2>/dev/null; then
|
|
|
|
curl "$1" > "${1##*/}"
|
|
|
|
fi
|
|
|
|
}
|
2014-10-19 00:56:28 +00:00
|
|
|
unpack() {
|
2015-11-05 16:07:49 +00:00
|
|
|
printf 'Verifying package: %s, against digest: %s...' "$1" "$2"
|
|
|
|
[[ $(digest "$1") = $2 ]] || {
|
|
|
|
printf ' mismatch!\n'
|
|
|
|
echo 2>&1 "Downloaded package doesn't match digest."
|
|
|
|
exit 1
|
|
|
|
}
|
|
|
|
printf ' OK!\n'
|
|
|
|
|
2014-10-19 00:56:28 +00:00
|
|
|
if [[ $1 = *.tar.gz || $1 = *.tgz ]]; then
|
|
|
|
tar -xvzf "$1"
|
|
|
|
|
|
|
|
elif [[ $1 = *.tar.bz2 || $1 = *.tbz2 ]]; then
|
|
|
|
tar -xvjf "$1"
|
|
|
|
|
|
|
|
elif [[ $1 = *.tar ]]; then
|
|
|
|
tar -xvf "$1"
|
|
|
|
|
|
|
|
else
|
|
|
|
echo 2>&1 "Don't know how to unpack: $1"
|
|
|
|
fi
|
|
|
|
|
2015-11-05 16:07:49 +00:00
|
|
|
files=( * )
|
2014-10-19 00:56:28 +00:00
|
|
|
if [[ -d $files ]] && (( ${#files[@]} == 1 )); then
|
|
|
|
mv "$files"/* .
|
|
|
|
rmdir "$files"
|
|
|
|
fi
|
|
|
|
}
|
2014-10-16 02:17:49 +00:00
|
|
|
fetchSource() (
|
2015-11-05 15:33:30 +00:00
|
|
|
local name=${PWD##*/}
|
2014-10-16 02:17:49 +00:00
|
|
|
source .source
|
|
|
|
|
2015-01-20 01:58:53 +00:00
|
|
|
if [[ -e .unpacked ]]; then
|
|
|
|
true
|
|
|
|
|
|
|
|
elif [[ $pkg && -e "${pkg##*/}" ]]; then
|
2015-11-05 16:07:49 +00:00
|
|
|
[[ -e src ]] || {
|
2014-10-19 00:56:28 +00:00
|
|
|
echo
|
2015-11-05 15:33:30 +00:00
|
|
|
echo "Unpacking: $name, using package..."
|
2015-11-05 16:07:49 +00:00
|
|
|
( mkdir src && cd src && unpack "../${pkg##*/}" "$pkg_sha256" )
|
|
|
|
touch .unpacked
|
2014-10-19 00:56:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
elif [[ $git ]] && hash git 2>/dev/null; then
|
|
|
|
[[ -e .git ]] || {
|
|
|
|
echo
|
2015-11-05 15:33:30 +00:00
|
|
|
echo "Fetching: $name, using git..."
|
|
|
|
git clone "$git" src
|
2015-11-05 16:07:49 +00:00
|
|
|
touch .unpacked
|
2014-10-19 00:56:28 +00:00
|
|
|
}
|
2014-10-16 02:17:49 +00:00
|
|
|
|
2014-10-18 22:22:29 +00:00
|
|
|
elif [[ $svn ]] && hash git 2>/dev/null && [[ -x "$(git --exec-path)/git-svn" ]]; then
|
2014-10-19 00:56:28 +00:00
|
|
|
[[ -e .git ]] || {
|
|
|
|
echo
|
2015-11-05 15:33:30 +00:00
|
|
|
echo "Fetching: $name, using git-svn..."
|
|
|
|
git svn clone --prefix=origin/ --stdlayout "$svn" src
|
2015-11-05 16:07:49 +00:00
|
|
|
touch .unpacked
|
2014-10-19 00:56:28 +00:00
|
|
|
}
|
2014-10-16 02:17:49 +00:00
|
|
|
|
|
|
|
elif [[ $svn ]] && hash svn 2>/dev/null; then
|
2014-10-19 00:56:28 +00:00
|
|
|
[[ -e .svn ]] || {
|
|
|
|
echo
|
2015-11-05 15:33:30 +00:00
|
|
|
echo "Fetching: $name, using svn..."
|
|
|
|
svn checkout "$svn/trunk" src
|
2015-11-05 16:07:49 +00:00
|
|
|
touch .unpacked
|
2014-10-19 00:56:28 +00:00
|
|
|
}
|
2014-10-16 02:17:49 +00:00
|
|
|
|
|
|
|
elif [[ $pkg ]]; then
|
2015-11-05 16:07:49 +00:00
|
|
|
[[ -e src ]] || {
|
2014-10-19 00:56:28 +00:00
|
|
|
echo
|
2015-11-05 15:33:30 +00:00
|
|
|
echo "Fetching: $name, using package..."
|
2014-10-19 00:56:28 +00:00
|
|
|
fetch "$pkg"
|
2015-11-05 16:07:49 +00:00
|
|
|
( mkdir src && cd src && unpack "../${pkg##*/}" "$pkg_sha256" )
|
|
|
|
touch .unpacked
|
2014-10-19 00:56:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
else
|
2014-10-16 02:17:49 +00:00
|
|
|
|
2014-10-19 00:56:28 +00:00
|
|
|
echo >&2 "error: Missing git-svn or svn."
|
|
|
|
echo >&2 "error: Please install either or manually check out the sources"
|
|
|
|
echo >&2 "error: from: $home"
|
2015-11-05 15:33:30 +00:00
|
|
|
echo >&2 "error: into: $PWD/src"
|
2014-10-19 00:56:28 +00:00
|
|
|
exit 1
|
|
|
|
fi
|
2014-11-21 14:39:30 +00:00
|
|
|
|
2015-01-20 01:58:53 +00:00
|
|
|
if [[ ! -e .patched ]] && (( ${#patches[@]} )); then
|
2015-11-05 15:33:30 +00:00
|
|
|
pushd src
|
2015-01-20 01:58:53 +00:00
|
|
|
for patch in "${patches[@]}"; do
|
|
|
|
echo
|
2015-11-05 15:33:30 +00:00
|
|
|
echo "Patching: $name, for $patch..."
|
2015-11-05 16:07:49 +00:00
|
|
|
patch -p0 < "../$patch.patch"
|
2015-01-20 01:58:53 +00:00
|
|
|
done
|
2015-11-05 15:33:30 +00:00
|
|
|
popd
|
2015-01-20 01:58:53 +00:00
|
|
|
touch .patched
|
|
|
|
fi
|
2014-10-16 02:17:49 +00:00
|
|
|
)
|
|
|
|
depend() {
|
2015-11-05 15:33:30 +00:00
|
|
|
local name=$1
|
2014-10-16 02:17:49 +00:00
|
|
|
|
2014-10-15 12:44:41 +00:00
|
|
|
echo
|
2015-11-05 15:33:30 +00:00
|
|
|
echo "Checking dependency: $name..."
|
|
|
|
[[ -e "lib/include/$name" ]] && return
|
2014-10-16 02:17:49 +00:00
|
|
|
|
2015-11-05 15:33:30 +00:00
|
|
|
pushd "lib/$name"
|
2015-11-05 16:07:49 +00:00
|
|
|
fetchSource
|
2015-11-05 15:33:30 +00:00
|
|
|
pushd "src"
|
2014-06-07 19:51:11 +00:00
|
|
|
|
2014-10-16 02:17:49 +00:00
|
|
|
echo
|
2015-11-05 15:33:30 +00:00
|
|
|
echo "Configuring dependency: $name..."
|
2014-10-16 02:17:49 +00:00
|
|
|
if [[ -e configure.ac ]]; then
|
|
|
|
if [[ ! -e configure ]]; then
|
|
|
|
# create configure using autotools.
|
2014-10-18 19:38:51 +00:00
|
|
|
if ! hash aclocal || ! hash automake; then
|
2015-11-05 15:33:30 +00:00
|
|
|
echo >&2 "Need autotools to build $name. Please install automake and autoconf."
|
2014-10-18 19:38:51 +00:00
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
2014-10-16 02:17:49 +00:00
|
|
|
aclocal
|
|
|
|
autoheader
|
|
|
|
autoconf
|
|
|
|
mkdir -p config.aux
|
|
|
|
automake --add-missing
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [[ -e configure ]]; then
|
|
|
|
./configure
|
|
|
|
fi
|
|
|
|
|
|
|
|
echo
|
2015-11-05 15:33:30 +00:00
|
|
|
echo "Building dependency: $name..."
|
2014-10-16 02:17:49 +00:00
|
|
|
if [[ -e Makefile ]]; then
|
2014-10-18 19:38:51 +00:00
|
|
|
if ! hash make; then
|
2015-11-05 15:33:30 +00:00
|
|
|
echo >&2 "Need make to build $name. Please install GNU make."
|
2014-10-18 19:38:51 +00:00
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
2014-10-16 02:17:49 +00:00
|
|
|
make
|
2015-11-05 15:33:30 +00:00
|
|
|
install -d "../../include/$name/"
|
|
|
|
find . -name '*.h' -exec install -m 444 {} "../../include/$name/" \;
|
2014-10-16 02:17:49 +00:00
|
|
|
else
|
2015-11-05 15:33:30 +00:00
|
|
|
echo >&2 "error: Don't know how to build: $name"
|
2014-10-16 02:17:49 +00:00
|
|
|
exit 1
|
|
|
|
fi
|
2014-10-15 12:44:41 +00:00
|
|
|
popd
|
2015-11-05 15:33:30 +00:00
|
|
|
popd
|
2014-10-16 02:17:49 +00:00
|
|
|
}
|
2017-04-08 18:25:54 +00:00
|
|
|
depend_scrypt() {
|
2017-04-08 20:20:58 +00:00
|
|
|
if haslib sodium; then
|
2017-04-08 20:48:20 +00:00
|
|
|
if [[ $CFLAGS != *HAS_SODIUM=1* ]]; then
|
|
|
|
CFLAGS+=" -DHAS_SODIUM=1"
|
|
|
|
LDFLAGS+=" -lsodium"
|
|
|
|
fi
|
2017-04-08 18:25:54 +00:00
|
|
|
return
|
|
|
|
fi
|
|
|
|
|
|
|
|
depend scrypt
|
2017-04-08 20:48:20 +00:00
|
|
|
if [[ $CFLAGS != *HAS_CPERCIVA=1* ]]; then
|
|
|
|
local objects=(
|
|
|
|
"lib/scrypt/src/libcperciva/"*/*.o
|
|
|
|
"lib/scrypt/src/lib/crypto/"*.o
|
|
|
|
)
|
|
|
|
CFLAGS+=" -DHAS_CPERCIVA=1"
|
|
|
|
LDFLAGS+=" -Llib/scrypt/src ${objects[*]}"
|
|
|
|
fi
|
2017-04-08 18:25:54 +00:00
|
|
|
}
|
2014-10-15 12:44:41 +00:00
|
|
|
|
2014-10-15 20:26:09 +00:00
|
|
|
|
|
|
|
### MPW
|
|
|
|
mpw() {
|
2017-04-08 18:25:54 +00:00
|
|
|
depend_scrypt
|
2014-10-16 02:17:49 +00:00
|
|
|
|
2014-10-17 21:10:43 +00:00
|
|
|
echo
|
2014-10-16 02:17:49 +00:00
|
|
|
echo "Building target: $target..."
|
2015-02-09 20:51:12 +00:00
|
|
|
local CFLAGS=(
|
2017-04-08 18:25:54 +00:00
|
|
|
$CFLAGS
|
|
|
|
|
2017-03-21 18:07:40 +00:00
|
|
|
# library paths
|
2014-12-19 14:00:38 +00:00
|
|
|
-I"lib/include"
|
2017-03-21 18:07:40 +00:00
|
|
|
# mpw paths
|
|
|
|
-I"core" -I"cli"
|
2014-10-15 20:26:09 +00:00
|
|
|
)
|
2015-02-09 20:51:12 +00:00
|
|
|
local LDFLAGS=(
|
2017-04-08 18:25:54 +00:00
|
|
|
$LDFLAGS
|
|
|
|
|
2014-12-05 18:51:02 +00:00
|
|
|
# link libraries
|
|
|
|
-l"crypto"
|
2014-10-15 20:26:09 +00:00
|
|
|
)
|
2014-11-21 13:06:29 +00:00
|
|
|
# optional features
|
|
|
|
(( mpw_color )) && CFLAGS+=( -DCOLOR ) LDFLAGS+=( -l"curses" )
|
2014-10-15 20:26:09 +00:00
|
|
|
|
2017-03-21 18:07:40 +00:00
|
|
|
cc "${CFLAGS[@]}" "$@" -c core/mpw-algorithm.c -o core/mpw-algorithm.o
|
|
|
|
cc "${CFLAGS[@]}" "$@" -c core/mpw-types.c -o core/mpw-types.o
|
|
|
|
cc "${CFLAGS[@]}" "$@" -c core/mpw-util.c -o core/mpw-util.o
|
|
|
|
cc "${CFLAGS[@]}" "$@" "core/mpw-algorithm.o" "core/mpw-types.o" "core/mpw-util.o" \
|
|
|
|
"${LDFLAGS[@]}" "cli/mpw-cli.c" -o "mpw"
|
2014-10-15 20:26:09 +00:00
|
|
|
echo "done! Now run ./install or use ./mpw"
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
### MPW-BENCH
|
|
|
|
mpw-bench() {
|
2017-04-08 18:25:54 +00:00
|
|
|
depend_scrypt
|
2014-10-16 02:17:49 +00:00
|
|
|
depend bcrypt
|
|
|
|
|
2014-10-17 21:10:43 +00:00
|
|
|
echo
|
2014-10-16 02:17:49 +00:00
|
|
|
echo "Building target: $target..."
|
2015-02-09 20:51:12 +00:00
|
|
|
local CFLAGS=(
|
2017-04-08 18:25:54 +00:00
|
|
|
$CFLAGS
|
|
|
|
|
2017-03-21 18:07:40 +00:00
|
|
|
# library paths
|
2014-12-19 14:00:38 +00:00
|
|
|
-I"lib/include"
|
2017-03-21 18:07:40 +00:00
|
|
|
# mpw paths
|
|
|
|
-I"core" -I"cli"
|
2014-10-15 20:26:09 +00:00
|
|
|
)
|
2015-02-09 20:51:12 +00:00
|
|
|
local LDFLAGS=(
|
2017-04-08 18:25:54 +00:00
|
|
|
$LDFLAGS
|
|
|
|
|
2014-10-15 20:26:09 +00:00
|
|
|
# bcrypt
|
2015-11-05 15:33:30 +00:00
|
|
|
"lib/bcrypt/src/crypt_blowfish.o"
|
|
|
|
"lib/bcrypt/src/crypt_gensalt.o"
|
|
|
|
"lib/bcrypt/src/wrapper.o"
|
|
|
|
"lib/bcrypt/src/x86.o"
|
2014-12-05 18:51:02 +00:00
|
|
|
# library paths
|
2015-11-05 15:33:30 +00:00
|
|
|
-L"lib/bcrypt/src"
|
2014-12-22 04:45:19 +00:00
|
|
|
# link libraries
|
2014-12-05 18:51:02 +00:00
|
|
|
-l"crypto"
|
2014-10-15 20:26:09 +00:00
|
|
|
)
|
|
|
|
|
2017-03-21 18:07:40 +00:00
|
|
|
cc "${CFLAGS[@]}" "$@" -c core/mpw-algorithm.c -o core/mpw-algorithm.o
|
|
|
|
cc "${CFLAGS[@]}" "$@" -c core/mpw-types.c -o core/mpw-types.o
|
|
|
|
cc "${CFLAGS[@]}" "$@" -c core/mpw-util.c -o core/mpw-util.o
|
|
|
|
cc "${CFLAGS[@]}" "$@" "core/mpw-algorithm.o" "core/mpw-types.o" "core/mpw-util.o" \
|
|
|
|
"${LDFLAGS[@]}" "cli/mpw-bench.c" -o "mpw-bench"
|
2014-10-15 20:26:09 +00:00
|
|
|
echo "done! Now use ./mpw-bench"
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-12-22 04:45:19 +00:00
|
|
|
### MPW-TESTS
|
|
|
|
mpw-tests() {
|
2017-04-08 18:25:54 +00:00
|
|
|
depend_scrypt
|
2014-12-22 04:45:19 +00:00
|
|
|
|
|
|
|
echo
|
|
|
|
echo "Building target: $target..."
|
2015-02-09 20:51:12 +00:00
|
|
|
local CFLAGS=(
|
2017-04-08 18:25:54 +00:00
|
|
|
$CFLAGS
|
|
|
|
|
2017-03-21 18:07:40 +00:00
|
|
|
# library paths
|
2014-12-22 04:45:19 +00:00
|
|
|
-I"lib/include"
|
|
|
|
-I"/usr/include/libxml2"
|
2015-01-20 04:21:10 +00:00
|
|
|
-I"/usr/local/include/libxml2"
|
2017-03-21 18:07:40 +00:00
|
|
|
# mpw paths
|
|
|
|
-I"core" -I"cli"
|
2014-12-22 04:45:19 +00:00
|
|
|
)
|
2015-02-09 20:51:12 +00:00
|
|
|
local LDFLAGS=(
|
2017-04-08 18:25:54 +00:00
|
|
|
$LDFLAGS
|
|
|
|
|
2014-12-22 04:45:19 +00:00
|
|
|
# link libraries
|
|
|
|
-l"crypto" -l"xml2"
|
|
|
|
)
|
|
|
|
|
2017-03-21 18:07:40 +00:00
|
|
|
cc "${CFLAGS[@]}" "$@" -c core/mpw-algorithm.c -o core/mpw-algorithm.o
|
|
|
|
cc "${CFLAGS[@]}" "$@" -c core/mpw-types.c -o core/mpw-types.o
|
|
|
|
cc "${CFLAGS[@]}" "$@" -c core/mpw-util.c -o core/mpw-util.o
|
|
|
|
cc "${CFLAGS[@]}" "$@" -c cli/mpw-tests-util.c -o cli/mpw-tests-util.o
|
|
|
|
cc "${CFLAGS[@]}" "$@" "core/mpw-algorithm.o" "core/mpw-types.o" "core/mpw-util.o" \
|
|
|
|
"${LDFLAGS[@]}" "cli/mpw-tests-util.o" "cli/mpw-tests.c" -o "mpw-tests"
|
2014-12-22 04:45:19 +00:00
|
|
|
echo "done! Now use ./mpw-tests"
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-15 20:26:09 +00:00
|
|
|
### TARGETS
|
2014-10-15 12:44:41 +00:00
|
|
|
|
2014-11-18 12:32:17 +00:00
|
|
|
haslib() {
|
2014-11-21 06:30:47 +00:00
|
|
|
! LC_ALL=C cc -l"$1" 2>&1 | grep -q 'library not found'
|
2014-11-18 12:32:17 +00:00
|
|
|
}
|
2014-10-15 18:00:44 +00:00
|
|
|
cc() {
|
2014-10-15 19:32:10 +00:00
|
|
|
if hash llvm-gcc 2>/dev/null; then
|
2014-10-15 20:03:46 +00:00
|
|
|
llvm-gcc "$@"
|
2014-10-18 19:38:51 +00:00
|
|
|
elif hash gcc 2>/dev/null; then
|
2014-10-15 19:32:10 +00:00
|
|
|
gcc -std=gnu99 "$@"
|
2014-10-18 22:22:29 +00:00
|
|
|
elif hash clang 2>/dev/null; then
|
|
|
|
clang "$@"
|
2014-10-18 19:38:51 +00:00
|
|
|
else
|
|
|
|
echo >&2 "Need a compiler. Please install GCC or LLVM."
|
|
|
|
exit 1
|
2014-10-15 18:00:44 +00:00
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
2014-10-19 00:56:28 +00:00
|
|
|
echo "Will build targets: ${targets[*]}..."
|
2014-10-15 20:26:09 +00:00
|
|
|
for target in "${targets[@]}"; do
|
|
|
|
"$target" "$@"
|
|
|
|
done
|