2
0
MasterPassword/platform-independent/cli-c/build
2017-07-15 21:13:49 -04:00

365 lines
9.6 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# TROUBLESHOOTING
# - If you see 'undefined reference to `AES_encrypt'',
# make sure you have openssl installed.
# If libcrypto.a is in a non-standard directory, try ./build -L[your-lib-dir]
# - 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.
# - Take a look at the "Optional features" section. Some features have dependencies,
# either make sure you have them or disable those features.
# eg. mpw_color=0 ./build
#
# BUGS
# masterpassword@lyndir.com
#
# AUTHOR
# Maarten Billemont
#
cd "${BASH_SOURCE%/*}"
shopt -s extglob
set -e
### 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, requires libsodium or openssl-dev.
#mpw-bench # C CLI Master Password benchmark utility.
#mpw-tests # C Master Password algorithm test suite, requires libxml2.
)
fi
# Optional features.
mpw_color=${mpw_color:-1} # Colorized Identicon, requires libncurses-dev.
mpw_json=${mpw_json:-1} # Support for JSON-based user configuration format.
mpw_sodium=${mpw_sodium:-1} # Use libsodium if available instead of cperciva's libscrypt.
# Default build flags.
export CFLAGS="-O3 $CFLAGS"
export LDFLAGS="$LDFLAGS"
# 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
### DEPENDENCIES
digest() {
openssl sha -sha256 -binary < "$1" | od -t x1 -An -v | tr -d '[:space:]'
}
fetch() {
if hash wget 2>/dev/null; then
wget -O "${1##*/}" "$1"
elif hash curl 2>/dev/null; then
curl "$1" > "${1##*/}"
fi
}
unpack() {
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'
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
files=( * )
if [[ -d $files ]] && (( ${#files[@]} == 1 )); then
mv "$files"/* .
rmdir "$files"
fi
}
fetchSource() (
local name=${PWD##*/}
source .source
if [[ -e .unpacked ]]; then
true
elif [[ $pkg && -e "${pkg##*/}" ]]; then
[[ -e src ]] || {
echo
echo "Unpacking: $name, using package..."
( mkdir src && cd src && unpack "../${pkg##*/}" "$pkg_sha256" )
touch .unpacked
}
elif [[ $git ]] && hash git 2>/dev/null; then
[[ -e .git ]] || {
echo
echo "Fetching: $name, using git..."
git clone "$git" src
touch .unpacked
}
elif [[ $svn ]] && hash git 2>/dev/null && [[ -x "$(git --exec-path)/git-svn" ]]; then
[[ -e .git ]] || {
echo
echo "Fetching: $name, using git-svn..."
git svn clone --prefix=origin/ --stdlayout "$svn" src
touch .unpacked
}
elif [[ $svn ]] && hash svn 2>/dev/null; then
[[ -e .svn ]] || {
echo
echo "Fetching: $name, using svn..."
svn checkout "$svn/trunk" src
touch .unpacked
}
elif [[ $pkg ]]; then
[[ -e src ]] || {
echo
echo "Fetching: $name, using package..."
fetch "$pkg"
( mkdir src && cd src && unpack "../${pkg##*/}" "$pkg_sha256" )
touch .unpacked
}
else
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"
echo >&2 "error: into: $PWD/src"
exit 1
fi
if [[ ! -e .patched ]] && (( ${#patches[@]} )); then
pushd src
for patch in "${patches[@]}"; do
echo
echo "Patching: $name, for $patch..."
patch -p0 < "../$patch.patch"
done
popd
touch .patched
fi
)
depend() {
local name=$1
echo
echo "Checking dependency: $name..."
[[ -e "lib/include/$name" ]] && return
pushd "lib/$name"
fetchSource
pushd "src"
echo
echo "Configuring dependency: $name..."
if [[ -e configure.ac ]]; then
if [[ ! -e configure ]]; then
# create configure using autotools.
if ! hash aclocal || ! hash automake; then
echo >&2 "Need autotools to build $name. Please install automake and autoconf."
exit 1
fi
aclocal
autoheader
autoconf
mkdir -p config.aux
automake --add-missing
fi
fi
if [[ -e configure ]]; then
./configure
fi
echo
echo "Building dependency: $name..."
if [[ -e Makefile ]]; then
if ! hash make; then
echo >&2 "Need make to build $name. Please install GNU make."
exit 1
fi
make
install -d "../../include/$name/"
find . -name '*.h' -exec install -m 444 {} "../../include/$name/" \;
else
echo >&2 "error: Don't know how to build: $name"
exit 1
fi
popd
popd
}
depend_scrypt() {
if (( mpw_sodium )) && haslib sodium; then
if [[ $CFLAGS != *HAS_SODIUM=1* ]]; then
CFLAGS+=" -DHAS_SODIUM=1"
LDFLAGS+=" -lsodium"
fi
return
fi
depend scrypt
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
}
### MPW
mpw() {
depend_scrypt
echo
echo "Building target: $target..."
local CFLAGS=(
$CFLAGS
# library paths
-I"lib/include"
# mpw paths
-I"core" -I"cli"
)
local LDFLAGS=(
$LDFLAGS
# link libraries
-l"crypto"
)
# optional features
(( mpw_color )) && CFLAGS+=( -DMPW_COLOR ) LDFLAGS+=( -l"curses" )
(( mpw_json )) && CFLAGS+=( -DMPW_JSON ) LDFLAGS+=( -l"json-c" )
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 core/mpw-marshall.c -o core/mpw-marshall.o
cc "${CFLAGS[@]}" "$@" "core/mpw-algorithm.o" "core/mpw-types.o" "core/mpw-util.o" "core/mpw-marshall.o" \
"${LDFLAGS[@]}" "cli/mpw-cli.c" -o "mpw"
echo "done! Now run ./install or use ./mpw"
}
### MPW-BENCH
mpw-bench() {
depend_scrypt
depend bcrypt
echo
echo "Building target: $target..."
local CFLAGS=(
$CFLAGS
# library paths
-I"lib/include"
# mpw paths
-I"core" -I"cli"
)
local LDFLAGS=(
$LDFLAGS
# bcrypt
"lib/bcrypt/src/crypt_blowfish.o"
"lib/bcrypt/src/crypt_gensalt.o"
"lib/bcrypt/src/wrapper.o"
"lib/bcrypt/src/x86.o"
# library paths
-L"lib/bcrypt/src"
# link libraries
-l"crypto"
)
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"
echo "done! Now use ./mpw-bench"
}
### MPW-TESTS
mpw-tests() {
depend_scrypt
echo
echo "Building target: $target..."
local CFLAGS=(
$CFLAGS
# library paths
-I"lib/include"
-I"/usr/include/libxml2"
-I"/usr/local/include/libxml2"
# mpw paths
-I"core" -I"cli"
)
local LDFLAGS=(
$LDFLAGS
# link libraries
-l"crypto" -l"xml2"
)
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"
echo "done! Now use ./mpw-tests"
}
### TARGETS
haslib() {
cc -l"$1" -x c -o /dev/null - <<< 'int main() { return 0; }'
}
cc() {
if hash llvm-gcc 2>/dev/null; then
llvm-gcc "$@"
elif hash gcc 2>/dev/null; then
gcc -std=gnu99 "$@"
elif hash clang 2>/dev/null; then
clang "$@"
else
echo >&2 "Need a compiler. Please install GCC or LLVM."
exit 1
fi
}
echo "Will build targets: ${targets[*]}..."
for target in "${targets[@]}"; do
"$target" "$@"
done