cargo/configure
Alex Crichton 230dbf6a59 Use libgit2 for driving git instead of the CLI
In general relying on external programs is dicey and tricky as they're very
different across systems in both how they're used as well as what versions
you'll find. Instead of binding to the least common denominator of CLI, we can
code against an exact version of libgit2.

This introduces a build-time dependency on cmake which libgit2 requires to build
itself, which is unfortunate, but thankfully it's only a build time dep. The
build process for libgit2 also automatically detects as many system libraries as
possible to use (if available), falling back to bundled versions if not
available. I have currently not figured how to control this, so the link-config
package is used to build libgit2 which requires that pkg-config be installed to
build cargo as well.

Closes #138
2014-08-16 15:54:07 -07:00

384 lines
8.1 KiB
Bash
Executable file

#!/bin/sh
msg() {
echo "configure: $1"
}
step_msg() {
msg
msg "$1"
msg
}
warn() {
echo "configure: WARNING: $1"
}
err() {
echo "configure: error: $1"
exit 1
}
need_ok() {
if [ $? -ne 0 ]
then
err "$1"
fi
}
need_cmd() {
if command -v $1 >/dev/null 2>&1
then msg "found $1"
else err "need $1"
fi
}
make_dir() {
if [ ! -d $1 ]
then
msg "mkdir -p $1"
mkdir -p $1
fi
}
copy_if_changed() {
if cmp -s $1 $2
then
msg "leaving $2 unchanged"
else
msg "cp $1 $2"
cp -f $1 $2
chmod u-w $2 # make copied artifact read-only
fi
}
move_if_changed() {
if cmp -s $1 $2
then
msg "leaving $2 unchanged"
else
msg "mv $1 $2"
mv -f $1 $2
chmod u-w $2 # make moved artifact read-only
fi
}
putvar() {
local T
eval T=\$$1
eval TLEN=\${#$1}
if [ $TLEN -gt 35 ]
then
printf "configure: %-20s := %.35s ...\n" $1 "$T"
else
printf "configure: %-20s := %s %s\n" $1 "$T" "$2"
fi
printf "%-20s := %s\n" $1 "$T" >>config.tmp
}
probe() {
local V=$1
shift
local P
local T
for P
do
T=$(command -v $P 2>&1)
if [ $? -eq 0 ]
then
VER0=$($P --version 2>/dev/null | head -1 \
| sed -e 's/[^0-9]*\([vV]\?[0-9.]\+[^ ]*\).*/\1/' )
if [ $? -eq 0 -a "x${VER0}" != "x" ]
then
VER="($VER0)"
else
VER=""
fi
break
else
VER=""
T=""
fi
done
eval $V=\$T
putvar $V "$VER"
}
probe_need() {
local V=$1
probe $*
eval VV=\$$V
if [ -z "$VV" ]
then
err "needed, but unable to find any of: $*"
fi
}
validate_opt () {
for arg in $CFG_CONFIGURE_ARGS
do
isArgValid=0
for option in $BOOL_OPTIONS
do
if test --disable-$option = $arg
then
isArgValid=1
fi
if test --enable-$option = $arg
then
isArgValid=1
fi
done
for option in $VAL_OPTIONS
do
if echo "$arg" | grep -q -- "--$option="
then
isArgValid=1
fi
done
if [ "$arg" = "--help" ]
then
echo
echo "No more help available for Configure options,"
echo "check the Wiki or join our IRC channel"
break
else
if test $isArgValid -eq 0
then
err "Option '$arg' is not recognized"
fi
fi
done
}
valopt() {
VAL_OPTIONS="$VAL_OPTIONS $1"
local OP=$1
local DEFAULT=$2
shift
shift
local DOC="$*"
if [ $HELP -eq 0 ]
then
local UOP=$(echo $OP | tr '[:lower:]' '[:upper:]' | tr '\-' '\_')
local V="CFG_${UOP}"
eval $V="$DEFAULT"
for arg in $CFG_CONFIGURE_ARGS
do
if echo "$arg" | grep -q -- "--$OP="
then
val=$(echo "$arg" | cut -f2 -d=)
eval $V=$val
fi
done
putvar $V
else
if [ -z "$DEFAULT" ]
then
DEFAULT="<none>"
fi
OP="${OP}=[${DEFAULT}]"
printf " --%-30s %s\n" "$OP" "$DOC"
fi
}
opt() {
BOOL_OPTIONS="$BOOL_OPTIONS $1"
local OP=$1
local DEFAULT=$2
shift
shift
local DOC="$*"
local FLAG=""
if [ $DEFAULT -eq 0 ]
then
FLAG="enable"
else
FLAG="disable"
DOC="don't $DOC"
fi
if [ $HELP -eq 0 ]
then
for arg in $CFG_CONFIGURE_ARGS
do
if [ "$arg" = "--${FLAG}-${OP}" ]
then
OP=$(echo $OP | tr 'a-z-' 'A-Z_')
FLAG=$(echo $FLAG | tr 'a-z' 'A-Z')
local V="CFG_${FLAG}_${OP}"
eval $V=1
putvar $V
fi
done
else
if [ ! -z "$META" ]
then
OP="$OP=<$META>"
fi
printf " --%-30s %s\n" "$FLAG-$OP" "$DOC"
fi
}
envopt() {
local NAME=$1
local V="CFG_${NAME}"
eval VV=\$$V
# If configure didn't set a value already, then check environment.
#
# (It is recommended that the configure script always check the
# environment before setting any values to envopt variables; see
# e.g. how CFG_CC is handled, where it first checks `-z "$CC"`,
# and issues msg if it ends up employing that provided value.)
if [ -z "$VV" ]
then
eval $V=\$$NAME
eval VV=\$$V
fi
# If script or environment provided a value, save it.
if [ ! -z "$VV" ]
then
putvar $V
fi
}
msg "looking for configure programs"
need_cmd cmp
need_cmd mkdir
need_cmd printf
need_cmd cut
need_cmd head
need_cmd grep
need_cmd xargs
need_cmd cp
need_cmd find
need_cmd uname
need_cmd date
need_cmd tr
need_cmd sed
need_cmd file
need_cmd cmake
need_cmd pkg-config
CFG_SRC_DIR="$(cd $(dirname $0) && pwd)/"
CFG_BUILD_DIR="$(pwd)/"
CFG_SELF="$0"
CFG_CONFIGURE_ARGS="$@"
OPTIONS=""
HELP=0
if [ "$1" = "--help" ]
then
HELP=1
shift
echo
echo "Usage: $CFG_SELF [options]"
echo
echo "Options:"
echo
else
msg "recreating config.tmp"
echo '' >config.tmp
step_msg "processing $CFG_SELF args"
fi
BOOL_OPTIONS=""
VAL_OPTIONS=""
opt debug 1 "build with extra debug fun"
opt optimize 0 "build with optimizations"
opt nightly 0 "build nightly packages"
opt verify-install 1 "verify installed binaries work"
opt cross-tests 1 "run cross-compilation tests"
valopt prefix "/usr/local" "set installation prefix"
valopt local-rust-root "" "set prefix for local rust binary"
if [ $HELP -eq 0 ]; then
if [ ! -z "${CFG_LOCAL_RUST_ROOT}" ]; then
export LD_LIBRARY_PATH="${CFG_LOCAL_RUST_ROOT}/lib:$LD_LIBRARY_PATH"
export DYLD_LIBRARY_PATH="${CFG_LOCAL_RUST_ROOT}/lib:$DYLD_LIBRARY_PATH"
LRV=`${CFG_LOCAL_RUST_ROOT}/bin/rustc --version`
if [ $? -eq 0 ]; then
step_msg "using rustc at: ${CFG_LOCAL_RUST_ROOT} with version: $LRV"
else
err "failed to run rustc at: ${CFG_LOCAL_RUST_ROOT}"
fi
CFG_RUSTC="${CFG_LOCAL_RUST_ROOT}/bin/rustc"
else
probe_need CFG_RUSTC rustc
fi
DEFAULT_BUILD=$("${CFG_RUSTC}" --version verbose | grep 'host: ' | sed 's/host: //')
fi
valopt build "${DEFAULT_BUILD}" "GNUs ./configure syntax LLVM build triple"
valopt host "${CFG_BUILD}" "GNUs ./configure syntax LLVM host triples"
valopt target "${CFG_HOST}" "GNUs ./configure syntax LLVM target triples"
valopt localstatedir "/var/lib" "local state directory"
valopt sysconfdir "/etc" "install system configuration files"
valopt datadir "${CFG_PREFIX}/share" "install data"
valopt infodir "${CFG_PREFIX}/share/info" "install additional info"
valopt mandir "${CFG_PREFIX}/share/man" "install man pages in PATH"
valopt libdir "${CFG_PREFIX}/lib" "install libraries"
if [ $HELP -eq 1 ]
then
echo
exit 0
fi
# Validate Options
step_msg "validating $CFG_SELF args"
validate_opt
step_msg "looking for build programs"
probe_need CFG_CURLORWGET curl wget
probe_need CFG_PYTHON python
# a little post-processing of various config values
CFG_PREFIX=${CFG_PREFIX%/}
CFG_MANDIR=${CFG_MANDIR%/}
CFG_HOST="$(echo $CFG_HOST | tr ',' ' ')"
CFG_TARGET="$(echo $CFG_TARGET | tr ',' ' ')"
# copy host-triples to target-triples so that hosts are a subset of targets
V_TEMP=""
for i in $CFG_HOST $CFG_TARGET;
do
echo "$V_TEMP" | grep -qF $i || V_TEMP="$V_TEMP${V_TEMP:+ }$i"
done
CFG_TARGET=$V_TEMP
if [ "$CFG_SRC_DIR" != "$CFG_BUILD_DIR" ]; then
err "cargo does not currently support an out-of-tree build dir"
fi
step_msg "writing configuration"
putvar CFG_SRC_DIR
putvar CFG_BUILD_DIR
putvar CFG_CONFIGURE_ARGS
putvar CFG_PREFIX
putvar CFG_BUILD
putvar CFG_HOST
putvar CFG_TARGET
putvar CFG_LIBDIR
putvar CFG_MANDIR
putvar CFG_RUSTC
msg
copy_if_changed ${CFG_SRC_DIR}Makefile.in ./Makefile
move_if_changed config.tmp config.mk
rm -f config.tmp
touch config.stamp
step_msg "complete"
msg