[distcc] toggle-wrapper

Wayne Davison wayned at users.sourceforge.net
Wed Feb 12 07:54:47 GMT 2003

On Tue, Feb 11, 2003 at 10:42:29PM -0700, Eric Andresen wrote:
> They are seperate entities. distcc-1.1-r8 is "toggled" by adding
> /usr/lib/distcc/bin to PATH, and/or "distcc" to FEATURES (in make.conf).

We should also mention that you need to set DISTCC_HOSTS directly in
some way (i.e. there is no support for reading the hosts from a file
like there was in the toggle-wrapper setup).  I had been setting
DISTCC_HOSTS in my make.conf file (right next to the MAKEOPTS setting)
but it changes so often that I've just switched over to using my new
"distcc_probe" perl script to set these values (and the PATH) based on
a config file.  It works as follows:

You define some HOST[:PORT]/COUNT values in a config file.  The COUNT is
how much to boost the -j (parallel threads) setting if the associated
host is found to be available.  The script attempts to connect to every
mentioned host on the specified port (defaulting to 3632), and if it
succeeds, it immediately closes the connection and marks that host as
present.  At the end it outputs some export lines with the values it
computed.  This lets me run something like this:

    eval `distcc_probe -v`

And then "make" or "emerge" to my heart's content.  The -v option tells
it to output a summary of what it did on STDERR.  The default config
file it reads is /etc/distcc_hosts, but you can specify one or more
filenames on the command-line to have it read the names from somewhere
else (use "-" for stdin).  The name "localhost" is handled specially --
it is not socket-probed, but it's COUNT does affect the -j value and it
will be listed in the DISTCC_HOSTS setting if there are non-localhost
values in the list.

Note that for gentoo emerging, the PATH is overridden inside the
ebuild.sh script.  To get this to work, I had to tweak the ebuild.sh
script to only add the /usr/lib/distcc/bin dir when DISTCC_HOSTS is not
empty (since I have to have "distcc" in FEATURES all the time.  I also
needed to ensure that the setting of MAKEOPTS in make.conf is commented
out so that full control is given to the environment.  I suppose I could
change ebuild.sh to actually run the distcc_probe script, but I figure
that's too much dynamism for what I need.

I've attached the distcc_hosts script to this message.  Here's my
tweaked version of the distcc section of ebuild.sh:

	if has distcc ${FEATURES} &>/dev/null; then
		#We can enable distributed compile support
		if [ -d /usr/lib/distcc/bin  ]; then
			if [ ! -z "${DISTCC_HOSTS}" ]; then
				export PATH="/usr/lib/distcc/bin:${PATH}"
			export DISTCC_HOSTS
		elif which distcc &>/dev/null; then
			export CC="distcc $CC"
			export CXX="distcc $CXX"
		[ ! -z "${DISTCC_LOG}" ] && addwrite "$(dirname ${DISTCC_LOG})"

-------------- next part --------------

use strict;
use Getopt::Long;
use Socket;

my $CONF_FILE = '/etc/distcc_hosts';
my $DISTCC_DIR = '/usr/lib/distcc/bin';

my $path = $ENV{'PATH'};
$path =~ s#(^|:)$DISTCC_DIR(:|$)# "$1$2" eq '::'? ':' : '' #e;

my($help_opt, $verbosity);

&usage if !&GetOptions(
    'help|h' => \$help_opt,
    'verbose|v+' => \$verbosity,
) || $help_opt;

@ARGV = ( $CONF_FILE ) unless @ARGV;

my @hosts;
my $j = 0;
my $remote_cnt = 0;

while (<>) {
    foreach my $spec (split(' ')) {
	if ($spec =~ m#^([^/]+)/(\d+)$#) {
	    my $host = $1;
	    my $cnt = $2;
	    if ($host eq 'localhost' || &probe_host($host)) {
		push(@hosts, $host);
		$j += $cnt;
		$remote_cnt++ if $host ne 'localhost';
	else {
	    warn "Invalid HOST[:PORT]/CNT specified: `$spec'\n";

if ($remote_cnt) {
    $path = "$DISTCC_DIR:$path";
else {
    @hosts = ( );
$j = 1 if !$j;

print <<EOT;
export MAKEOPTS=-j$j
export DISTCC_HOSTS="@hosts"
export PATH=$path

if ($verbosity) {
    print STDERR "Set -j$j";
    print STDERR ", hosts=`@hosts'" if $remote_cnt;
    print STDERR "\n";


sub probe_host
    my($host) = @_;
    my $port = $host =~ s#:(\d+)$##? $1 : 3632;
    my $iaddr = inet_aton($host);
    if (!defined $iaddr) {
	warn "Undefined host: $host\n";
	return 0;
    my $paddr = sockaddr_in($port, $iaddr);
    my $proto   = getprotobyname('tcp');
    my $S;
    socket($S, PF_INET, SOCK_STREAM, $proto)  || die "socket: $!";
    $SIG{'ALRM'} = sub { };
    if (!connect($S, $paddr)) {
	return 0;
    shutdown($S, 2);

sub usage
    die <<EOT;
Usage: distcc_probe [-v] [HOST_FILE...]

-v (verbose) will output a summary to STDERR of what it sent to STDOUT

If no HOST_FILE(s) are specified, $CONF_FILE will be read instead.

More information about the distcc mailing list