#!/bin/sh
PYTHON=/usr/bin/python2.5
prefix=/usr
exec_prefix=${prefix}
sysconfdir=${prefix}/etc
srcdir=/private/tmp/submission/49729/distcc/distcc_dist
include_server=''
CheckUsage() {
if [ "$1" = "" -o "$1" = '-h' -o "$1" = '--help' ]; then
cat <<'EOF'
Usage:
pump COMMAND [ARG...]
or
pump --startup
pump --shutdown
Description:
Pump, also known as distcc-pump, accelerates remote compilation with
distcc by also distributing preprocessing to the servers.
The simplest usage is the form "pump COMMAND [ARG...]".
This will start an include server for distcc-pump; set some environment
variables; change PATH to use the distcc-pump "distcc" client; execute
COMMAND with the specified ARG(s); and then shutdown the include server.
The COMMAND is typically a parallel build command, such as
"make -j80", that will do many concurrent invocations of distcc.
An alternative way of invoking pump is to explicitly invoke "pump --startup"
to start the include server and "pump --shutdown" to stop the include server.
The "pump --startup" command will start up the include server, and will print
out some environment variable settings. These environment variables are used
to communicate between the distcc-pump "distcc" client and the include
server, and to communicate between "pump --startup" and "pump --shutdown".
The caller of "pump --startup" is responsible for setting those environment
variables before invoking "distcc" or "pump --shutdown". For example:
eval `pump --startup`
make -j80
pump --shutdown
Note that distcc-pump assumes that sources files will not be modified during
the lifetime of the include server, so modifying source files during a build
may cause inconsistent results.
Environment variables (all optional):
DISTCC_LOCATION Either the distcc 'bin' install directory (when the
pump script in the installation executes) or the build
directory (when the pump script is run during
development).
This location is normally inferred from the dirname
of argv[0]. It is resolved with respect to links.
If this location is the bin directory inside an
installation, then Python executables and distcc
itself will be retrieved from the parent directory of
the location.
If this location is the build directory, then Python
sources are retrived from the source directory.
DISTCC_POTENTIAL_HOSTS The distcc servers that will be queried by lsdistcc
in order to produce a value for DISTCC_HOSTS.
This value may be unset or null. In such
cases, use DISTCC_HOSTS.
DISTCC_HOSTS This variable is passed through to distcc but only if
DISTCC_POTENTIAL_HOSTS is not set.
LSDISTCC_ARGS Extra arguments to lsdistcc.
INCLUDE_SERVER_ARGS Extra arguments to the include server.
PYTHONOPTIMIZE If set to "", then Python optimization is disabled.
Example:
pump make
EOF
exit 0
fi
}
GetScriptDir() {
if [ -h "$0" ]; then
dir=`dirname "$0"`
link=`readlink "$0"`
linkdir=`dirname "$link"`
case $linkdir in
/*) echo "$linkdir" ;;
*) echo "$dir/$linkdir" ;;
esac
else
dirname "$0"
fi
}
max_discrepancies_before_demotion=1
if [ -z "$DISTCC_LOCATION" ]; then
DISTCC_LOCATION=`GetScriptDir "$0"`
fi
program_name="$0"
socket_dir='' tmp_pid_file='' available_hosts_file='' socket='' include_server_stdout='' include_server_stderr='' include_server_pid=''
include_server_relative='' distcc_location='' DISTCC='distcc' verbose=1 redirect_io=0
MakeTmpFile() {
if mktemp $2 /tmp/$1.XXXXXX; then
: else
echo "$program_name: Could not make temp \"$1\"" 1>&2
exit 1
fi
}
Initialize() {
include_server_relative="../$PYTHON_RELATIVE_LIB/include_server"
distcc_location="$DISTCC_LOCATION"
if [ ! -x "$distcc_location/$DISTCC" ]; then
echo "$0: error: can't find distcc (looked in $distcc_location)" 1>&2
exit 1
fi
}
PrintIncludeServerStatusMessage() {
include_server_status=$1
if [ "$verbose" = 1 ]; then
if [ "$include_server_status" = 0 ]; then
echo '__________Started distcc-pump include server'
else
echo '__________Could not start distcc-pump include server' 1>&2
fi
fi
}
Announce() {
echo "__________Using distcc-pump from $DISTCC_LOCATION"
}
StartIncludeServer() {
if [ -n "$include_server" ]; then
pythonpath=`dirname "$include_server"`
else
distcc_srcdir=`cd "$DISTCC_LOCATION"; cd "$srcdir"; pwd`
include_server="$distcc_srcdir/include_server/include_server.py"
so_dir=`"$distcc_srcdir/find_c_extension.sh" "$DISTCC_LOCATION"`
pythonpath="$so_dir"
fi
socket_dir=`MakeTmpFile "distcc-pump" -d`
socket="$socket_dir/socket"
include_server_stdout="$socket_dir/stdout"
include_server_stderr="$socket_dir/stderr"
tmp_pid_file=`MakeTmpFile "distcc-pump-pid"`
(
case $redirect_io in
1) exec < /dev/null \
> $include_server_stdout \
2> $include_server_stderr
;;
*)
rm -f $include_server_stdout $include_server_stderr
;;
esac
if [ -z "$PYTHONOPTIMIZE" ]; then PYTHONOPTIMIZE=1; fi
eval \
"PYTHONOPTIMIZE='$PYTHONOPTIMIZE' " \
"PYTHONPATH='$pythonpath::$PYTHONPATH' " \
"'$PYTHON'" \
"'$include_server'" \
--port "'$socket'" \
--pid_file "'$tmp_pid_file'" \
-d1 \
$INCLUDE_SERVER_ARGS
)
if [ -x /bin/test ]; then
TEST=/bin/test
elif [ -x /usr/bin/test ]; then
TEST=/usr/bin/test
else
TEST=test
fi
if $TEST ! -S "$socket"; then
echo "__________Expected a socket at '$socket'" 1>&2
PrintIncludeServerStatusMessage 1
return 1
fi
include_server_pid=`cat $tmp_pid_file`
rm "$tmp_pid_file"
if echo "$include_server_pid" | grep '^[0-9][0-9]*$' >/dev/null; then
INCLUDE_SERVER_PORT="$socket"
export INCLUDE_SERVER_PORT
else
include_server_pid=''
PrintIncludeServerStatusMessage 1
return 1
fi
}
ReportDiscrepancies() {
num_discrepancies=`(cat $socket_dir/discrepancy_counter 2>/dev/null | wc -c \
|| echo 0)`
if [ $num_discrepancies -ge $max_discrepancies_before_demotion ]; then
echo -n '__________Warning: ' 1>&2
echo -n "$num_discrepancies " 1>&2
echo -n 'pump-mode compilation(s) failed on server, ' 1>&2
echo 'but succeeded locally.' 1>&2
echo -n '__________Distcc-pump was demoted to plain mode.' 1>&2
echo -n ' See the Distcc Discrepancy Symptoms section in the ' 1>&2
echo 'include_server(1) man page.' 1>&2
fi
}
ShutDown() {
ReportDiscrepancies
if [ -n "$include_server_pid" ] && \
ps -p "$include_server_pid" > /dev/null; then
echo '__________Shutting down distcc-pump include server'
kill $include_server_pid
while kill -0 $include_server_pid; do sleep 0.01; done >/dev/null 2>&1
fi
if [ -f "$include_server_stdout" ]; then
cat "$include_server_stdout"
fi
if [ -f "$include_server_stderr" ]; then
cat "$include_server_stderr" >&2
fi
if [ -n "$socket_dir" ]; then
rm -rf "$socket_dir"
fi
if [ -n "$tmp_pid_file" ]; then
rm -f "$tmp_pid_file"
fi
if [ -n "$available_hosts_file" ]; then
rm -f "$available_hosts_file"
fi
}
AvailableHosts() {
available_hosts="$1"
lsdistcc="$DISTCC_LOCATION/lsdistcc"
if [ ! -x "$lsdistcc" ]; then
echo "$0: error: can't find lsdistcc (looked in $DISTCC_LOCATION)" 1>&2
exit 1
fi
"$lsdistcc" -c150 $LSDISTCC_ARGS $DISTCC_POTENTIAL_HOSTS > "$available_hosts"
}
ExportDISTCC_HOSTS() {
include_server_status="$1"
opts=''
if [ "$include_server_status" = 0 ]; then
opts=",cpp,lzo"
else
if [ "$?" = 1 ]; then
echo "__________Warning: distcc-pump include server failed;" \
"running unpumped" 1>&2
fi
opts=",lzo"
fi
export DISTCC_HOSTS="--randomize `sed s/'$'/$opts/ $available_hosts_file`"
if [ "$verbose" = 1 ]; then
echo "__________Found" \
"`wc -l < $available_hosts_file` available distcc servers"
fi
}
StartIncludeServerAndDetermineHosts() {
include_server_status=1 if [ -n "$DISTCC_POTENTIAL_HOSTS" ]; then
available_hosts_file=`MakeTmpFile "distcc-pump-hosts"`
AvailableHosts "$available_hosts_file" &
StartIncludeServer && include_server_status=0
wait
ExportDISTCC_HOSTS "$include_server_status"
rm -f "$available_hosts_file"
else
if [ -z "$DISTCC_HOSTS" ] &&
[ -z "$DISTCC_DIR" -o ! -f "$DISTCC_DIR/hosts" ] &&
[ -z "$HOME" -o ! -f "$HOME/.distcc/hosts" ] &&
[ ! -f "$sysconfdir/distcc/hosts" ]
then
echo "$program_name:" \
"expected environment variables \"DISTCC_HOSTS\" or" \
"\"DISTCC_POTENTIAL_HOSTS\" to be set, or to find a" \
"distcc hosts file in \"\$DISTCC_DIR/hosts\"," \
"\"\$HOME/.distcc/hosts\", or \"$sysconfdir/distcc/hosts\"." \
1>&2
exit 1
else
hosts=`$distcc_location/distcc --show-hosts`
num_hosts=`echo "$hosts" | wc -l`
num_pump_hosts=`echo "$hosts" | grep ',cpp' | wc -l`
if [ $num_hosts -eq 0 ]; then
echo "$program_name: error: distcc hosts list is empty!" 1>&2
exit 1
elif [ $num_pump_hosts -eq 0 ]; then
echo "$program_name: error: pump mode requested, but distcc" \
"hosts list does not contain any hosts with ',cpp' option" 1>&2
exit 1
else
if [ "$verbose" = 1 ]; then
server_word="servers"
if [ $num_hosts = 1 ]; then
server_word="server"
fi
if [ $num_hosts -eq $num_pump_hosts ]; then
echo "__________Using $num_hosts distcc $server_word in pump mode"
else
echo "__________Using $num_hosts distcc $server_word, of which" \
"only $num_pump_hosts support(s) pump mode"
fi
fi
fi
fi
StartIncludeServer && include_server_status=0
fi
return "$include_server_status"
}
DumpEnvironmentVariables() {
echo export INCLUDE_SERVER_PID=\'$include_server_pid\'
echo export INCLUDE_SERVER_DIR=\'$socket_dir\'
echo export INCLUDE_SERVER_PORT=\'$INCLUDE_SERVER_PORT\'
if [ -n "$DISTCC_HOSTS" ]; then
echo export DISTCC_HOSTS=\'$DISTCC_HOSTS\'
fi
echo export PATH=\'$distcc_location:$PATH\'
}
Main() {
CheckUsage "$@"
Initialize
case "$*" in
--startup)
verbose=0
redirect_io=1
trap 'ShutDown' EXIT StartIncludeServerAndDetermineHosts
include_server_status=$?
trap '' EXIT
if [ "$include_server_status" = 0 ]; then
DumpEnvironmentVariables
exit 0
else
exit 1
fi
;;
--shutdown)
include_server_pid="$INCLUDE_SERVER_PID"
socket_dir="$INCLUDE_SERVER_DIR"
include_server_stdout="$socket_dir/stdout"
include_server_stderr="$socket_dir/stderr"
ShutDown
exit 0
;;
*)
trap 'ShutDown' EXIT
Announce
StartIncludeServerAndDetermineHosts || exit 1
PATH="$distcc_location:$PATH" \
"$@"
;;
esac
}
Main "$@"