r106 - trunk/code/unix

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Sun Sep 25 17:46:55 EDT 2005


Author: tma
Date: 2005-09-25 17:46:55 -0400 (Sun, 25 Sep 2005)
New Revision: 106

Removed:
   trunk/code/unix/pcons-2.3.1
Log:
* Removed stray cons script


Deleted: trunk/code/unix/pcons-2.3.1
===================================================================
--- trunk/code/unix/pcons-2.3.1	2005-09-25 21:46:00 UTC (rev 105)
+++ trunk/code/unix/pcons-2.3.1	2005-09-25 21:46:55 UTC (rev 106)
@@ -1,7911 +0,0 @@
-#!/usr/bin/env perl
-
-#
-# Revision history:
-# -----------------
-# July 2001, Thomas Gleerup <tgl at oticon.dk>
-#   1) pcons-1.6 (John Erickson, August 1999) merged into cons-2.3.0.
-#   2) Added automatic insertion of && for multi-line commands.
-#
-# September 2001, Thomas Gleerup <tgl at oticon.dk>
-#   1) Updated with Kevin Nolish's multi-line improvement.
-#   2) Improved this so that single [perl] commands can still be used.
-#
-
-# NOTE:  Cons intentionally does not use the "perl -w" option or
-# "use strict."  Because Cons "configuration files" are actually
-# Perl scripts, enabling those restrictions here would force them
-# on every user's config files, wanted or not.  Would users write
-# "better" Construct and Conscript files if we forced "use strict"
-# on them?  Probably.  But we want people to use Cons to get work
-# done, not force everyone to become a Perl guru to use it, so we
-# don't insist.
-#
-# That said, Cons' code is both "perl -w" and "use strict" clean.
-# Regression tests keep the code honest by checking for warnings
-# and "use strict" failures.
-
-use vars qw( $CVS_id $CVS_ver $ver_num $ver_rev $version );
-
-# I hate those CVS tags
-$CVS_id  = 'pcons-2.3.1';
-$CVS_ver = (split (/\s+/, $CVS_id))[2];
-
-$ver_num = "__VERSION__";
-$ver_rev = "__REVISION__";
-
-#$version = "This is Cons $ver_num$ver_rev ($CVS_id)\n";
-$version = "This is parallel Cons (pcons) $ver_num$ver_rev ($CVS_id)\n";
-
-# Cons: A Software Construction Tool.
-# Copyright (c) 1996-2001 Free Software Foundation, Inc.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; see the file COPYING.  If not, write to
-# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-
-require 5.003;
-
-# See the NOTE above about why Cons doesn't "use strict".
-use integer;
-use Cwd;
-use File::Copy;
-
-use vars qw( $_WIN32 $_a $_exe $_o $_so );
-
-#------------------------------------------------------------------
-# Determine if running on win32 platform - either Windows NT or 95
-#------------------------------------------------------------------
-
-use vars qw( $PATH_SEPARATOR $iswin32 $_WIN32 $usage $indent @targets );
-
-BEGIN
-{
-    use Config;
-
-    # if the version is 5.003, we can check $^O
-    if ($] < 5.003)
-    {
-        eval("require Win32");
-        $_WIN32 = (!$@);
-    }
-    else
-    {
-        $_WIN32 = ($^O eq "MSWin32") ? 1 : 0;
-    }
-
-    # Fetch the PATH separator from Config;
-    # provide our old defaults in case it's not set.
-    $PATH_SEPARATOR = $Config{path_sep};
-    $PATH_SEPARATOR = $_WIN32 ? ';' : ':' if !defined $PATH_SEPARATOR;
-
-    # Fetch file suffixes from Config,
-    # accomodating differences in the Config variables
-    # used by different Perl versions.
-    $_exe = $Config{_exe};
-    $_exe = $Config{exe_ext} if !defined $_exe;
-    $_exe = $_WIN32 ? '.exe' : '' if !defined $_exe;
-    $_o   = $Config{_o};
-    $_o = $Config{obj_ext} if !defined $_o;
-    $_o = $_WIN32 ? '.obj' : '.o' if !defined $_o;
-    $_a  = $Config{_a};
-    $_a  = $Config{lib_ext} if !defined $_a;
-    $_a  = $_WIN32 ? '.lib' : '.a' if !defined $_a;
-    $_so = ".$Config{so}";
-    $_so = $_WIN32 ? '.dll' : '.so' if !defined $_so;
-}
-
-# Flush stdout each time.
-$| = 1;
-
-# Seed random number generator.
-srand(time . $$);    # this works better than time ^ $$ in perlfunc manpage.
-
-$usage = q(
-Usage: cons <arguments> -- <construct-args>
-
-Arguments can be any of the following, in any order:
-
-  <targets>	Build the specified targets. If <target> is a directory
-		recursively build everything within that directory.
-
-  +<pattern>	Limit the cons scripts considered to just those that
-		match <pattern>. Multiple + arguments are accepted.
-
-  <name>=<val>	Sets <name> to value <val> in the ARG hash passed to the
-		top-level Construct file.
-
-  -cc           Show command that would have been executed, when
-		retrieving from cache. No indication that the file
-		has been retrieved is given; this is useful for
-		generating build logs that can be compared with
-		real build logs.
-
-  -cd           Disable all caching. Do not retrieve from cache nor
-		flush to cache.
-
-  -cr           Build dependencies in random order. This is useful when
-		building multiple similar trees with caching enabled.
-
-  -cs           Synchronize existing build targets that are found to be
-		up-to-date with cache. This is useful if caching has
-		been disabled with -cc or just recently enabled with
-		UseCache.
-
-  -d            Enable dependency debugging.
-
-  -f <file>	Use the specified file instead of "Construct" (but first
-		change to containing directory of <file>).
-
-  -h            Show a help message local to the current build if
-		one such is defined,  and exit.
-
-  -k		Keep going as far as possible after errors.
-
-  -o <file>	Read override file <file>.
-
-  -p		Show construction products in specified trees.
-  -pa		Show construction products and associated actions.
-  -pw		Show products and where they are defined.
-
-  -q		Be quiet; multiple -q flags increase quietness level:
-		1: quiet about Installing and Removing targets
-		2: quiet about build commands, up-to-date targets
-
-  -r		Remove construction products associated with <targets>
-
-  -R <repos>	Search for files in <repos>.  Multiple -R <repos>
-		directories are searched in the order specified.
-
-  -S <pkg>	Use package sig::<pkg> to calculate file signatures.
-		Currently supported values are "md5" for MD5
-		signatures (the default) and "md5::debug" for MD5
-		signature debug information.
-
-  -t            Traverse up the directory hierarchy looking for a
-		Construct file, if none exists in the current directory.
-		(Targets will be modified to be relative to the
-		Construct file.)
-
-  -v		Show cons version and continue processing.
-  -V            Show cons version and exit.
-
-  -wf <file>    Write all filenames considered into <file>.
-
-  -x		Show this message and exit.
-
-
-   Please report any suggestions through the cons-discuss at gnu.org mailing
-   list.
-
-   To subscribe, send mail to cons-discuss-request at gnu.org with body
-   'subscribe'.
-
-   If you find a bug, please report it through the bug-cons at gnu.org
-   mailing list.
-
-   Information about CONS can be obtained from the official cons web site
-   http://www.dsmit.com/cons/ or its mirrors (listed there).
-
-   The cons maintainers can be contacted by email at cons-maintainers at gnu.org
-
-   User documentation of cons is contained in cons and can be obtained
-   by doing 'perldoc /path/to/cons'.
-
-);
-my $pcons = 1;
-
-# Simplify program name, if it is a path.
-{
-    my ($vol, $dir, $file) = File::Spec->splitpath(File::Spec->canonpath($0));
-    $0 = $file;
-}
-
-# Default parameters.
-$param::topfile = 'Construct';    # Top-level construction file.
-$param::install = 1;              # Show installations
-$param::build   = 1;              # Build targets
-     ### $param::show = 1;		# Show building of targets.
-$param::sigpro  = 'md5';    # Signature protocol.
-$param::depfile = '';       # Write all deps out to this file
-$param::salt    = '';       # Salt derived file signatures with this.
-$param::sourcesig = ['*' => 'content'];    # Source file signature calculation
-$param::rep_sig_times_ok = 1;    # Repository .consign times are in sync
-                                 #   w/files.
-$param::conscript_chdir  = 0;    # Change dir to Conscript directory
-$param::quiet            = 0;    # should we show the command being executed.
-$param::max_jobs         = 1;    # pcons
-
- at param::defaults = ();
-
-#
-$indent = '';
-
-# Display a command while executing or otherwise. This
-# should be called by command builder action methods.
-sub showcom
-{
-    print($indent . $_[0] . "\n") if ($param::quiet < 2);
-}
-
-# Default environment.
-# This contains only the completely platform-independent information
-# we can figure out.  Platform-specific information (UNIX, Win32)
-# gets added below.
- at param::base = (
-    'SIGNATURE' => ['*' => 'build'],
-    'SUFEXE'  => $_exe,         # '' on UNIX systems
-    'SUFLIB'  => $_a,           # '.a' on UNIX systems
-    'SUFLIBS' => "$_so:$_a",    # '.so:.a' on UNIX
-    'SUFOBJ'  => $_o,           # '.o' on UNIX systems
-    'SUFMAP' => {
-                  '.c'   => 'build::command::cc',
-                  '.s'   => 'build::command::cc',
-                  '.S'   => 'build::command::cc',
-                  '.C'   => 'build::command::cxx',
-                  '.cc'  => 'build::command::cxx',
-                  '.cxx' => 'build::command::cxx',
-                  '.cpp' => 'build::command::cxx',
-                  '.c++' => 'build::command::cxx',
-                  '.C++' => 'build::command::cxx',
-    },
-    'PERL' => $^X,
-    );
-
-# pcons does not allow multi-line commands
-my $ar_command = ($param::max_jobs <= 1)
-  ?    # pcons
-  ['%AR %ARFLAGS %> %<', '%RANLIB %>']
-  :                                          # cons
-  '%AR %ARFLAGS %> %<   &&   %RANLIB %>';    # pcons
-
-%param::rulesets = (
-
-    # Defaults for Win32.
-    # Defined for VC++ 6.0 by Greg Spencer <greg_spencer at acm.org>
-    # Your mileage may vary.
-    'msvc' => [
-                'CC'            => 'cl',
-                'CFLAGS'        => '/nologo',
-                'CCCOM'         => '%CC %CFLAGS %_IFLAGS /c %< /Fo%>',
-                'CXX'           => '%CC',
-                'CXXFLAGS'      => '%CFLAGS',
-                'CXXCOM'        => '%CXX %CXXFLAGS %_IFLAGS /c %< /Fo%>',
-                'INCDIRPREFIX'  => '/I',
-                'INCDIRSUFFIX'  => '',
-                'LINK'          => 'link',
-                'LINKCOM'       => '%LINK %LDFLAGS /out:%> %< %_LDIRS %LIBS',
-                'LINKMODULECOM' => '%LD /r /o %> %<',
-                'LIBDIRPREFIX'  => '/LIBPATH:',
-                'LIBDIRSUFFIX'  => '',
-                'AR'            => 'lib',
-                'ARFLAGS'       => '/nologo ',
-                'ARCOM'         => "%AR %ARFLAGS /out:%> %<",
-                'RANLIB'        => '',
-                'LD'            => 'link',
-                'LDFLAGS'       => '/nologo ',
-                'PREFLIB'       => '',
-    ],
-
-    # Defaults for a typical (?) UNIX platform.
-    # Your mileage may vary.
-    'unix' => [
-           'CC'            => 'cc',
-           'CFLAGS'        => '',
-           'CCCOM'         => '%CC %CFLAGS %_IFLAGS -c %< -o %>',
-           'CXX'           => '%CC',
-           'CXXFLAGS'      => '%CFLAGS',
-           'CXXCOM'        => '%CXX %CXXFLAGS %_IFLAGS -c %< -o %>',
-           'INCDIRPREFIX'  => '-I',
-           'INCDIRSUFFIX'  => '',
-           'LINK'          => '%CXX',
-           'LINKCOM'       => '%LINK %LDFLAGS -o %> %< %_LDIRS %LIBS',
-           'LINKMODULECOM' => '%LD -r -o %> %<',
-           'LIBDIRPREFIX'  => '-L',
-           'LIBDIRSUFFIX'  => '',
-           'AR'            => 'ar',
-           'ARFLAGS'       => 'r',                                       # rs?
-           'ARCOM'         => $ar_command,                               # pcons
-           'RANLIB'        => 'ranlib',
-           'AS'            => 'as',
-           'ASFLAGS'       => '',
-           'ASCOM'         => '%AS %ASFLAGS %< -o %>',
-           'LD'            => 'ld',
-           'LDFLAGS'       => '',
-           'PREFLIB'       => 'lib',
-           'ENV'           => {'PATH' => '/bin:/usr/bin'},
-    ],
-    );
-
-# Set the rules based on the platform.
-script::DefaultRules(script::RuleSet($_WIN32 ? 'msvc' : 'unix'));
-
-# Handle command line arguments.
-while (@ARGV)
-{
-    $_ = shift @ARGV;
-    last if /^--$/;    # Argument passing to Construct.
-    &option, next if s/^-//;
-    push (@param::include, $_), next if s/^\+//;
-    &equate, next if /=/;
-    push (@targets, $_), next;
-}
-
-sub option
-{
-    my %opt = (
-        'cc' => sub { $param::cachecom     = 1; },
-        'cd' => sub { $param::cachedisable = 1; },
-        'cr' => sub { $param::random       = 1; },
-        'cs' => sub { $param::cachesync    = 1; },
-        'd'  => sub { $param::depends      = 1; },
-        'h'  => sub { $param::localhelp    = 1; },
-        'k'  => sub { $param::kflag        = 1; },
-        'p'  => sub {
-            $param::pflag = 1;
-            $param::build = 0;
-        },
-        'pa' => sub {
-            $param::pflag = 1;
-            $param::aflag = 1;
-            $indent       = "... ";
-            $param::build = 0;
-        },
-        'pw' => sub {
-            $param::pflag = 1;
-            $param::wflag = 1;
-            $param::build = 0;
-        },
-        'q' => sub { $param::quiet++; },
-        'r' => sub {
-            $param::rflag = 1;
-            $param::build = 0;
-        },
-        't' => sub { $param::traverse = 1; },
-        'v' => sub { print($version); },
-        'V' => sub { print($version), exit(0); },
-        'x' => sub { print($usage), exit 0; },
-        );
-
-    my %opt_arg = (
-        'f' => sub { $param::topfile  = $_[0]; },
-        'o' => sub { $param::overfile = $_[0]; },
-        'R'  => sub { script::Repository($_[0]); },
-        'S'  => sub { $param::sigpro = $_[0]; },
-        'wf' => sub { $param::depfile = $_[0]; },
-        'j'  => sub { $param::max_jobs = $_[0]; },    # pcons
-        );
-
-    if (defined $opt{$_})
-    {
-        &{$opt{$_}} ();
-        return;
-    }
-    while ($_)
-    {
-        $_ =~ m/(.)(.*)/;
-        if (defined $opt{$1})
-        {
-            &{$opt{$1}} ();
-            $_ = $2;
-            next;
-        }
-        if (defined $opt_arg{$1})
-        {
-            if (!$2)
-            {
-                $_ = shift @ARGV;
-                die ("$0: -$1 option requires an argument.\n") if !$_;
-            }
-            &{$opt_arg{$1}} ($2 || $_);
-            return;
-        }
-        $_ =~ m/(..)(.*)/;
-        if (defined $opt_arg{$1})
-        {
-            if (!$2)
-            {
-                $_ = shift @ARGV;
-                die ("$0: -$1 option requires an argument.\n") if !$_;
-            }
-            &{$opt_arg{$1}} ($2 || $_);
-            return;
-        }
-        if ($_)
-        {
-            die
-              qq($0: unrecognized option "-$_".  Use -x for a usage message.\n);
-        }
-    }
-}
-
-# Process an equate argument (var=val).
-sub equate
-{
-    my ($var, $val) = /([^=]*)=(.*)/;
-    $script::ARG{$var} = $val;
-}
-
-# Define file signature protocol.
-'sig'->select($param::sigpro);
-
-# Cleanup after an interrupt.
-$SIG{INT} = $SIG{QUIT} = $SIG{TERM} = sub {
-    $SIG{PIPE} = $SIG{INT} = $SIG{QUIT} = $SIG{TERM} = 'IGNORE';
-    $SIG{HUP} = $SIG{INT} if !$main::_WIN32;
-    warn("\n$0: killed\n");
-
-    # Call this first, to make sure that this processing
-    # occurs even if a child process does not die (and we
-    # hang on the wait).
-    sig::hash::END();
-    wait();
-    exit(1);
-};
-$SIG{HUP} = $SIG{INT} if !$main::_WIN32;
-
-# Cleanup after a broken pipe (someone piped our stdout?)
-$SIG{PIPE} = sub {
-    $SIG{PIPE} = $SIG{HUP} = $SIG{INT} = $SIG{QUIT} = $SIG{TERM} = 'IGNORE';
-    warn("\n$0: broken pipe\n");
-    sig::hash::END();
-    wait();
-    exit(1);
-};
-
-if ($param::depfile)
-{
-    open(main::DEPFILE, ">" . $param::depfile)
-      || die ("$0: couldn't open $param::depfile ($!)\n");
-}
-
-# If the supplied top-level Conscript file is not in the
-# current directory, then change to that directory.
-{
-    my ($vol, $dir, $file) =
-      File::Spec->splitpath(File::Spec->canonpath($param::topfile));
-    if ($vol || $dir)
-    {
-        my ($cd) = File::Spec->catpath($vol, $dir, undef);
-        chdir($cd) || die ("$0: couldn't change to directory $cd ($!)\n");
-        $param::topfile = $file;
-    }
-}
-
-# Walk up the directory hierarchy looking for a Conscript file (if -t set).
-my ($target_top);
-my (@targetdir) = ();
-if ($param::traverse && !-f $param::topfile)
-{
-    my ($vol, $dirs, $file) = File::Spec->splitpath(cwd());
-    my (@dirs) = (File::Spec->splitdir($dirs), $file);
-    while (
-        !-f File::Spec->catpath($vol, File::Spec->catdir(@dirs),
-                                $param::topfile))
-    {
-        die ("$0: unable to find $param::topfile.\n") if !@dirs;
-        unshift (@targetdir, pop (@dirs));
-    }
-    my ($cwd) = File::Spec->catpath($vol, File::Spec->catdir(@dirs), '');
-    print "$0: Entering directory `$cwd'\n";
-    chdir($cwd);
-    @targets = map { File::Spec->catdir(@targetdir, $_) } @targets;
-}
-
-# Set up $dir::top and $dir::cwd, now that we are in the right directory.
-dir::init();
-
-#
-if (@targetdir)
-{
-    $target_top = $dir::top->lookupdir(File::Spec->catdir(@targetdir));
-}
-
-# Now handle override file.
-package override;
-if ($param::overfile)
-{
-    my ($ov) = $param::overfile;
-    die qq($0: can\'t read override file "$ov" ($!)\n) if !-f $ov;    #'
-    do $ov;
-    if ($@)
-    {
-        chop($@);
-        die qq($0: errors in override file "$ov" ($@)\n);
-    }
-}
-
-# Provide this to user to setup override patterns.
-sub Override
-{
-    my ($re, @env) = @_;
-    return if $param::overrides{$re};    # if identical, first will win.
-    $param::overrides = 1;
-    $param::overrides{$re} = \@env;
-    push (@param::overrides, $re);
-}
-
-package main;
-
-use vars qw( %priority $errors );
-
-# Check script inclusion regexps
-my $re;
-for $re (@param::include)
-{
-    if (!defined eval { "" =~ /$re/ })
-    {
-        my ($err) = $@;
-        $err =~ s/in regexp at .*$//;
-        die ("$0: error in regexp $err");
-    }
-}
-
-# Read the top-level construct file and its included scripts.
-doscripts($param::topfile);
-
-# Status priorities. This lets us aggregate status for directories
-# and print an appropriate message (at the top-level).
-%priority =
-  ('none' => 1, 'handled' => 2, 'built' => 3, 'unknown' => 4, 'errors' => 5);
-
-# If no targets were specified, supply default targets (if any).
- at targets = @param::default_targets if !@targets;
-
-$errors = 0;
-
-# Build the supplied target patterns.
-my $tgt;
-for $tgt (map($dir::top->lookup($_), @targets))
-{
-    if ($target_top && !$tgt->is_under($target_top))
-    {
-
-        # A -t option was used, and this target is not underneath
-        # the directory where we were invoked via -t.
-        # If the target is a directory and the -t directory
-        # is underneath it, then build the -t directory.
-        if (ref $tgt ne "dir" || !$target_top->is_under($tgt))
-        {
-            next;
-        }
-        $tgt = $target_top;
-    }
-    buildtoptarget($tgt);
-}
-
-exit 0 + ($errors != 0);
-
-sub buildtoptarget
-{
-    my ($tgt) = @_;
-    return if !$tgt;
-    my ($status) = buildtarget($tgt);
-    if ($status ne 'built')
-    {
-        my ($path) = $tgt->path;
-        if ($status eq "errors")
-        {
-            print qq($0: "$path" not remade because of errors.\n);
-            $errors++;
-        }
-        elsif ($status eq "handled")
-        {
-            print qq($0: "$path" is up-to-date.\n) if ($param::quiet < 2);
-        }
-        elsif ($status eq "unknown")
-        {
-
-            # cons error already reported.
-            $errors++;
-        }
-        elsif ($status eq "none")
-        {
-
-            # search for targets that may be linked to the given path.
-            my @linked = dir::linked_targets($tgt) if $target_top;
-            if (@linked)
-            {
-                my @names = map($_->path, @linked);
-                print "Linked targets: @names\n" if ($param::quiet < 1);
-                map(buildtoptarget($_), @linked);
-            }
-            else
-            {
-                print qq($0: nothing to be built in "$path".\n)
-                  if $param::build && ($param::quiet < 2);
-            }
-        }
-        else
-        {
-            print qq($0: don\'t know how to construct "$path".\n);    #'
-            $errors++;
-        }
-    }
-}
-
-# Build the supplied target directory or files. Return aggregated status.
-sub buildtarget
-{
-    my ($tgt) = @_;
-    if (ref($tgt) eq "dir")
-    {
-        my ($result)   = "none";
-        my ($priority) = $priority{$result};
-        if (exists $tgt->{member})
-        {
-            my ($members) = $tgt->{member};
-            my $entry;
-            for $entry (sort keys %$members)
-            {
-                next if $entry eq $dir::CURDIR || $entry eq $dir::UPDIR;
-                my ($tgt) = $members->{$entry};
-                next if ref($tgt) ne "dir" && !exists($tgt->{builder});
-                my ($stat) = buildtarget($members->{$entry});
-                my ($pri)  = $priority{$stat};
-                if ($pri > $priority)
-                {
-                    $priority = $pri;
-                    $result   = $stat;
-                }
-            }
-        }
-        return $result;
-    }
-    if ($param::depends)
-    {
-        my ($path) = $tgt->path;
-        if ($tgt->{builder})
-        {
-            my (@dep) = (@{$tgt->{dep}}, @{$tgt->{sources}});
-            my ($dep) = join (' ', map($_->path, @dep));
-            print("Target $path: $dep\n");
-        }
-        else
-        {
-            print("Target $path: not a derived file\n");
-        }
-    }
-    if ($param::build)
-    {
-        return build $tgt;
-    }
-    elsif ($param::pflag || $param::wflag || $param::aflag)
-    {
-        if ($tgt->{builder})
-        {
-            if ($param::wflag)
-            {
-                print qq(${\$tgt->path}: $tgt->{script}\n);
-            }
-            elsif ($param::pflag)
-            {
-                print qq(${\$tgt->path}:\n) if $param::aflag;
-                print qq(${\$tgt->path}\n)  if !$param::aflag;
-            }
-            if ($param::aflag)
-            {
-                $tgt->{builder}->action($tgt);
-            }
-        }
-    }
-    elsif ($param::rflag && $tgt->{builder})
-    {
-        my ($path) = $tgt->path;
-        if (-f $path)
-        {
-            if (unlink($path))
-            {
-                print("Removed $path\n") if ($param::quiet < 1);
-            }
-            else
-            {
-                warn("$0: couldn't remove $path\n");
-            }
-        }
-    }
-
-    return "none";
-}
-
-package NameSpace;
-
-# Return a hash that maps the name of symbols in a namespace to an
-# array of refs for all types for which the name has a defined value.
-# A list of symbols may be specified; default is all symbols in the
-# name space.
-sub save
-{
-    my $package = shift;
-    my (%namerefs, $var, $type);
-    no strict 'refs';
-    @_ = keys %{$package . "::"} if !@_;
-    foreach $var (@_)
-    {
-        $namerefs{$var} = [];
-        my $fqvar = $package . "::" . $var;
-
-        # If the scalar for this variable name doesn't already
-        # exist, *foo{SCALAR} will autovivify the reference
-        # instead of returning undef, so unlike the other types,
-        # we have to dereference to find out if it exists.
-        push (@{$namerefs{$var}}, *{$fqvar}{SCALAR})
-          if defined ${*{$fqvar}{SCALAR}};
-        foreach $type (qw(ARRAY HASH CODE IO))
-        {
-            push (@{$namerefs{$var}}, *{$fqvar}{$type})
-              if defined *{$fqvar}{$type};
-        }
-    }
-    return \%namerefs;
-}
-
-# Remove the specified symbols from the namespace.
-# Default is to remove all.
-sub remove
-{
-    my $package = shift;
-    my (%namerefs, $var);
-    no strict 'refs';
-    @_ = keys %{$package . "::"} if !@_;
-    foreach $var (@_)
-    {
-        delete ${$package . "::"}{$var};
-    }
-}
-
-# Restore values to symbols specified in a hash as returned
-# by NameSpace::save.
-sub restore
-{
-    my ($package, $namerefs) = @_;
-    my ($var, $ref);
-    no strict 'refs';
-    foreach $var (keys %$namerefs)
-    {
-        my $fqvar = $package . "::" . $var;
-        foreach $ref (@{$namerefs->{$var}})
-        {
-            *{$fqvar} = $ref;
-        }
-    }
-}
-
-# Support for "building" scripts, importing and exporting variables.
-# With the exception of the top-level routine here (invoked from the
-# main package by cons), these are all invoked by user scripts.
-package script;
-
-use vars qw( $ARG $caller_dir_path %special_var );
-
-BEGIN
-{
-
-    # We can't Export or Import the following variables because Perl always
-    # treats them as part of the "main::" package (see perlvar(1)).
-    %special_var = map { $_ => 1 } qw(ENV INC ARGV ARGVOUT SIG
-      STDIN STDOUT STDERR);
-}
-
-# This is called from main to interpret/run the top-level Construct
-# file, passed in as the single argument.
-sub main::doscripts
-{
-    my ($script) = @_;
-    Build($script);
-
-    # Now set up the includes/excludes (after the Construct file is read).
-    $param::include = join ('|', @param::include);
-
-    # Save the original variable names from the script package.
-    # These will stay intact, but any other "script::" variables
-    # defined in a Conscript file will get saved, deleted,
-    # and (when necessary) restored.
-    my (%orig_script_var) = map { $_ => 1 } keys %script::;
-    $caller_dir_path = undef;
-    my $cwd = Cwd::cwd();
-    my (@scripts) = pop (@priv::scripts);
-    while ($priv::self = shift (@scripts))
-    {
-        my ($path) = $priv::self->{script}->rsrcpath;
-        if (-f $path)
-        {
-            $dir::cwd = $priv::self->{script}->{dir};
-
-            # Handle chdir to the Conscript file directory, if necessary.
-            my ($vol, $dir, $file);
-            if ($param::conscript_chdir)
-            {
-                ($vol, $dir, $file) =
-                  File::Spec->splitpath(File::Spec->canonpath($path));
-                if ($vol ne '' || $dir ne '')
-                {
-                    $caller_dir_path = File::Spec->catpath($vol, $dir, undef);
-                    chdir($caller_dir_path)
-                      || die "Could not chdir to $caller_dir_path: $!\n";
-                }
-            }
-            else
-            {
-                $file = $path;
-            }
-
-            # Actually process the Conscript file.
-            do $file;
-
-            # Save any variables defined by the Conscript file
-            # so we can restore them later, if needed;
-            # then delete them from the script:: namespace.
-            my (@del) = grep(!$orig_script_var{$_}, keys %script::);
-            if (@del)
-            {
-                $priv::self->{script}->{pkgvars} =
-                  NameSpace::save('script', @del);
-                NameSpace::remove('script', @del);
-            }
-            if ($caller_dir_path)
-            {
-                chdir($cwd);
-                $caller_dir_path = undef;
-            }
-            if ($@)
-            {
-                chomp($@);
-                my $err = ($@ =~ /\n/ms) ? ":\n$@" : " ($@)";
-                print qq($0: error in file "$path"$err\n);
-                $run::errors++;
-            }
-            else
-            {
-
-                # Only process subsidiary scripts if no errors in parent.
-                unshift (@scripts, @priv::scripts);
-            }
-            undef @priv::scripts;
-        }
-        else
-        {
-            my $where = '';
-            my $cref  = $priv::self->{script}->creator;
-            if (defined $cref)
-            {
-                my ($_foo, $script, $line, $sub) = @$cref;
-                $where = " ($sub in $script, line $line)";
-            }
-            warn qq(Ignoring missing script "$path"$where);
-        }
-    }
-    die ("$0: script errors encountered: construction aborted\n")
-      if $run::errors;
-}
-
-# Return caller info about the method being invoked.
-# This is everything from the Perl "caller" builtin function,
-# including which Construct/Conscript file, line number,
-# subroutine name, etc.
-sub caller_info
-{
-    my ($lev) = 1;
-    my (@frame);
-    do
-    {
-        @frame = caller ++$lev;
-        if (defined($frame[3]) && $frame[3] eq '(eval)')
-        {
-            @frame = caller --$lev;
-            if ($caller_dir_path)
-            {
-                $frame[1] = File::Spec->catfile($caller_dir_path, $frame[1]);
-            }
-            return @frame;
-        }
-    } while ($frame[3]);
-    return;
-}
-
-# Link a directory to another. This simply means set up the *source*
-# for the directory to be the other directory.
-sub Link
-{
-    dir::link(@_);
-}
-
-# Add directories to the repository search path for files.
-# Strip our current directory from the list so Repository
-# (or -R options) can be used from within the repository.
-sub Repository
-{
-    my ($my_dir) = Cwd::cwd();
-    my $dir;
-    foreach $dir (@_)
-    {
-
-        # The following more direct call isn't available in
-        # Cwd.pm until some time after 5.003...
-        #	my($d) = Cwd::abs_path($dir);
-        chdir($dir);
-        my ($d) = Cwd::cwd();
-        chdir($my_dir);
-
-        #
-        next if !$d || !-d $d || $d eq $my_dir;
-
-        # We know we can get away with passing undef to lookupdir
-        # as the directory because $dir is an absolute path.
-        push (@param::rpath, dir::lookupdir(undef, $dir));
-        push @INC, $d;
-    }
-}
-
-# Return the list of Repository directories specified.
-sub Repository_List
-{
-    map($_->path, @param::rpath);
-}
-
-# Specify whether the .consign signature times in repository files are,
-# in fact, consistent with the times on the files themselves.
-sub Repository_Sig_Times_OK
-{
-    $param::rep_sig_times_ok = shift;
-}
-
-sub SourceSignature
-{
-    $param::sourcesig = [@_];
-}
-
-# Specify whether we should chdir to the containing directories
-# of Conscript files.
-sub Conscript_chdir
-{
-    $param::conscript_chdir = shift;
-}
-
-# Specify files/targets that must be present and built locally,
-# even if they exist already-built in a Repository.
-sub Local
-{
-    my (@files) = map($dir::cwd->lookupfile($_), @_);
-    map($_->local(1), @files);
-}
-
-# Export variables to any scripts invoked from this one.
-sub Export
-{
-    my (@illegal) = grep($special_var{$_}, @_);
-    if (@illegal)
-    {
-        die qq($0: cannot Export special Perl variables: @illegal\n);
-    }
-    @{$priv::self->{exports}} = grep(!defined $special_var{$_}, @_);
-}
-
-# Import variables from the export list of the caller
-# of the current script.
-sub Import
-{
-    my (@illegal) = grep($special_var{$_}, @_);
-    if (@illegal)
-    {
-        die qq($0: cannot Import special Perl variables: @illegal\n);
-    }
-    my ($parent)  = $priv::self->{parent};
-    my ($imports) = $priv::self->{imports};
-    @{$priv::self->{exports}} = keys %$imports;
-    my ($var);
-    foreach $var (grep(!defined $special_var{$_}, @_))
-    {
-        if (!exists $imports->{$var})
-        {
-            my ($path) = $parent->{script}->path;
-            die qq($0: variable "$var" not exported by file "$path"\n);
-        }
-        if (!defined $imports->{$var})
-        {
-            my $path = $parent->{script}->path;
-            my $err  =
-              "$0: variable \"$var\" exported but not "
-              . "defined by file \"$path\"\n";
-            die $err;
-        }
-        ${"script::$var"} = $imports->{$var};
-    }
-}
-
-# Build an inferior script. That is, arrange to read and execute
-# the specified script, passing to it any exported variables from
-# the current script.
-sub Build
-{
-    my (@files) = map($dir::cwd->lookupfile($_), @_);
-    my (%imports) = map { $_ => ${"script::$_"} } @{$priv::self->{exports}};
-    my $file;
-    for $file (@files)
-    {
-        next if $param::include && $file->path !~ /$param::include/o;
-        my ($self) = {
-                       'script'  => $file,
-                       'parent'  => $priv::self,
-                       'imports' => \%imports
-                       };
-        bless $self;    # may want to bless into class of parent in future
-        push (@priv::scripts, $self);
-    }
-}
-
-# Set up regexps dependencies to ignore. Should only be called once.
-sub Ignore
-{
-    die ("Ignore called more than once\n") if $param::ignore;
-    $param::ignore = join ("|", map("($_)", @_)) if @_;
-}
-
-# Specification of default targets.
-sub Default
-{
-    push (@param::default_targets, map($dir::cwd->lookup($_)->path, @_));
-}
-
-# Local Help.  Should only be called once.
-sub Help
-{
-    if ($param::localhelp)
-    {
-        print "@_\n";
-        exit 2;
-    }
-}
-
-# For windows platforms which use unix tool sets, the msvc defaults may
-# not be useful. Also, in the future, other platforms (Mac?) may have the
-# same problem.
-sub RuleSet
-{
-    my $style    = shift;
-    my @rulesets = sort keys %param::rulesets;
-    die "Unknown style for rules: $style.\n"
-      . "Supported rules are: ("
-      . join (" ", @rulesets) . ")"
-      unless eval(join ("||", map("\$style eq '$_'", @rulesets)));
-    return @param::base, @{$param::rulesets{$style}};
-}
-
-sub DefaultRules
-{
-    @param::defaults = ();
-    push @param::defaults, @_;
-}
-
-# Return the build name(s) of a file or file list.
-sub FilePath
-{
-    wantarray 
-      ? map($dir::cwd->lookupfile($_)->path, @_)
-      : $dir::cwd->lookupfile($_[0])->path;
-}
-
-# Return the build name(s) of a directory or directory list.
-sub DirPath
-{
-    wantarray 
-      ? map($dir::cwd->lookupdir($_)->path, @_)
-      : $dir::cwd->lookupdir($_[0])->path;
-}
-
-# Split the search path provided into components. Look each up
-# relative to the current directory.
-# The usual path separator problems abound; for now we'll use :
-sub SplitPath
-{
-    my ($dirs) = @_;
-    if (ref($dirs) ne "ARRAY")
-    {
-        $dirs = [split (/$main::PATH_SEPARATOR/o, $dirs)];
-    }
-    map { DirPath($_) } @$dirs;
-}
-
-# Return true if the supplied path is available as a source file
-# or is buildable (by rules seen to-date in the build).
-sub ConsPath
-{
-    my ($path) = @_;
-    my ($file) = $dir::cwd->lookup($path);
-    return $file->accessible;
-}
-
-# Return the source path of the supplied path.
-sub SourcePath
-{
-    wantarray 
-      ? map($dir::cwd->lookupfile($_)->rsrcpath, @_)
-      : $dir::cwd->lookupfile($_[0])->rsrcpath;
-}
-
-# Search up the tree for the specified cache directory, starting with
-# the current directory. Returns undef if not found, 1 otherwise.
-# If the directory is found, then caching is enabled. The directory
-# must be readable and writable. If the argument "mixtargets" is provided,
-# then targets may be mixed in the cache (two targets may share the same
-# cache file--not recommended).
-sub UseCache($@)
-{
-    my ($dir, @args) = @_;
-
-    # NOTE: it's important to process arguments here regardless of whether
-    # the cache is disabled temporarily, since the mixtargets option affects
-    # the salt for derived signatures.
-    for (@args)
-    {
-        if ($_ eq "mixtargets")
-        {
-
-            # When mixtargets is enabled, we salt the target signatures.
-            # This is done purely to avoid a scenario whereby if
-            # mixtargets is turned on or off after doing builds, and
-            # if cache synchronization with -cs is used, then
-            # cache files may be shared in the cache itself (linked
-            # under more than one name in the cache). This is not bad,
-            # per se, but simply would mean that a cache cleaning algorithm
-            # that looked for a link count of 1 would never find those
-            # particular files; they would always appear to be in use.
-            $param::salt       = 'M' . $param::salt;
-            $param::mixtargets = 1;
-        }
-        else
-        {
-            die qq($0: UseCache unrecognized option "$_"\n);
-        }
-    }
-    if ($param::cachedisable)
-    {
-        warn("Note: caching disabled by -cd flag\n");
-        return 1;
-    }
-    my ($depth) = 15;
-    while ($depth-- && !-d $dir)
-    {
-        $dir = File::Spec->catdir($dir::UPDIR, $dir);
-    }
-    if (-d $dir)
-    {
-        $param::cache = $dir;
-        return 1;
-    }
-    return undef;
-}
-
-# Salt the signature generator. The salt (a number of string) is added
-# into the signature of each derived file. Changing the salt will
-# force recompilation of all derived files.
-sub Salt($)
-{
-
-    # We append the value, so that UseCache and Salt may be used
-    # in either order without changing the signature calculation.
-    $param::salt .= $_[0];
-}
-
-# Mark files (or directories) to not be removed before building.
-sub Precious
-{
-    map($_->{precious} = 1, map($dir::cwd->lookup($_), @_));
-}
-
-# These methods are callable from Conscript files, via a cons
-# object. Procs beginning with _ are intended for internal use.
-package cons;
-
-use vars qw( %envcache );
-
-# This is passed the name of the base environment to instantiate.
-# Overrides to the base environment may also be passed in
-# as key/value pairs.
-sub new
-{
-    my ($package) = shift;
-    my ($env) = {@param::defaults, @_};
-    @{$env->{_envcopy}} = %$env;    # Note: we never change PATH
-    $env->{_cwd} = $dir::cwd;       # Save directory of environment for
-    bless $env, $package;           # any deferred name interpretation.
-}
-
-# Clone an environment.
-# Note that the working directory will be the initial directory
-# of the original environment.
-sub clone
-{
-    my ($env) = shift;
-    my $clone = {@{$env->{_envcopy}}, @_};
-    @{$clone->{_envcopy}} = %$clone;    # Note: we never change PATH
-    $clone->{_cwd} = $env->{_cwd};
-    bless $clone, ref $env;
-}
-
-# Create a flattened hash representing the environment.
-# It also contains a copy of the PATH, so that the path
-# may be modified if it is converted back to a hash.
-sub copy
-{
-    my ($env) = shift;
-    (@{$env->{_envcopy}}, 'ENV' => {%{$env->{ENV}}}, @_);
-}
-
-# Resolve which environment to actually use for a given
-# target. This is just used for simple overrides.
-sub _resolve
-{
-    return $_[0] if !$param::overrides;
-    my ($env, $tgt) = @_;
-    my ($path) = $tgt->path;
-    my $re;
-    for $re (@param::overrides)
-    {
-        next if $path !~ /$re/;
-
-        # Found one. Return a combination of the original environment
-        # and the override.
-        my ($ovr) = $param::overrides{$re};
-        return $envcache{$env, $re} if $envcache{$env, $re};
-        my ($newenv) = {@{$env->{_envcopy}}, @$ovr};
-        @{$newenv->{_envcopy}} = %$env;
-        $newenv->{_cwd} = $env->{_cwd};
-        return $envcache{$env, $re} = bless $newenv, ref $env;
-    }
-    return $env;
-}
-
-# Substitute construction environment variables into a string.
-# Internal function/method.
-sub _subst
-{
-    my ($env, $str) = @_;
-    if (!defined $str)
-    {
-        return undef;
-    }
-    elsif (ref($str) eq "ARRAY")
-    {
-        return [map($env->_subst($_), @$str)];
-    }
-    else
-    {
-
-        # % expansion.  %% gets converted to % later, so expand any
-        # %keyword construction that doesn't have a % in front of it,
-        # modulo multiple %% pairs in between.
-        # In Perl 5.005 and later, we could actually do this in one regex
-        # using a conditional expression as follows,
-        #	while ($str =~ s/($pre)\%(\{)?([_a-zA-Z]\w*)(?(2)\})/"$1".
-        #                      $env->{$3}/ge) {}
-        # The following two-step approach is backwards-compatible
-        # to (at least) Perl5.003.
-        my $pre = '^|[^\%](?:\%\%)*';
-        while (($str =~ s/($pre)\%([_a-zA-Z]\w*)/$1.($env->{$2}||'')/ge)
-               || ($str =~ s/($pre)\%\{([_a-zA-Z]\w*)\}/$1.($env->{$2}||'')/ge))
-        {
-        }
-        return $str;
-    }
-}
-
-sub AfterBuild
-{
-    my ($env)           = shift;
-    my ($perl_eval_str) = pop (@_);
-    my $file;
-    for $file (map($dir::cwd->lookup($_), @_))
-    {
-        $file->{after_build_func} = $perl_eval_str;
-
-    }
-}
-
-sub Install
-{
-    my ($env)    = shift;
-    my ($tgtdir) = $dir::cwd->lookupdir($env->_subst(shift));
-    my $file;
-    for $file (map($dir::cwd->lookupfile($env->_subst($_)), @_))
-    {
-        my ($tgt) = $tgtdir->lookupfile($file->{entry});
-        $tgt->bind(find build::install($env), $file);
-    }
-}
-
-sub InstallAs
-{
-    my $env     = shift;
-    my $tgt     = shift;
-    my $src     = shift;
-    my @sources = ();
-    my @targets = ();
-
-    if (ref $tgt)
-    {
-        die "InstallAs: Source is a file and target is a list!\n"
-          if (!ref($src));
-        @sources = @$src;
-        @targets = @$tgt;
-    }
-    elsif (ref $src)
-    {
-        die "InstallAs: Target is a file and source is a list!\n";
-    }
-    else
-    {
-        push @sources, $src;
-        push @targets, $tgt;
-    }
-
-    if ($#sources != $#targets)
-    {
-        my $tn = $#targets + 1;
-        my $sn = $#sources + 1;
-        die "InstallAs: Source file list ($sn) and target file list ($tn) "
-          . "are inconsistent in length!\n";
-    }
-    else
-    {
-        foreach (0 .. $#sources)
-        {
-            my $tfile = $dir::cwd->lookupfile($env->_subst($targets[$_]));
-            my $sfile = $dir::cwd->lookupfile($env->_subst($sources[$_]));
-            $tfile->bind(find build::install($env), $sfile);
-        }
-    }
-}
-
-# Installation in a local build directory,
-# copying from the repository if it's already built there.
-# Functionally equivalent to:
-#	Install $env $dir, $file;
-#	Local "$dir/$file";
-sub Install_Local
-{
-    my ($env)    = shift;
-    my ($tgtdir) = $dir::cwd->lookupdir($env->_subst(shift));
-    my $file;
-    for $file (map($dir::cwd->lookupfile($env->_subst($_)), @_))
-    {
-        my ($tgt) = $tgtdir->lookupfile($file->{entry});
-        $tgt->bind(find build::install($env), $file);
-        $tgt->local(1);
-    }
-}
-
-sub Objects
-{
-    my ($env) = shift;
-    map($dir::cwd->relpath($_), $env->_Objects(@_));
-}
-
-# Called with multiple source file references (or object files).
-# Returns corresponding object files references.
-sub _Objects
-{
-    my ($env)    = shift;
-    my ($suffix) = $env->{SUFOBJ};
-    map($env->_Object($_, $_->{dir}->lookupfile($_->base_suf($suffix))),
-      map { ref $_ ? $_ : $dir::cwd->lookupfile($env->_subst($_)) }
-      grep(defined $_, @_));
-}
-
-# Called with an object and source reference.  If no object reference
-# is supplied, then the object file is determined implicitly from the
-# source file's extension. Sets up the appropriate rules for creating
-# the object from the source.  Returns the object reference.
-sub _Object
-{
-    my ($env, $src, $obj) = @_;
-    return $obj if $src eq $obj;    # don't need to build self from self.
-    my ($objenv) = $env->_resolve($obj);
-    my ($suffix) = $src->suffix;
-
-    my ($builder) = $env->{SUFMAP}{$suffix};
-
-    if ($builder)
-    {
-        $obj->bind((find $builder($objenv)), $src);
-    }
-    else
-    {
-        die ("don't know how to construct ${\$obj->path} from "
-             . "${\$src->path}.\n");
-    }
-    $obj;
-}
-
-sub Program
-{
-    my ($env) = shift;
-    my ($tgt) =
-      $dir::cwd->lookupfile(
-                          file::addsuffix($env->_subst(shift), $env->{SUFEXE}));
-    my ($progenv) = $env->_resolve($tgt);
-    $tgt->bind(find build::command::link($progenv, $progenv->{LINKCOM}),
-               $env->_Objects(@_));
-}
-
-sub Module
-{
-    my ($env)    = shift;
-    my ($tgt)    = $dir::cwd->lookupfile($env->_subst(shift));
-    my ($modenv) = $env->_resolve($tgt);
-    my ($com)    = pop (@_);
-    $tgt->bind(find build::command::link($modenv, $com), $env->_Objects(@_));
-}
-
-sub LinkedModule
-{
-    my ($env)     = shift;
-    my ($tgt)     = $dir::cwd->lookupfile($env->_subst(shift));
-    my ($progenv) = $env->_resolve($tgt);
-    $tgt->bind(
-               find build::command::linkedmodule($progenv,
-                                                 $progenv->{LINKMODULECOM}),
-               $env->_Objects(@_));
-}
-
-sub Library
-{
-    my ($env) = shift;
-    my ($lib) =
-      $dir::cwd->lookupfile(
-                          file::addsuffix($env->_subst(shift), $env->{SUFLIB}));
-    my ($libenv) = $env->_resolve($lib);
-    $lib->bind(find build::command::library($libenv), $env->_Objects(@_));
-}
-
-# Simple derivation: you provide target, source(s), command.
-# Special variables substitute into the rule.
-# Target may be a reference, in which case it is taken
-# to be a multiple target (all targets built at once).
-sub Command
-{
-    my ($env)     = shift;
-    my ($tgt)     = $env->_subst(shift);
-    my ($builder) = find build::command::user($env, pop (@_), 'script');
-    my (@sources) = map($dir::cwd->lookupfile($env->_subst($_)), @_);
-    if (ref($tgt))
-    {
-
-        # A multi-target command.
-        my (@tgts) = map($dir::cwd->lookupfile($_), @$tgt);
-        die ("empty target list in multi-target command\n") if !@tgts;
-        $env = $env->_resolve($tgts[0]);
-        my ($multi) = build::multiple->new($builder, \@tgts);
-        for $tgt (@tgts)
-        {
-            $tgt->bind($multi, @sources);
-        }
-    }
-    else
-    {
-        $tgt = $dir::cwd->lookupfile($tgt);
-        $env = $env->_resolve($tgt);
-        $tgt->bind($builder, @sources);
-    }
-}
-
-sub Depends
-{
-    my ($env)  = shift;
-    my ($tgt)  = $env->_subst(shift);
-    my (@deps) = map($dir::cwd->lookup($env->_subst($_)), @_);
-    if (!ref($tgt))
-    {
-        $tgt = [$tgt];
-    }
-    my ($t);
-    foreach $t (map($dir::cwd->lookupfile($_), @$tgt))
-    {
-        push (@{$t->{dep}}, @deps);
-    }
-}
-
-# Setup a quick scanner for the specified input file, for the
-# associated environment. Any use of the input file will cause the
-# scanner to be invoked, once only. The scanner sees just one line at
-# a time of the file, and is expected to return a list of
-# dependencies.
-sub QuickScan
-{
-    my ($env, $code, $file, $path) = @_;
-    $dir::cwd->lookup($env->_subst($file))->{'srcscan', $env} =
-      find scan::quickscan($code, $env, $env->_subst($path));
-}
-
-# Generic builder module. Just a few default methods.  Every derivable
-# file must have a builder object of some sort attached.  Usually
-# builder objects are shared.
-package build;
-
-use vars qw( %builder );
-
-# Every builder must now have at least an associated environment,
-# so we can find its sigarray and calculate the proper signature.
-sub find
-{
-    my ($class, $env) = @_;
-    $builder{$env} || do
-    {
-        my $self = {env => $env};
-        $builder{$env} = bless $self, $class;
-      }
-}
-
-# Null signature for dynamic includes.
-sub includes { () }
-
-# Null signature for build script.
-sub scriptsig { () }
-
-# Not compatible with any other builder, by default.
-sub compatible { 0 }
-
-# Builder module for the Install command.
-package build::install;
-
-use vars qw( @ISA );
-
-BEGIN { @ISA = qw(build) }
-
-# Caching not supported for Install: generally install is trivial anyway,
-# and we don't want to clutter the cache.
-sub cachin  { undef }
-sub cachout { }
-
-# Do the installation.
-sub action
-{
-    my ($self, $tgt) = @_;
-    my ($src) = $tgt->{sources}[0];
-    main::showcom("Install ${\$src->rpath} as ${\$tgt->path}")
-      if ($param::install && $param::quiet < 1);
-    return unless $param::build;
-    futil::install($src->rpath, $tgt);
-    return 1;
-}
-
-# Builder module for generic UNIX commands.
-package build::command;
-
-use vars qw( @ISA %com );
-
-BEGIN { @ISA = qw(build) }
-
-sub find
-{
-    my ($class, $env, $cmd, $package) = @_;
-    my ($act) = action::new($env, $cmd);
-    $package ||= '';
-    $com{$env, $act, $package} || do
-    {
-        my $self = {env => $env, act => $act, 'package' => $package};
-        $com{$env, $act, $package} = bless $self, $class;
-      }
-}
-
-# Default cache in function.
-sub cachin
-{
-    my ($self, $tgt, $sig) = @_;
-    if (cache::in($tgt, $sig))
-    {
-        if ($param::cachecom)
-        {
-            $self->{act}->show($self->{env}, $tgt);
-        }
-        else
-        {
-            printf("Retrieved %s from cache\n", $tgt->path)
-              if ($param::quiet < 1);
-        }
-        return 1;
-    }
-    return undef;
-}
-
-# Default cache out function.
-sub cachout
-{
-    my ($self, $tgt, $sig) = @_;
-    cache::out($tgt, $sig);
-}
-
-# Build the target using the previously specified commands.
-sub action
-{
-    my ($self, $tgt) = @_;
-    $self->{act}->execute($self->{env}, $tgt, $self->{'package'});
-}
-
-# Return script signature.
-sub scriptsig
-{
-    $_[0]->{act}->scriptsig;
-}
-
-# Create a linked module.
-package build::command::link;
-
-use vars qw( @ISA );
-
-BEGIN { @ISA = qw(build::command) }
-
-# Find an appropriate linker.
-sub find
-{
-    my ($class, $env, $command) = @_;
-    if (!exists $env->{_LDIRS})
-    {
-        my ($ldirs) = '';
-        my ($wd)    = $env->{_cwd};
-        my ($pdirs) = $env->{LIBPATH};
-        if (!defined $pdirs)
-        {
-            $pdirs = [];
-        }
-        elsif (ref($pdirs) ne 'ARRAY')
-        {
-            $pdirs = [split (/$main::PATH_SEPARATOR/o, $pdirs)];
-        }
-        my ($dir, $dpath);
-        for $dir (map($wd->lookupdir($env->_subst($_)), @$pdirs))
-        {
-            $dpath = $dir->path;
-
-            # Add the (presumably local) directory to the -L flags
-            # if we're not using repositories, the directory exists,
-            # or it's Linked to a source directory (that is, it *will*
-            # exist by the time the link occurs).
-            $ldirs .= " " . $env->{LIBDIRPREFIX} . $dpath . $env->{LIBDIRSUFFIX}
-              if !@param::rpath || -d $dpath || $dir->is_linked;
-            next if File::Spec->file_name_is_absolute($dpath);
-            if (@param::rpath)
-            {
-                my $d;
-                if ($dpath eq $dir::CURDIR)
-                {
-                    foreach $d (map($_->path, @param::rpath))
-                    {
-                        $ldirs .= " "
-                          . $env->{LIBDIRPREFIX} . $d
-                          . $env->{LIBDIRSUFFIX};
-                    }
-                }
-                else
-                {
-                    my ($rpath);
-                    foreach $d (map($_->path, @param::rpath))
-                    {
-                        $rpath = File::Spec->catfile($d, $dpath);
-                        $ldirs .= " "
-                          . $env->{LIBDIRPREFIX} . $rpath
-                          . $env->{LIBDIRSUFFIX}
-                          if -d $rpath;
-                    }
-                }
-            }
-        }
-        $env->{_LDIRS} = "%($ldirs%)";
-    }
-
-    # Introduce a new magic _LIBS symbol which allows to use the
-    # Unix-style -lNAME syntax for Win32 only. -lNAME will be replaced
-    # with %{PREFLIB}NAME%{SUFLIB}. <schwarze at isa.de> 1998-06-18
-
-    if ($main::_WIN32 && !exists $env->{_LIBS})
-    {
-        my $libs;
-        my $name;
-        for $name (split (' ', $env->_subst($env->{LIBS} || '')))
-        {
-            if ($name =~ /^-l(.*)/)
-            {
-                $name = "$env->{PREFLIB}$1$env->{SUFLIB}";
-            }
-            $libs .= ' ' . $name;
-        }
-        $env->{_LIBS} = $libs ? "%($libs%)" : '';
-    }
-    bless find build::command($env, $command);
-}
-
-# Called from file::build. Make sure any libraries needed by the
-# environment are built, and return the collected signatures
-# of the libraries in the path.
-sub includes
-{
-    return $_[0]->{'bsig'} if exists $_[0]->{'bsig'};
-    my ($self, $tgt) = @_;
-    my ($env) = $self->{env};
-    my ($ewd) = $env->{_cwd};
-    my $ldirs = $env->{LIBPATH};
-    if (!defined $ldirs)
-    {
-        $ldirs = [];
-    }
-    elsif (ref($ldirs) ne 'ARRAY')
-    {
-        $ldirs = [split (/$main::PATH_SEPARATOR/o, $ldirs)];
-    }
-    my @lpath = map($ewd->lookupdir($_), @$ldirs);
-    my (@sigs);
-    my (@names);
-
-    # Pass %LIBS symbol through %-substituition
-    # <schwarze at isa.de> 1998-06-18
-    @names = split (' ', $env->_subst($env->{LIBS} || ''));
-    my $name;
-    for $name (@names)
-    {
-        my ($lpath, @allnames);
-        if ($name =~ /^-l(.*)/)
-        {
-
-            # -l style names are looked up on LIBPATH, using all
-            # possible lib suffixes in the same search order the
-            # linker uses (according to SUFLIBS).
-            # Recognize new PREFLIB symbol, which should be 'lib' on
-            # Unix, and empty on Win32. TODO: What about shared
-            # library suffixes?  <schwarze at isa.de> 1998-05-13
-            @allnames =
-              map("$env->{PREFLIB}$1$_", split (/:/, $env->{SUFLIBS}));
-            $lpath = \@lpath;
-        }
-        else
-        {
-            @allnames = ($name);
-
-            # On Win32, all library names are looked up in LIBPATH
-            # <schwarze at isa.de> 1998-05-13
-            if ($main::_WIN32)
-            {
-                $lpath = [$dir::top, @lpath];
-            }
-            else
-            {
-                $lpath = [$dir::top];
-            }
-        }
-        my $dir;
-        DIR: for $dir (@$lpath)
-        {
-            my $n;
-            for $n (@allnames)
-            {
-                my ($lib) = $dir->lookup_accessible($n);
-                if ($lib)
-                {
-                    last DIR if $lib->ignore;
-                    if ((build $lib) eq 'errors')
-                    {
-                        $tgt->{status} = 'errors';
-                        return undef;
-                    }
-                    push (@sigs, 'sig'->signature($lib));
-                    last DIR;
-                }
-            }
-        }
-    }
-    $self->{'bsig'} = 'sig'->collect(@sigs);
-}
-
-# Always compatible with other such builders, so the user
-# can define a single program or module from multiple places.
-sub compatible
-{
-    my ($self, $other) = @_;
-    ref($other) eq "build::command::link";
-}
-
-# Link a program.
-package build::command::linkedmodule;
-
-use vars qw( @ISA );
-
-BEGIN { @ISA = qw(build::command) }
-
-# Always compatible with other such builders, so the user
-# can define a single linked module from multiple places.
-sub compatible
-{
-    my ($self, $other) = @_;
-    ref($other) eq "build::command::linkedmodule";
-}
-
-# Builder for a C module
-package build::command::cc;
-
-use vars qw( @ISA );
-
-BEGIN { @ISA = qw(build::command) }
-
-sub find
-{
-    $_[1]->{_cc} || do
-    {
-        my ($class, $env) = @_;
-        my ($cpppath) = $env->_subst($env->{CPPPATH});
-        my ($cscanner) = find scan::cpp($env->{_cwd}, $cpppath);
-        $env->{_IFLAGS} = "%(" . $cscanner->iflags($env) . "%)";
-        my ($self) = find build::command($env, $env->{CCCOM});
-        $self->{scanner} = $cscanner;
-        bless $env->{_cc} = $self;
-      }
-}
-
-# Invoke the associated	 C scanner to get signature of included files.
-sub includes
-{
-    my ($self, $tgt) = @_;
-    $self->{scanner}->includes($tgt, $tgt->{sources}[0]);
-}
-
-# Builder for a C++ module
-package build::command::cxx;
-
-use vars qw( @ISA );
-
-BEGIN { @ISA = qw(build::command) }
-
-sub find
-{
-    $_[1]->{_cxx} || do
-    {
-        my ($class, $env) = @_;
-        my ($cpppath) = $env->_subst($env->{CPPPATH});
-        my ($cscanner) = find scan::cpp($env->{_cwd}, $cpppath);
-        $env->{_IFLAGS} = "%(" . $cscanner->iflags($env) . "%)";
-        my ($self) = find build::command($env, $env->{CXXCOM});
-        $self->{scanner} = $cscanner;
-        bless $env->{_cxx} = $self;
-      }
-}
-
-# Invoke the associated	 C scanner to get signature of included files.
-sub includes
-{
-    my ($self, $tgt) = @_;
-    $self->{scanner}->includes($tgt, $tgt->{sources}[0]);
-}
-
-# Builder for a user command (cons::Command).  We assume that a user
-# command might be built and implement the appropriate dependencies on
-# the command itself (actually, just on the first word of the command
-# line).
-package build::command::user;
-
-use vars qw( @ISA );
-
-BEGIN { @ISA = qw(build::command) }
-
-sub includes
-{
-    my ($self, $tgt) = @_;
-    my ($sig) = '';
-
-    # Check for any quick scanners attached to source files.
-    my $dep;
-    for $dep (@{$tgt->{dep}}, @{$tgt->{sources}})
-    {
-        my ($scanner) = $dep->{'srcscan', $self->{env}};
-        if ($scanner)
-        {
-            $sig .= $scanner->includes($tgt, $dep);
-        }
-    }
-
-    # XXX Optimize this to not use ignored paths.
-    if (!exists $self->{_comsig})
-    {
-        my ($env) = $self->{env};
-        $self->{_comsig} = '';
-        my ($com, $dir);
-        com:
-        for $com ($self->{act}->commands)
-        {
-            my ($pdirs) = $env->{ENV}->{PATH};
-            if (!defined $pdirs)
-            {
-                $pdirs = [];
-            }
-            elsif (ref($pdirs) ne 'ARRAY')
-            {
-                $pdirs = [split (/$main::PATH_SEPARATOR/o, $pdirs)];
-            }
-            for $dir (map($dir::top->lookupdir($_), @$pdirs))
-            {
-                my ($prog) = $dir->lookup_accessible($com);
-                if ($prog)
-                {    # XXX Not checking execute permission.
-                    if ((build $prog) eq 'errors')
-                    {
-                        $tgt->{status} = 'errors';
-                        return $sig;
-                    }
-                    next com if $prog->ignore;
-                    $self->{_comsig} .= 'sig'->signature($prog);
-                    next com;
-                }
-            }
-        }
-    }
-
-    return $self->{_comsig} . $sig;
-}
-
-# Builder for a library module (archive).
-# We assume that a user command might be built and implement the
-# appropriate dependencies on the command itself.
-package build::command::library;
-
-use vars qw( @ISA );
-
-BEGIN { @ISA = qw(build::command) }
-
-sub find
-{
-    my ($class, $env) = @_;
-    bless find build::command($env, $env->{ARCOM});
-}
-
-# Always compatible with other library builders, so the user
-# can define a single library from multiple places.
-sub compatible
-{
-    my ($self, $other) = @_;
-    ref($other) eq "build::command::library";
-}
-
-# A multi-target builder.
-# This allows multiple targets to be associated with a single build
-# script, without forcing all the code to be aware of multiple targets.
-package build::multiple;
-
-sub new
-{
-    my ($class, $builder, $tgts) = @_;
-    bless {'builder' => $builder, 'env' => $builder->{env}, 'tgts' => $tgts};
-}
-
-sub scriptsig
-{
-    my ($self, $tgt) = @_;
-    $self->{builder}->scriptsig($tgt);
-}
-
-sub includes
-{
-    my ($self, $tgt) = @_;
-    $self->{builder}->includes($tgt);
-}
-
-sub compatible
-{
-    my ($self, $tgt) = @_;
-    $self->{builder}->compatible($tgt);
-}
-
-sub cachin
-{
-    my ($self, $tgt, $sig) = @_;
-    $self->{builder}->cachin($tgt, $sig);
-}
-
-sub cachout
-{
-    my ($self, $tgt, $sig) = @_;
-    $self->{builder}->cachout($tgt, $sig);
-}
-
-sub action
-{
-    my ($self, $invoked_tgt) = @_;
-    return $self->{built} if exists $self->{built};
-
-    # Make sure all targets in the group are unlinked before building any.
-    my ($tgts) = $self->{tgts};
-    my $tgt;
-    for $tgt (@$tgts)
-    {
-        futil::mkdir($tgt->{dir});
-        unlink($tgt->path) if !$tgt->precious;
-    }
-
-    # Now do the action to build all the targets. For consistency
-    # we always call the action on the first target, just so that
-    # $> is deterministic.
-    if ($param::max_jobs <= 1)
-    {    # pcons
-        $self->{built} = $self->{builder}->action($tgts->[0]);
-    }
-    else
-    {
-        {
-
-            # action now is non-blocking, so we must kludge blocking for this
-            # explicit call
-            local ($file::child_queue) = {parent => $tgts->[0]};    # pcons
-            $self->{built} = $self->{builder}->action($tgts->[0]);  # pcons
-            &file::wait_on_all_children();                          # pcons
-        }
-    }
-
-    # Now "build" all the other targets (except for the one
-    # we were called with). This guarantees that the signature
-    # of each target is updated appropriately. We force the
-    # targets to be built even if they have been previously
-    # considered and found to be OK; the only effect this
-    # has is to make sure that signature files are updated
-    # correctly.
-    for $tgt (@$tgts)
-    {
-        if ($tgt ne $invoked_tgt)
-        {
-            delete $tgt->{status};
-            'sig'->invalidate($tgt);
-            build $tgt;
-        }
-    }
-
-    # Status of action.
-    $self->{built};
-}
-
-package action;
-
-sub new
-{
-    my ($env, $act) = @_;
-    if (ref($act) eq 'CODE')
-    {
-        return action::perl->new($act);
-    }
-    else
-    {
-        return action::command->new($env, $act);
-    }
-}
-
-package action::command;
-
-use vars qw( @ISA %cmd %_varopts $_varletters );
-
-BEGIN
-{
-    @ISA = $main::_WIN32 ? 'action::command::win32' : 'action::command::unix';
-
-    # Internal hash for processing variable options.
-    # f: return file part
-    # d: return directory part
-    # F: return file part, but strip any suffix
-    # b: return full path, but strip any suffix (a.k.a. return basename)
-    # s: return only the suffix (or an empty string, if no suffix is there)
-    # a: return the absolute path to the file
-    # S: return the absolute path to a Linked source file
-    %_varopts = (
-        'f' => sub { return $_[0]->{entry}; },
-        'd' => sub { return $_[0]->{dir}->path; },
-        'F' => sub {
-            my $subst = $_[0]->{entry};
-            $subst =~ s/\.[^\.]+$//;
-            return $subst;
-        },
-        'b' => sub {
-            my $subst = $_[0]->path;
-            $subst =~ s/\.[^\.]+$//;
-            return $subst;
-        },
-        's' => sub {
-            my $subst = $_[0]->{entry};
-            $subst =~ m/(\.[^\.]+)$/;
-            return $1;
-        },
-        'a' => sub {
-            my $path = $_[0]->path;
-            if (!File::Spec->file_name_is_absolute($path))
-            {
-                $path = File::Spec->catfile(Cwd::cwd(), $path);
-            }
-            return $path;
-        },
-        'S' => sub {
-            my $path = $_[0]->srcpath;
-            if (!File::Spec->file_name_is_absolute($path))
-            {
-                my $cwd = File::Spec->canonpath(Cwd::cwd());
-                $path = File::Spec->catfile($cwd, $path);
-            }
-            return $path;
-        },
-        );
-
-    $_varletters = join ('', keys %_varopts);
-}
-
-# Internal routine for processing variable options.
-# Options are specified in hash in the BEGIN block above.
-# no option: return path to file (relative to top,
-# or absolute if it's outside)
-sub _variant
-{
-    my ($opt, $file) = @_;
-    $opt = '' if !defined $opt;
-    if (defined $_varopts{$opt})
-    {
-        return &{$_varopts{$opt}} ($file);
-    }
-    return $file->path;
-}
-
-sub new
-{
-    my ($class, $env, $cmd) = @_;
-    $cmd = $env->_subst($cmd);
-    $cmd{$env, $cmd} || do
-    {
-
-        # Remove unwanted bits from signature -- those bracketed by %( ... %)
-        my $sigs = $cmd;
-        my $sig  = '';
-        if (ref($sigs) eq 'ARRAY')
-        {
-
-            # This is an array of commands..
-            my $f;
-            foreach $f (@$sigs)
-            {
-                $sig .= _strip($f);
-            }
-        }
-        else
-        {
-            $sig = _strip($sigs);
-        }
-        my $self = {cmd => $cmd, cmdsig => 'sig'->cmdsig($sig)};
-        $cmd{$env, $cmd} = bless $self, $class;
-    };
-}
-
-sub _strip
-{
-    my $sig = shift;
-    $sig =~ s/^\@\s*//mg;
-    while ($sig =~ s/%\(([^%]|%[^\(])*?%\)//g) { }
-    $sig;
-}
-
-sub scriptsig
-{
-    $_[0]->{cmdsig};
-}
-
-# Return an array of all the commands (first word on each line).
-sub commands
-{
-    my ($self) = @_;
-    my (@cmds) = ();
-    my $com;
-    my $cmd = $self->{'cmd'};
-    my @allcoms;
-
-    push @allcoms, ref $cmd ? @{$cmd} : split (/\n/, $cmd);
-
-    for $com (@allcoms)
-    {
-        $com =~ s/^\s*//;
-        $com =~ s/\s.*//;
-        next if !$com;    # blank line
-        push @cmds, $com;
-    }
-    @cmds;
-}
-
-# For the signature of a basic command, we don't bother
-# including the command itself. This is not strictly correct,
-# and if we wanted to be rigorous, we might want to insist
-# that the command was checked for all the basic commands
-# like gcc, etc. For this reason we don't have an includes
-# method.
-
-# Call this to get the command line script: an array of
-# fully substituted commands.
-sub getcoms
-{
-    my ($self, $env, $tgt) = @_;
-    my (@coms);
-    my $com;
-    my @allcoms = ();
-    my $cmd     = $self->{'cmd'};
-
-    push @allcoms, ref $cmd ? @{$cmd} : split (/\n/, $cmd);
-
-    for $com (@allcoms)
-    {
-        my (@src) = (undef, @{$tgt->{sources}});
-        my (@src1) = @src;
-
-        next if $com =~ /^\s*$/;
-
-        # NOTE: we used to have a more elegant s//.../e solution
-        # for the items below, but this caused a bus error...
-
-        # Remove %( and %) -- those are only used to bracket parts
-        # of the command that we don't depend on.
-        $com =~ s/%[()]//g;
-
-        # Deal with %n, n=1,9 and variants.
-        while ($com =~ /%([1-9])(:([$_varletters]?))?/o)
-        {
-            my ($match) = $&;
-            my ($src)   = $src1[$1];
-            my ($subst) = _variant($3, $src1[$1]->rfile);
-            undef $src[$1];
-            $com =~ s/$match/$subst/;
-        }
-
-        # Deal with %0 aka %> and variants.
-        while ($com =~ /%[0>](:([$_varletters]?))?/o)
-        {
-            my ($match) = $&;
-            my ($subst) = _variant($2, $tgt);
-            $com =~ s/$match/$subst/;
-        }
-
-        # Deal with %< (all sources except %n's already used)
-        while ($com =~ /%<(:([$_varletters]?))?/o)
-        {
-            my ($match) = $&;
-            my @list = ();
-            foreach (@src)
-            {
-                push (@list, _variant($2, $_->rfile)) if $_;
-            }
-            my ($subst) = join (' ', @list);
-            $com =~ s/$match/$subst/;
-        }
-
-        # Deal with %[ %].
-        $com =~ s{%\[(.*?)%\]}{
-	    my($func, @args) = grep { $_ ne '' } split(/\s+/, $1);
-	    die("$0: \"$func\" is not defined.\n")
-		unless ($env->{$func});
-	    &{$env->{$func}}(@args);
-	}gex;
-
-        # Convert left-over %% into %.
-        $com =~ s/%%/%/g;
-
-        # White space cleanup. XXX NO WAY FOR USER TO HAVE QUOTED SPACES
-        $com = join (' ', split (' ', $com));
-        next if $com =~ /^:/ && $com !~ /^:\S/;
-        push (@coms, $com);
-    }
-    @coms;
-}
-
-# Build the target using the previously specified commands.
-sub execute
-{
-    my ($self, $env, $tgt, $package) = @_;
-
-    if ($param::build)
-    {
-        futil::mkdir($tgt->{dir});
-        unlink($tgt->path) if !$tgt->precious;
-    }
-
-    # Set environment.
-    map(delete $ENV{$_}, keys %ENV);
-    %ENV = %{$env->{ENV}};
-
-    # Handle multi-line commands.
-
-    my @cmds = $self->getcoms($env, $tgt);    # pcons
-    if ($param::max_jobs > 1)
-    {    # pcons
-        if ($#cmds > 0)
-        {
-            for ($i = 0 ; $i < @cmds ; $i++)
-            {    #pcons -kn
-                $cmds[$i] = "( " . $cmds[$i] . " )";    #pcons -kn
-            }    #pcons -kn
-            @cmds = join (" && ", @cmds);    # pcons
-        }    # pcons
-    }    # pcons
-
-    my $com;    # pcons
-    for $com (@cmds)
-    {           # pcons
-        if ($com !~ s/^\@\s*//)
-        {
-            main::showcom($com);
-        }
-        next if !$param::build;
-
-        if ($com =~ /^\[perl\]\s*/)
-        {
-            my $perlcmd = $';
-            my $status;
-            {
-
-                # Restore the script package variables that were defined
-                # in the Conscript file that defined this [perl] build,
-                # so the code executes with the expected variables.
-                # Then actually execute (eval) the [perl] command to build
-                # the target, followed by cleaning up the name space
-                # by deleting the package variables we just restored.
-                my ($pkgvars) = $tgt->{conscript}->{pkgvars};
-                NameSpace::restore($package, $pkgvars) if $pkgvars;
-                $status = eval "package $package; $perlcmd";
-                NameSpace::remove($package, keys %$pkgvars) if $pkgvars;
-            }
-            if (!defined($status))
-            {
-                warn "$0: *** Error during perl command eval: $@.\n";
-                return undef;
-            }
-            elsif ($status == 0)
-            {
-                warn "$0: *** Perl command returned $status "
-                  . "(this indicates an error).\n";
-                return undef;
-            }
-            next;
-        }
-        if (!$self->do_command($com, $tgt->path, $tgt))
-        {
-            return undef;
-        }
-    }
-
-    # success.
-    return 1;
-}
-
-sub show
-{
-    my ($self, $env, $tgt) = @_;
-    my $com;
-    for $com ($self->getcoms($env, $tgt))
-    {
-        if ($com !~ /^\@\s*/)
-        {
-            main::showcom($com);
-        }
-    }
-}
-
-package action::command::unix;
-
-sub do_command
-{
-    my ($class, $com, $path) = @_;    # cons
-    my ($class, $com, $path, $tgt) = @_;    # pcons
-
-    if ($param::max_jobs > 1)
-    {    # pcons
-        &file::wait_on_max_jobs();    # pcons
-    }    # pcons
-    my ($pid) = fork();
-    die ("$0: unable to fork child process ($!)\n") if !defined $pid;
-    if (!$pid)
-    {
-
-        # This is the child.  We eval the command to suppress -w
-        # warnings about not reaching the statements afterwards.
-        eval 'exec($com)';
-        $com =~ s/\s.*//;
-        die qq($0: failed to execute "$com" ($!). )
-          . qq(Is this an executable on path "$ENV{PATH}"?\n);
-    }
-    if ($param::max_jobs <= 1)
-    {    # pcons
-        for (; ;)
-        {
-            do { } until wait() == $pid;
-            my ($b0, $b1) = ($? & 0xFF, $? >> 8);
-
-            # Don't actually see 0177 on stopped process; is this necessary?
-            next if $b0 == 0177;    # process stopped; we can wait.
-            if ($b0)
-            {
-                my ($core, $sig) = ($b0 & 0200, $b0 & 0177);
-                my ($coremsg) = $core ? "; core dumped" : "";
-                $com =~ s/\s.*//;
-                my $err =
-                  "$0: *** \[$path\] $com terminated by signal "
-                  . "$sig$coremsg\n";
-                warn $err;
-                return undef;
-            }
-            if ($b1)
-            {
-                warn qq($0: *** [$path] Error $b1\n);  # trying to be like make.
-                return undef;
-            }
-            last;
-        }
-    }
-    else
-    {    # pcons
-        $file::child_queue->{$pid}->{com} = $com;    # pcons
-        $file::child_queue->{$pid}->{tgt} = $tgt;    # pcons
-
-    }    # pcons
-
-    return 1;
-}
-
-package action::command::win32;
-
-sub do_command
-{
-    my ($class, $com, $path, $tgt) = @_;
-    system($com);
-    if ($?)
-    {
-        my ($b0, $b1) = ($? & 0xFF, $? >> 8);
-        my $err = $b1 || $?;
-        my $warn = qq($0: *** [$path] Error $err);
-        $warn .= " (executable not found in path?)" if $b1 == 0xFF;
-        warn "$warn\n";
-        return undef;
-    }
-    return 1;
-}
-
-package action::perl;
-
-# THIS IS AN EXPERIMENTAL PACKAGE.  It's entirely possible that the
-# interface may change as this gets completed, so use at your own risk.
-#
-# There are (at least) two issues that need to be solved before blessing
-# this as a real, fully-supported feature:
-#
-#   --	We need to calculate a signature value for a Perl code ref, in
-#	order to rebuild the target if there's a change to the Perl code
-#	used to generate it.
-#
-#	This is not straightforward.  A B::Deparse package exists that
-#	decompiles a coderef into text.  It's reportedly not completely
-#	reliable for closures; it misses which variables are global, and
-#	the values of private lexicals.  Nevertheless, it'd probably
-#	be perfect for our purposes, except that it wasn't added until
-#	some time between Perl 5.00502 and 5.00554, and doesn't seem to
-#	really work until Perl 5.6.0, so by relying on it, we'd lose
-#	support for Perl versions back to 5.003*.
-#
-#   --	Ideally, a code ref should be able to use something like
-#	$env->_subst to fetch values from the construction environment
-#	to modify its behavior without having to cut-and-paste code.
-#	(Actually, since we pass the environment to the executed code
-#	ref, there's no reason you can't do this with the code as it
-#	stands today.)  But this REALLY complicates the signature
-#	calculation, because now the actual signature would depend not
-#	just on the code contents, but on the construction variables (or
-#	maybe just the environment).
-#
-# A potentially valid workaround would be to use the contents of the
-# Conscript file in which the code reference is defined as the code
-# ref's signature.  This has the drawback of causing a recompilation of
-# the target file even in response to unrelated changes in the Conscript
-# file, but it would ensure correct builds without having to solve the
-# messy issues of generating a signature directly from a code ref.
-#
-# Nevertheless, this seemed a useful enough skeleton of a feature that
-# it made sense to release it in hopes that some practical experience
-# will encourage someone to figure out how to solve the signature
-# issues.  Or maybe we'll discover these aren't big issues in practice
-# and end up blessing it as is.
-
-use vars qw( %code );
-
-sub new
-{
-    my ($class, $cref) = @_;
-    $code{$cref} || do
-    {
-        my $sig = '';
-
-        # Generating a code signature using B::Deparse doesn't really
-        # work for us until Perl 5.6.0.  Here's the code in case
-        # someone wants to use it.
-        #use B::Deparse;
-        #my $deparse = B::Deparse->new();
-        #my $body = $deparse->coderef2text($cref);
-        #$sig = $body;	# should be an MD5 sig
-        my ($self) = {cref => $cref, crefsig => $sig};
-        $code{$cref} = bless $self, $class;
-      }
-}
-
-sub scriptsig
-{
-    $_[0]->{crefsig};
-}
-
-sub execute
-{
-    my ($self, $env, $tgt) = @_;
-    if ($param::build)
-    {
-        futil::mkdir($tgt->{dir});
-        unlink($tgt->path) if !$tgt->precious;
-        my ($cref) = $self->{cref};
-        &$cref($env, $tgt->path, map($_->rpath, @{$tgt->{sources}}));
-    }
-}
-
-sub commands
-{
-    return ();
-}
-
-# Generic scanning module.
-package scan;
-
-# Returns the signature of files included by the specified files on
-# behalf of the associated target. Any errors in handling the included
-# files are propagated to the target on whose behalf this processing
-# is being done. Signatures are cached for each unique file/scanner
-# pair.
-sub includes
-{
-    my ($self, $tgt, @files) = @_;
-    my (%files, $file);
-    my ($inc) = $self->{includes} || ($self->{includes} = {});
-    while ($file = pop @files)
-    {
-        next if exists $files{$file};
-        if ($inc->{$file})
-        {
-            push (@files, @{$inc->{$file}});
-            $files{$file} = 'sig'->signature($file->rfile);
-        }
-        else
-        {
-            if ((build $file) eq 'errors')
-            {
-                $tgt->{status} = 'errors';    # tgt inherits build status
-                return ();
-            }
-            $files{$file} = 'sig'->signature($file->rfile);
-            my (@includes) = $self->scan($file);
-            $inc->{$file} = \@includes;
-            push (@files, @includes);
-        }
-    }
-    'sig'->collect(sort values %files);
-}
-
-# A simple scanner. This is used by the QuickScanfunction, to setup
-# one-time target and environment-independent scanning for a source
-# file. Only used for commands run by the Command method.
-package scan::quickscan;
-
-use vars qw( @ISA %scanner );
-
-BEGIN { @ISA = qw(scan) }
-
-sub find
-{
-    my ($class, $code, $env, $pdirs) = @_;
-    if (!defined $pdirs)
-    {
-        $pdirs = [];
-    }
-    elsif (ref($pdirs) ne 'ARRAY')
-    {
-        $pdirs = [split (/$main::PATH_SEPARATOR/o, $pdirs)];
-    }
-    my (@path) = map { $dir::cwd->lookupdir($_) } @$pdirs;
-    my ($spath) = "@path";
-    $scanner{$code, $env, $spath} || do
-    {
-        my ($self) = {code => $code, env => $env, path => \@path};
-        $scanner{$code, $env, $spath} = bless $self;
-      }
-}
-
-# Scan the specified file for included file names.
-sub scan
-{
-    my ($self, $file) = @_;
-    my ($code) = $self->{code};
-    my (@includes);
-
-    # File should have been built by now. If not, we'll ignore it.
-    return () unless open(SCAN, $file->rpath);
-    while (<SCAN>)
-    {
-        push (@includes, grep($_ ne '', &$code));
-    }
-    close(SCAN);
-    my ($wd) = $file->{dir};
-    my (@files);
-    my $name;
-    for $name (@includes)
-    {
-        my $dir;
-        for $dir ($file->{dir}, @{$self->{path}})
-        {
-            my ($include) = $dir->lookup_accessible($name);
-            if ($include)
-            {
-                push (@files, $include) unless $include->ignore;
-                last;
-            }
-        }
-    }
-    @files;
-}
-
-# CPP (C preprocessor) scanning module
-package scan::cpp;
-
-use vars qw( @ISA %scanner );
-
-BEGIN { @ISA = qw(scan) }
-
-# For this constructor, provide the include path argument (colon
-# separated). Each path is taken relative to the provided directory.
-
-# Note: a particular scanning object is assumed to always return the
-# same result for the same input. This is why the search path is a
-# parameter to the constructor for a CPP scanning object. We go to
-# some pains to make sure that we return the same scanner object
-# for the same path: otherwise we will unecessarily scan files.
-sub find
-{
-    my ($class, $dir, $pdirs) = @_;
-    if (!defined $pdirs)
-    {
-        $pdirs = [];
-    }
-    elsif (ref($pdirs) ne 'ARRAY')
-    {
-        $pdirs = [split (/$main::PATH_SEPARATOR/o, $pdirs)];
-    }
-    my @path = map($dir->lookupdir($_), @$pdirs);
-    my ($spath) = "@path";
-    $scanner{$spath} || do
-    {
-        my ($self) = {'path' => \@path};
-        $scanner{$spath} = bless $self;
-      }
-}
-
-# Scan the specified file for include lines.
-sub scan
-{
-    my ($self, $file) = @_;
-    my ($angles, $quotes);
-
-    if (exists $file->{angles})
-    {
-        $angles = $file->{angles};
-        $quotes = $file->{quotes};
-    }
-    else
-    {
-        my (@anglenames, @quotenames);
-        return () unless open(SCAN, $file->rpath);
-        while (<SCAN>)
-        {
-            next unless /^\s*#/;
-            if (/^\s*#\s*include\s*([<"])(.*?)[>"]/)
-            {
-                if ($1 eq "<")
-                {
-                    push (@anglenames, $2);
-                }
-                else
-                {
-                    push (@quotenames, $2);
-                }
-            }
-        }
-        close(SCAN);
-        $angles = $file->{angles} = \@anglenames;
-        $quotes = $file->{quotes} = \@quotenames;
-    }
-
-    my (@shortpath) = @{$self->{path}};             # path for <> style includes
-    my (@longpath)  = ($file->{dir}, @shortpath);   # path for "" style includes
-
-    my (@includes);
-
-    my $name;
-    for $name (@$angles)
-    {
-        my $dir;
-        for $dir (@shortpath)
-        {
-            my ($include) = $dir->lookup_accessible($name);
-            if ($include)
-            {
-                push (@includes, $include) unless $include->ignore;
-                last;
-            }
-        }
-    }
-
-    for $name (@$quotes)
-    {
-        my $dir;
-        for $dir (@longpath)
-        {
-            my ($include) = $dir->lookup_accessible($name);
-            if ($include)
-            {
-                push (@includes, $include) unless $include->ignore;
-                last;
-            }
-        }
-    }
-
-    return @includes;
-}
-
-# Return the include flags that would be used for a C Compile.
-sub iflags
-{
-    my ($self, $env) = @_;
-    my ($iflags) = '';
-    my ($dir, $dpath);
-    for $dir (@{$self->{path}})
-    {
-        $dpath = $dir->path;
-
-        # Add the (presumably local) directory to the -I flags
-        # if we're not using repositories, the directory exists,
-        # or it's Linked to a source directory (that is, it *will*
-        # exist by the time the compilation occurs).
-        $iflags .= " " . $env->{INCDIRPREFIX} . $dpath . $env->{INCDIRSUFFIX}
-          if !@param::rpath || -d $dpath || $dir->is_linked;
-        next if File::Spec->file_name_is_absolute($dpath);
-        if (@param::rpath)
-        {
-            my $d;
-            if ($dpath eq $dir::CURDIR)
-            {
-                foreach $d (map($_->path, @param::rpath))
-                {
-                    $iflags .=
-                      " " . $env->{INCDIRPREFIX} . $d . $env->{INCDIRSUFFIX};
-                }
-            }
-            else
-            {
-                my ($rpath);
-                foreach $d (map($_->path, @param::rpath))
-                {
-                    $rpath = File::Spec->catfile($d, $dpath);
-                    $iflags .=
-                      " " . $env->{INCDIRPREFIX} . $rpath . $env->{INCDIRSUFFIX}
-                      if -d $rpath;
-                }
-            }
-        }
-    }
-    $iflags;
-}
-
-package File::Spec;
-
-use vars qw( $_SEP $_MATCH_SEP $_MATCH_VOL );
-
-# Cons is migrating to using File::Spec for portable path name
-# manipulation.  This is the right long-term direction, but there are
-# some problems with making the transition:
-#
-#	For multi-volume support, we need to use newer interfaces
-#	(splitpath, catpath, splitdir) that are only available in
-#	File::Spec 0.8.
-#
-#	File::Spec 0.8 doesn't work with Perl 5.00[34] due to
-#	regular expression incompatibilities (use of \z).
-#
-#	Forcing people to use a new version of a module is painful
-#	because (in the workplace) their administrators aren't
-#	always going to agree to install it everywhere.
-#
-# As a middle ground, we provide our own versions of all the File::Spec
-# methods we use, supporting both UNIX and Win32.  Some of these methods
-# are home brew, some are cut-and-pasted from the real File::Spec methods.
-# This way, we're not reinventing the whole wheel, at least.
-#
-# We can (and should) get rid of this class whenever 5.00[34] and
-# versions of File::Spec prior to 0.9 (?) have faded sufficiently.
-# We also may need to revisit whenever someone first wants to use
-# Cons on some platform other than UNIX or Win32.
-
-BEGIN
-{
-    if ($main::_WIN32)
-    {
-        $_SEP       = '\\';
-        $_MATCH_SEP = "[\Q/$_SEP\E]";
-        $_MATCH_VOL = "([a-z]:)?$_MATCH_SEP";
-    }
-    else
-    {
-        $_SEP       = '/';
-        $_MATCH_SEP = "\Q$_SEP\E";
-        $_MATCH_VOL = $_MATCH_SEP;
-    }
-}
-
-sub canonpath
-{
-    my ($self, $path) = @_;
-    if ($main::_WIN32)
-    {
-        $path =~ s/^([a-z]:)/\u$1/s;
-        $path =~ s|/|\\|g;
-        $path =~ s|([^\\])\\+|$1\\|g;                       # xx////xx  -> xx/xx
-        $path =~ s|(\\\.)+\\|\\|g;                          # xx/././xx -> xx/xx
-        $path =~ s|^(\.\\)+||s unless $path eq ".\\";       # ./xx      -> xx
-        $path =~ s|\\$|| unless $path =~ m#^([A-Z]:)?\\$#s; # xx/       -> xx
-    }
-    else
-    {
-        $path =~ s|/+|/|g unless ($^O eq 'cygwin');    # xx////xx  -> xx/xx
-        $path =~ s|(/\.)+/|/|g;                        # xx/././xx -> xx/xx
-        $path =~ s|^(\./)+||s unless $path eq "./";    # ./xx      -> xx
-        $path =~ s|^/(\.\./)+|/|s;                     # /../../xx -> xx
-        $path =~ s|/$|| unless $path eq "/";           # xx/       -> xx
-    }
-    return $path;
-}
-
-sub catdir
-{
-    my $self = shift;
-    my @args = @_;
-    foreach (@args)
-    {
-
-        # append a slash to each argument unless it has one there
-        $_ .= $_SEP if $_ eq '' || substr($_, -1) ne $_SEP;
-    }
-    return $self->canonpath(join ('', @args));
-}
-
-sub catfile
-{
-    my $self = shift;
-    my $file = pop @_;
-    return $file unless @_;
-    my $dir = $self->catdir(@_);
-    $dir .= $_SEP unless substr($dir, -1) eq $_SEP;
-    $file = '' if !defined($file);
-    return $dir . $file;
-}
-
-sub catpath
-{
-    my $path = $_[1] . $_[0]->catfile(@_[2 .. $#_]);
-    $path =~ s/(.)$_MATCH_SEP*$/$1/;
-    $path;
-}
-
-sub curdir
-{
-    '.';
-}
-
-sub file_name_is_absolute
-{
-    my ($self, $file) = @_;
-    return scalar($file =~ m{^$_MATCH_VOL}is);
-}
-
-sub splitdir
-{
-    my @dirs = split (/$_MATCH_SEP/, $_[1], -1);
-    push (@dirs, '') if $dirs[$#dirs];
-    @dirs;
-}
-
-sub splitpath
-{
-    my ($self, $path) = @_;
-    my $vol = '';
-    my $sep = $_SEP;
-    if ($main::_WIN32)
-    {
-        if ($path =~ s#^([A-Za-z]:|(?:\\\\|//)[^\\/]+[\\/][^\\/]+)([\\/])#$2#)
-        {
-            $vol = $1;
-            $sep = $2;
-        }
-    }
-    my (@path) = split (/$_MATCH_SEP/, $path, -1);
-    my $file = pop @path;
-    my $dirs = join ($sep, @path, '');
-    return ($vol, $dirs, $file);
-}
-
-sub updir
-{
-    '..';
-}
-
-sub case_tolerant
-{
-    return $main::_WIN32;
-}
-
-# Directory and file handling. Files/dirs are represented by objects.
-# Other packages are welcome to add component-specific attributes.
-package dir;
-
-use vars qw( $SEPARATOR $MATCH_SEPARATOR $CURDIR $UPDIR
-  $cwd_vol %root $top $cwd );
-
-BEGIN
-{
-
-    # A portable way of determing our directory separator.
-    $SEPARATOR = File::Spec->catdir('', '');
-
-    # A fast-path regular expression to match a directory separator
-    # anywhere in a path name.
-    if ($SEPARATOR eq '/')
-    {
-        $MATCH_SEPARATOR = "\Q$SEPARATOR\E";
-    }
-    else
-    {
-        $MATCH_SEPARATOR = "[\Q/$SEPARATOR\E]";
-    }
-
-    # Cache these values so we don't have to make a method call
-    # every time we need them.
-    $CURDIR  = File::Spec->curdir;    # '.' on UNIX
-    $UPDIR   = File::Spec->updir;     # '..' on UNIX
-                                      #
-    $cwd_vol = '';
-}
-
-# Annotate a node (file or directory) with info about the
-# method that created it.
-sub creator
-{
-    my ($self, @frame) = @_;
-    $self->{'creator'} = \@frame if @frame;
-    $self->{'creator'};
-}
-
-# Handle a file|dir type exception.  We only die if we find we were
-# invoked by something in a Conscript/Construct file, because
-# dependencies created directly by Cons' analysis shouldn't cause
-# an error.
-sub _type_exception
-{
-    my ($e) = @_;
-    my ($line, $sub);
-    (undef, undef, $line, $sub) = script::caller_info;
-    if (defined $line)
-    {
-        my $err =
-          "\"${\$e->path}\" already in use as a "
-          . ref($e)
-          . " before $sub on line $line";
-        if ($e->{'creator'})
-        {
-            my $script;
-            (undef, $script, $line, $sub) = @{$e->{'creator'}};
-            $err =
-              "\t" . $err . ",\n\t\tdefined by $sub in $script, line $line";
-        }
-        $err .= "\n";
-        die $err;
-    }
-}
-
-# This wraps up all the common File::Spec logic that we use for parsing
-# directory separators in a path and turning it into individual
-# subdirectories that we must create, as well as creation of root
-# nodes for any new file system volumes we find.  File::Spec doesn't have
-# intuitively obvious interfaces, so this is heavily commented.
-#
-# Note:  This is NOT an object or class method;
-# it's just a utility subroutine.
-sub _parse_path
-{
-    my ($dir, $path) = @_;
-
-    # Convert all slashes to the native directory separator.
-    # This allows Construct files to always be written with good
-    # old POSIX path names, regardless of what we're running on.
-    $path = File::Spec->canonpath($path);
-
-    # File::Spec doesn't understand the Cons convention of
-    # an initial '#' for top-relative files.  Strip it.
-    my ($toprel) = $path =~ s/^#//;
-
-    # Let File::Spec do the heavy lifting of parsing the path name.
-    my ($vol, $directories, $entry) = File::Spec->splitpath($path);
-    my @dirs = File::Spec->splitdir($directories);
-
-    # If there was a file entry on the end of the path, then the
-    # last @dirs element is '' and we don't need it.  If there
-    # wasn't a file entry on the end (File::Spec->splitpath() knew
-    # the last component was a directory), then the last @dirs
-    # element becomes the entry we want to look up.
-    my ($e) = pop @dirs;
-    $entry = $e if $entry eq '';
-
-    if (File::Spec->file_name_is_absolute($path))
-    {
-
-        # An absolute path name.  If no volume was supplied,
-        # use the volume of our current directory.
-        $vol = $cwd_vol if $vol eq '';
-        $vol = uc($vol) if File::Spec->case_tolerant;
-        if (!defined $root{$vol})
-        {
-
-            # This is our first time looking up a path name
-            # on this volume, so create a root node for it.
-            # (On UNIX systems, $vol is always '', so '/'
-            # always maps to the $root{''} node.)
-            $root{$vol} = {
-                            path     => $vol . $SEPARATOR,
-                            prefix   => $vol . $SEPARATOR,
-                            srcpath  => $vol . $SEPARATOR,
-                            'exists' => 1
-                            };
-            $root{$vol}->{'srcdir'} = $root{$vol};
-            bless $root{$vol};
-        }
-
-        # We're at the top, so strip the blank entry from the front of
-        # the @dirs array since the initial '/' it represents will now
-        # be supplied by the root node we return.
-        shift @dirs;
-        $dir = $root{$vol};
-    }
-    elsif ($toprel)
-    {
-        $dir = $dir::top;
-    }
-    ($dir, \@dirs, $entry);
-}
-
-# Common subroutine for creating directory nodes.
-sub _create_dirs
-{
-    my ($dir, @dirs) = @_;
-    my $e;
-    foreach $e (@dirs)
-    {
-        my $d = $dir->{member}->{$e};
-        if (!defined $d)
-        {
-            bless $d = {'entry' => $e, 'dir' => $dir,}, 'dir';
-            $d->creator(script::caller_info);
-            $d->{member}->{$dir::CURDIR} = $d;
-            $d->{member}->{$dir::UPDIR}  = $dir;
-            $dir->{member}->{$e}         = $d;
-        }
-        elsif (ref $d eq 'entry')
-        {
-            bless $d, 'dir';
-            $d->{member}->{$dir::CURDIR} = $d;
-            $d->{member}->{$dir::UPDIR}  = $dir;
-        }
-        elsif (ref $d eq 'file')
-        {
-
-            # This clause is to supply backwards compatibility,
-            # with a warning, for anyone that's used FilePath
-            # to refer to a directory.  After people have using
-            # 1.8 have had time to adjust (sometime in version
-            # 1.9 or later), we should remove this entire clause.
-            my ($script, $line, $sub);
-            (undef, $script, $line, $sub) = @{$d->{'creator'}};
-            if ($sub eq 'script::FilePath')
-            {
-                print STDERR
-                  "$0:  Warning:  $sub used to refer to a directory\n"
-                  . "\tat line $line of $script.  Use DirPath instead.\n";
-                bless $d, 'dir';
-            }
-            else
-            {
-                _type_exception($d);
-            }
-        }
-        elsif (ref $d ne 'dir')
-        {
-            _type_exception($d);
-        }
-        $dir = $d;
-    }
-    $dir;
-}
-
-# Look up an entry in a directory.  This method is for when we don't
-# care whether a file or directory is returned, so if the entry already
-# exists, it will simply be returned.  If not, we create it as a
-# generic "entry" which can be later turned into a file or directory
-# by a more-specific lookup.
-#
-# The file entry may be specified as relative, absolute (starts with /),
-# or top-relative (starts with #).
-sub lookup
-{
-    my ($dir, $entry) = @_;
-
-    if ($entry !~ m#$MATCH_SEPARATOR#o)
-    {
-
-        # Fast path: simple entry name in a known directory.
-        if ($entry =~ s/^#//)
-        {
-
-            # Top-relative names begin with #.
-            $dir = $dir::top;
-        }
-        elsif ($entry =~ s/^!//)
-        {
-            $dir = $dir::cwd->srcdir;
-        }
-    }
-    else
-    {
-        my $dirsref;
-        ($dir, $dirsref, $entry) = _parse_path($dir, $entry);
-        $dir = _create_dirs($dir, @$dirsref) if @$dirsref;
-        return if !defined $dir;
-        return $dir if $entry eq '';
-    }
-
-    my $e = $dir->{member}->{$entry};
-    if (!defined $e)
-    {
-        bless $e = {'entry' => $entry, 'dir' => $dir,}, 'entry';
-        $e->creator(script::caller_info);
-        $dir->{member}->{$entry} = $e;
-    }
-
-    $e;
-}
-
-# Look up a file entry in a directory.
-#
-# The file entry may be specified as relative, absolute (starts with /),
-# or top-relative (starts with #).
-sub lookupfile
-{
-    my ($dir, $entry) = @_;
-
-    if ($entry !~ m#$MATCH_SEPARATOR#o)
-    {
-
-        # Fast path: simple entry name in a known directory.
-        if ($entry =~ s/^#//)
-        {
-
-            # Top-relative names begin with #.
-            $dir = $dir::top;
-        }
-        elsif ($entry =~ s/^!//)
-        {
-            $dir = $dir::cwd->srcdir;
-        }
-    }
-    else
-    {
-        my $dirsref;
-        ($dir, $dirsref, $entry) = _parse_path($dir, $entry);
-        $dir = _create_dirs($dir, @$dirsref) if @$dirsref;
-        return undef if $entry eq '';
-    }
-
-    my $f = $dir->{member}->{$entry};
-    if (!defined $f)
-    {
-        bless $f = {'entry' => $entry, 'dir' => $dir,}, 'file';
-        $f->creator(script::caller_info);
-        $dir->{member}->{$entry} = $f;
-    }
-    elsif (ref $f eq 'entry')
-    {
-        bless $f, 'file';
-    }
-    elsif (ref $f ne 'file')
-    {
-        _type_exception($f);
-    }
-
-    $f;
-}
-
-# Look up a (sub-)directory entry in a directory.
-#
-# The (sub-)directory entry may be specified as relative, absolute
-# (starts with /), or top-relative (starts with #).
-sub lookupdir
-{
-    my ($dir, $entry) = @_;
-
-    my $dirsref;
-    if ($entry !~ m#$MATCH_SEPARATOR#o)
-    {
-
-        # Fast path: simple entry name in a known directory.
-        if ($entry =~ s/^#//)
-        {
-
-            # Top-relative names begin with #.
-            $dir = $dir::top;
-        }
-        elsif ($entry =~ s/^!//)
-        {
-            $dir = $dir::cwd->srcdir;
-        }
-    }
-    else
-    {
-        ($dir, $dirsref, $entry) = _parse_path($dir, $entry);
-    }
-    push (@$dirsref, $entry) if $entry ne '';
-    _create_dirs($dir, @$dirsref);
-}
-
-# Look up a file entry and return it if it's accessible.
-sub lookup_accessible
-{
-    my $file = $_[0]->lookupfile($_[1]);
-    return ($file && $file->accessible) ? $file : undef;
-}
-
-# Return the parent directory without doing a lookupdir,
-# which would create a parent if it doesn't already exist.
-# A return value of undef (! $dir->up) indicates a root directory.
-sub up
-{
-    $_[0]->{member}->{$dir::UPDIR};
-}
-
-# Return whether this is an entry somewhere underneath the
-# specified directory.
-sub is_under
-{
-    my $dir = $_[0];
-    while ($dir)
-    {
-        return 1 if $_[1] == $dir;
-        $dir = $dir->up;
-    }
-    return undef;
-}
-
-# Return the relative path from the calling directory ($_[1])
-# to the object.  If the object is not under the directory, then
-# we return it as a top-relative or absolute path name.
-sub relpath
-{
-    my ($dir, $obj) = @_;
-    my @dirs;
-    my $o = $obj;
-    while ($o)
-    {
-        if ($dir == $o)
-        {
-            if (@dirs < 2)
-            {
-                return $dirs[0] || '';
-            }
-            else
-            {
-                return File::Spec->catdir(@dirs);
-            }
-        }
-        unshift (@dirs, $o->{entry});
-        $o = $o->up;
-    }
-
-    # The object was not underneath the specified directory.
-    # Use the node's cached path, which is either top-relative
-    # (in which case we append '#' to the beginning) or
-    # absolute.
-    my $p = $obj->path;
-    $p = '#' . $p if !File::Spec->file_name_is_absolute($p);
-    return $p;
-}
-
-# Return the path of the directory (file paths implemented
-# separately, below).
-sub path
-{
-    $_[0]->{path} || ($_[0]->{path} = $_[0]->{dir}->prefix . $_[0]->{entry});
-}
-
-# Return the pathname as a prefix to be concatenated with an entry.
-sub prefix
-{
-    return $_[0]->{prefix} if exists $_[0]->{prefix};
-    $_[0]->{prefix} = $_[0]->path . $SEPARATOR;
-}
-
-# Return the related source path prefix.
-sub srcprefix
-{
-    return $_[0]->{srcprefix} if exists $_[0]->{srcprefix};
-    my ($srcdir) = $_[0]->srcdir;
-    $srcdir->{srcprefix} =
-      $srcdir eq $_[0] ? $srcdir->prefix : $srcdir->srcprefix;
-}
-
-# Return the related source directory.
-sub srcdir
-{
-    $_[0]->{'srcdir'}
-      || ($_[0]->{'srcdir'} = $_[0]->{dir}->srcdir->lookupdir($_[0]->{entry}));
-}
-
-# Return if the directory is linked to a separate source directory.
-sub is_linked
-{
-    return $_[0]->{is_linked} if defined $_[0]->{is_linked};
-    $_[0]->{is_linked} = $_[0]->path ne $_[0]->srcdir->path;
-}
-
-sub link
-{
-    my (@paths)  = @_;
-    my ($srcdir) = $dir::cwd->lookupdir(pop @paths)->srcdir;
-    map($dir::cwd->lookupdir($_)->{'srcdir'} = $srcdir, @paths);
-
-    # make a reverse lookup for the link.
-    $srcdir->{links} = [] if !$srcdir->{links};
-    push @{$srcdir->{links}}, @paths;
-}
-
-use vars qw( @tail );    # TODO: Why global ????
-
-sub linked_targets
-{
-    my $tgt     = shift;
-    my @targets = ();
-    my $dir;
-    if (ref $tgt eq 'dir')
-    {
-        $dir = $tgt;
-    }
-    else
-    {
-        push @tail, $tgt;
-        $dir = $tgt->{dir};
-    }
-    while ($dir)
-    {
-        if (defined $dir->{links} && @{$dir->{links}})
-        {
-            push @targets, map(File::Spec->catdir($_, @tail), @{$dir->{links}});
-
-            #print STDERR "Found Link: ${\$dir->path} -> @{\$dir->{links}}\n";
-        }
-        unshift @tail, $dir->{entry};
-        $dir = $dir->up;
-    }
-
-    return map($dir::top->lookupdir($_), @targets);
-}
-
-sub accessible
-{
-    my $path = $_[0]->path;
-    my $err  =
-      "$0: you have attempted to use path \"$path\" both as a file "
-      . "and as a directory!\n";
-    die $err;
-}
-
-sub init
-{
-    my $path = Cwd::cwd();
-
-    # We know we can get away with passing undef to lookupdir
-    # as the directory because $dir is an absolute path.
-    $top = lookupdir(undef, $path);
-    $top->{'path'} = $top->{srcpath} = $dir::CURDIR;
-    $top->{'prefix'} = '';
-    $top->{'srcdir'} = $top;
-
-    $cwd = $top;
-
-    ($cwd_vol, undef, undef) = File::Spec->splitpath($path);
-    $cwd_vol = '' if !defined $cwd_vol;
-    $cwd_vol = uc($cwd_vol) if File::Spec->case_tolerant;
-}
-
-package file;
-
-use vars qw( @ISA $level );
-
-BEGIN { @ISA = qw(dir); $level = 0 }
-
-# Return the pathname of the file.
-# Define this separately from dir::path because we don't want to
-# cache all file pathnames (just directory pathnames).
-sub path
-{
-    $_[0]->{dir}->prefix . $_[0]->{entry};
-}
-
-# Return the related source file path.
-sub srcpath
-{
-    $_[0]->{dir}->srcprefix . $_[0]->{entry};
-}
-
-# Return if the file is (should be) linked to a separate source file.
-sub is_linked
-{
-    $_[0]->{dir}->is_linked;
-}
-
-# Repository file search.  If the local file exists, that wins.
-# Otherwise, return the first existing same-named file under a
-# Repository directory.  If there isn't anything with the same name
-# under a Repository directory, return the local file name anyway
-# so that some higher layer can try to construct it.
-sub rfile
-{
-    return $_[0]->{rfile} if exists $_[0]->{rfile};
-    my ($self)  = @_;
-    my ($rfile) = $self;
-    if (@param::rpath)
-    {
-        my ($path) = $self->path;
-        if (!File::Spec->file_name_is_absolute($path) && !-f $path)
-        {
-            my ($dir);
-            foreach $dir (@param::rpath)
-            {
-                my ($t) = $dir->prefix . $path;
-                if (-f $t)
-                {
-                    $rfile = $_[0]->lookupfile($t);
-                    $rfile->{'lfile'} = $self;
-                    last;
-                }
-            }
-        }
-    }
-    $self->{rfile} = $rfile;
-}
-
-# Returns the local file for a repository file;
-# returns self if it's already a local file.
-sub lfile
-{
-    $_[0]->{'lfile'} || $_[0];
-}
-
-# returns the "precious" status of this file.
-sub precious
-{
-    return $_[0]->{precious};
-}
-
-# "Erase" reference to a Repository file,
-# making this a completely local file object
-# by pointing it back to itself.
-sub no_rfile
-{
-    $_[0]->{'rfile'} = $_[0];
-}
-
-# Return a path to the first existing file under a Repository directory,
-# implicitly returning the current file's path if there isn't a
-# same-named file under a Repository directory.
-sub rpath
-{
-    $_[0]->{rpath} || ($_[0]->{rpath} = $_[0]->rfile->path);
-}
-
-# Return a path to the first linked srcpath file under a Repositoy
-# directory, implicitly returning the current file's srcpath if there
-# isn't a same-named file under a Repository directory.
-sub rsrcpath
-{
-    return $_[0]->{rsrcpath} if exists $_[0]->{rsrcpath};
-    my ($self) = @_;
-    my ($path) = $self->{rsrcpath} = $self->srcpath;
-    if (@param::rpath && !File::Spec->file_name_is_absolute($path) && !-f $path)
-    {
-        my ($dir);
-        foreach $dir (@param::rpath)
-        {
-            my ($t) = $dir->prefix . $path;
-            if (-f $t)
-            {
-                $self->{rsrcpath} = $t;
-                last;
-            }
-        }
-    }
-    $self->{rsrcpath};
-}
-
-# Return if a same-named file source file exists.
-# This handles the interaction of Link and Repository logic.
-# As a side effect, it will link a source file from its Linked
-# directory (preferably local, but maybe in a repository)
-# into a build directory from its proper Linked directory.
-sub source_exists
-{
-    return $_[0]->{source_exists} if defined $_[0]->{source_exists};
-    my ($self) = @_;
-    my ($path) = $self->path;
-    my ($mtime, $ctime) = (stat($path))[9, 10];
-    if ($self->is_linked)
-    {
-
-        # Linked directory, local logic.
-        my ($srcpath) = $self->srcpath;
-        my ($src_mtime, $src_ctime) = (stat($srcpath))[9, 10];
-        if ($src_mtime)
-        {
-            if (!$mtime || $src_mtime != $mtime || $src_ctime != $ctime)
-            {
-                futil::install($srcpath, $self);
-            }
-            return $self->{source_exists} = 1;
-        }
-
-        # Linked directory, repository logic.
-        if (@param::rpath)
-        {
-            if ($self != $self->rfile)
-            {
-                return $self->{source_exists} = 1;
-            }
-            my ($rsrcpath) = $self->rsrcpath;
-            if ($path ne $rsrcpath)
-            {
-                my ($rsrc_mtime, $rsrc_ctime) = (stat($rsrcpath))[9, 10];
-                if ($rsrc_mtime)
-                {
-                    if (!$mtime
-                        || $rsrc_mtime != $mtime
-                        || $rsrc_ctime != $ctime)
-                    {
-                        futil::install($rsrcpath, $self);
-                    }
-                    return $self->{source_exists} = 1;
-                }
-            }
-        }
-
-        # There was no source file in any Linked directory
-        # under any Repository.  If there's one in the local
-        # build directory, it no longer belongs there.
-        if ($mtime)
-        {
-            unlink($path) || die ("$0: couldn't unlink $path ($!)\n");
-        }
-        return $self->{source_exists} = '';
-    }
-    else
-    {
-        if ($mtime)
-        {
-            return $self->{source_exists} = 1;
-        }
-        if (@param::rpath && $self != $self->rfile)
-        {
-            return $self->{source_exists} = 1;
-        }
-        return $self->{source_exists} = '';
-    }
-}
-
-# Return if a same-named derived file exists under a Repository directory.
-sub derived_exists
-{
-    $_[0]->{derived_exists}
-      || ($_[0]->{derived_exists} = ($_[0] != $_[0]->rfile));
-}
-
-# Return if this file is somewhere under a Repository directory.
-sub is_on_rpath
-{
-    defined $_[0]->{'lfile'};
-}
-
-sub local
-{
-    my ($self, $arg) = @_;
-    if (defined $arg)
-    {
-        $self->{'local'} = $arg;
-    }
-    $self->{'local'};
-}
-
-# Return the entry name of the specified file with the specified
-# suffix appended.  Leave it untouched if the suffix is already there.
-# Differs from the addsuffix function, below, in that this strips
-# the existing suffix (if any) before appending the desired one.
-sub base_suf
-{
-    my ($entry) = $_[0]->{entry};
-    if ($entry !~ m/$_[1]$/)
-    {
-        $entry =~ s/\.[^\.]*$//;
-        $entry .= $_[1];
-    }
-    $entry;
-}
-
-# Return the suffix of the file; everything including and to the
-# right of the last dot.
-sub suffix
-{
-    my @pieces = split (/\./, $_[0]->{entry});
-    my $suffix = pop (@pieces);
-    return ".$suffix";
-}
-
-# Called as a simple function file::addsuffix(name, suffix)
-sub addsuffix
-{
-    my ($name, $suffix) = @_;
-
-    if ($suffix && substr($name, -length($suffix)) ne $suffix)
-    {
-        return $name .= $suffix;
-    }
-    $name;
-}
-
-# Return true if the file is (or will be) accessible.
-# That is, if we can build it, or if it is already present.
-sub accessible
-{
-    (exists $_[0]->{builder}) || ($_[0]->source_exists);
-}
-
-# Return true if the file should be ignored for the purpose
-# of computing dependency information (should not be considered
-# as a dependency and, further, should not be scanned for
-# dependencies).
-sub ignore
-{
-    return 0 if !$param::ignore;
-    return $_[0]->{ignore} if exists $_[0]->{ignore};
-    $_[0]->{ignore} = $_[0]->path =~ /$param::ignore/o;
-}
-
-# Build the file, if necessary.
-sub build
-{
-    return $_[0]->{status} if $_[0]->{status};
-    my ($status) = &file::_build;
-    if ($_[0]->{after_build_func})
-    {
-
-        #print STDERR "DEBUG: after_build_func=$_[0]->{after_build_func}\n";
-        my ($pkgvars) = $_[0]->{conscript}->{pkgvars};
-        NameSpace::restore('script', $pkgvars) if $pkgvars;
-        eval("package script; " . $_[0]->{after_build_func});
-        print "Error running AfterBuild for ${\$_[0]->path}: $@\n" if ($@);
-        NameSpace::remove('script', keys %$pkgvars) if $pkgvars;
-    }
-    return $status;
-}
-
-sub _build
-{
-    my @args = @_;
-
-    if ($param::max_jobs <= 1)
-    {    # pcons
-        my ($self) = @args;
-        print main::DEPFILE $self->path, "\n" if $param::depfile;
-        print((' ' x $level), "Checking ", $self->path, "\n")
-          if $param::depends;
-        if (!exists $self->{builder})
-        {
-
-            # We don't know how to build the file. This is OK, if
-            # the file is present as a source file, under either the
-            # local tree or a Repository.
-            if ($self->source_exists)
-            {
-                return $self->{status} = 'handled';
-            }
-            else
-            {
-                my ($name) = $self->path;
-                print("$0: don't know how to construct \"$name\"\n");
-                exit(1) unless $param::kflag;
-                return $self->{status} = 'errors';    # xxx used to be 'unknown'
-            }
-        }
-
-        # An associated build object exists, so we know how to build
-        # the file. We first compute the signature of the file, based
-        # on its dependendencies, then only rebuild the file if the
-        # signature has changed.
-        my ($builder) = $self->{builder};
-        $level += 2;
-
-        my (@deps) = (@{$self->{dep}}, @{$self->{sources}});
-        my ($rdeps) = \@deps;
-
-        if ($param::random)
-        {
-
-            # If requested, build in a random order, instead of the
-            # order that the dependencies were listed.
-            my (%rdeps);
-            map { $rdeps{$_, '*' x int(rand 10)} = $_ } @deps;
-            $rdeps = [values(%rdeps)];
-        }
-
-        $self->{status} = '';
-
-        my $dep;
-        for $dep (@$rdeps)
-        {
-            if ((build $dep) eq 'errors')
-            {
-
-                # Propagate dependent errors to target.
-                # but try to build all dependents regardless of errors.
-                $self->{status} = 'errors';
-            }
-        }
-
-        # If any dependents had errors, then we abort.
-        if ($self->{status} eq 'errors')
-        {
-            $level -= 2;
-            return 'errors';
-        }
-
-        # Compute the final signature of the file, based on
-        # the static dependencies (in order), dynamic dependencies,
-        # output path name, and (non-substituted) build script.
-        my ($sig) =
-          'sig'->collect(map('sig'->signature($_->rfile), @deps),
-                         $builder->includes($self), $builder->scriptsig);
-
-        # May have gotten errors during computation of dynamic
-        # dependency signature, above.
-        $level -= 2;
-        return 'errors' if $self->{status} eq 'errors';
-
-        if (@param::rpath && $self->derived_exists)
-        {
-
-            # There is no local file of this name, but there is one
-            # under a Repository directory.
-
-            if ('sig'->current($self->rfile, $sig))
-            {
-
-                # The Repository copy is current (its signature matches
-                # our calculated signature).
-                if ($self->local)
-                {
-
-                    # ...but they want a local copy, so provide it.
-                    main::showcom("Local copy of ${\$self->path} from "
-                                  . "${\$self->rpath}");
-                    futil::install($self->rpath, $self);
-                    'sig'->bsig($self, $sig);
-                }
-                return $self->{status} = 'handled';
-            }
-
-            # The signatures don't match, implicitly because something
-            # on which we depend exists locally.  Get rid of the reference
-            # to the Repository file; we'll build this (and anything that
-            # depends on it) locally.
-            $self->no_rfile;
-        }
-
-        # Then check for currency.
-        if (!'sig'->current($self, $sig))
-        {
-
-            # We have to build/derive the file.
-            print((' ' x $level), "Rebuilding ", $self->path,
-                  ": out of date.\n")
-              if $param::depends;
-
-            # First check to see if the built file is cached.
-            if ($builder->cachin($self, $sig))
-            {
-                'sig'->bsig($self, $sig);
-                return $self->{status} = 'built';
-            }
-            elsif ($builder->action($self))
-            {
-                $builder->cachout($self, $sig);
-                'sig'->bsig($self, $sig);
-                return $self->{status} = 'built';
-            }
-            else
-            {
-                die ("$0: errors constructing ${\$self->path}\n")
-                  unless $param::kflag;
-                return $self->{status} = 'errors';
-            }
-        }
-        else
-        {
-
-            # Push this out to the cache if we've been asked to (-C option).
-            # Don't normally do this because it slows us down.
-            # In a fully built system, no accesses to the cache directory
-            # are required to check any files. This is a win if cache is
-            # heavily shared. Enabling this option puts the directory in the
-            # loop. Useful only when you wish to recreate a cache from a build.
-            if ($param::cachesync)
-            {
-                $builder->cachout($self, $sig);
-                'sig'->bsig($self, $sig);
-            }
-            return $self->{status} = 'handled';
-        }
-    }
-    else
-    {    # pcons
-        my ($tgt) = @args;    # pcons
-        local ($file::child_queue) = {parent => $tgt};    # pcons
-        _pbuild($tgt);                                    # pcons
-        wait_on_all_children();                           # pcons
-        return $tgt->{status};                            # pcons
-    }
-}
-
-########################################
-# pcons only BEGIN
-#
-
-sub pbuild
-{
-    $_[0]->{status} || &file::_pbuild;
-}
-
-sub _pbuild
-{
-    my ($self) = @_;
-    $self->{status} = '';    # tgl
-    print main::DEPFILE $self->path, "\n" if param::depfile;
-    print((' ' x $level), $self->path, "\n") if $param::depends;
-    if (!exists $self->{builder})
-    {
-
-        # We don't know how to build the file. This is OK, if
-        # the file is present as a source file, under either the
-        # local tree or a Repository.
-        if ($self->source_exists)
-        {
-            return $self->{status} = 'handled';
-        }
-        else
-        {
-            my ($name) = $self->path;
-            print("$0: don't know how to construct \"$name\"\n");
-            exit(1) unless $param::kflag;
-            return $self->{status} = 'errors';    # xxx used to be 'unknown'
-        }
-    }
-
-    # An associated build object exists, so we know how to build
-    # the file. We first compute the signature of the file, based
-    # on its dependendencies, then only rebuild the file if the
-    # signature has changed.
-    my ($builder) = $self->{'builder'};
-    $level += 2;
-
-    my (@deps) = (@{$self->{dep}}, @{$self->{sources}});
-    my ($rdeps) = \@deps;
-
-    if ($param::random)
-    {
-
-        # If requested, build in a random order, instead of the
-        # order that the dependencies were listed.
-        my (%rdeps);
-
-        # FIX	map { $rdeps{$_,'*' x int(rand(0,10))} = $_ } @deps;
-        map { $rdeps{$_, '*' x int(rand(10))} = $_ } @deps;
-        $rdeps = [values(%rdeps)];
-    }
-
-    $self->{status} = '';
-
-    my $sig;
-    {
-
-        # print "in ", $self->path, "\n";
-        local ($file::child_queue) = {parent => $self};
-        for my $dep (@$rdeps)
-        {
-            if ((pbuild $dep) eq 'errors')
-            {
-
-                # Propagate dependent errors to target.
-                # but try to build all dependents regardless of errors.
-                $self->{status} = 'errors';
-            }
-        }
-        wait_on_all_children();
-
-    }
-
-    # If any dependents had errors, then we abort.
-    if ($self->{'status'} eq 'errors')
-    {
-        $level -= 2;
-        return 'errors';
-    }
-
-    # Compute the final signature of the file, based on
-    # the static dependencies (in order), dynamic dependencies,
-    # output path name, and (non-substituted) build script.
-
-    #    my($sig) = $self->{'sign'} = sig->collect(map(sig->signature($_->rfile), @deps),
-    #			    $builder->includes($self),
-    ## FIX			    $builder->script);
-    #			    $builder->scriptsig);
-
-    my ($sig) = 'sig'->collect(
-        map('sig'->signature($_->rfile), @deps),    # from cons-2.3.0
-        $builder->includes($self),                  # from cons-2.3.0
-        $builder->scriptsig
-        );    # from cons-2.3.0
-    $self->{sign} = $sig;
-
-    # May have gotten errors during computation of dynamic
-    # dependency signature, above.
-    $level -= 2;
-    return 'errors' if $self->{status} eq 'errors';
-
-    if (@param::rpath && $self->derived_exists)
-    {
-
-        # There is no local file of this name, but there is one
-        # under a Repository directory.
-
-        if ('sig'->current($self->rfile, $sig))
-        {
-
-            # The Repository copy is current (its signature matches
-            # our calculated signature).
-            if ($self->local)
-            {
-
-                # ...but they want a local copy, so provide it.
-                main::showcom(
-                         "Local copy of ${\$self->path} from ${\$self->rpath}");
-                futil::install($self->rpath, $self);
-
-                #'sig'->set($self, $sig);
-                'sig'->bsig($self, $sig);    # pcons
-            }
-            return $self->{status} = 'handled';
-        }
-
-        # The signatures don't match, implicitly because something
-        # on which we depend exists locally.  Get rid of the reference
-        # to the Repository file; we'll build this (and anything that
-        # depends on it) locally.
-        $self->no_rfile;
-    }
-
-    # Then check for currency.
-    if (!'sig'->current($self, $sig))
-    {
-
-        # We have to build/derive the file.
-        # First check to see if the built file is cached.
-        if ($builder->cachin($self, $sig))
-        {
-
-            #'sig'->set($self, $sig);
-            'sig'->bsig($self, $sig);    # pcons
-            return $self->{status} = 'built';
-
-            # action no longer blocks (for most actions), so this returns
-            # immediately, before any  commands are actually run.  The
-            # signature and return status should be overridden later in
-            # wait_on_child if a process was forked, but they are still set
-            # here in case a non-spawning action was called
-        }
-        elsif ($builder->action($self))
-        {
-            $builder->cachout($self, $sig);
-
-            #'sig'->set($self, $sig);
-            'sig'->bsig($self, $sig);    # pcons
-            return $self->{status} = 'built';
-        }
-        else
-        {
-            die ("$0: errors constructing ${\$self->path}\n")
-              unless $param::kflag;
-            return $self->{status} = 'errors';
-        }
-    }
-    else
-    {
-
-        # Push this out to the cache if we've been asked to (-C option).
-        # Don't normally do this because it slows us down.
-        # In a fully built system, no accesses to the cache directory
-        # are required to check any files. This is a win if cache is
-        # heavily shared. Enabling this option puts the directory in the
-        # loop. Useful only when you wish to recreate a cache from a build.
-        if ($param::cachesync)
-        {
-            $builder->cachout($self, $sig);
-
-            #'sig'->set($self, $sig);
-            'sig'->bsig($self, $sig);
-        }
-        return $self->{status} = 'handled';
-    }
-}
-
-my @finished;    # pcons //fix -Mstrict
-
-sub wait_on_max_jobs
-{
-    while (grep(/\d+/, keys %{$file::child_queue}) >= $param::max_jobs)
-    {
-        wait_on_child();
-    }
-}
-
-sub wait_on_all_children
-{
-
-    while (grep(/\d+/, keys %{$file::child_queue}) != 0)
-    {
-        wait_on_child();
-    }
-}
-
-sub wait_on_child
-{
-    my ($queue)  = $file::child_queue;
-    my ($parent) = $queue->{parent};
-
-    my $n = grep(/\d+/, keys %{$file::child_queue});
-
-    # printf "Waiting to build (%s): %s\n", $n, $parent->path if ref($parent) eq 'file';
-    my $pid = undef;
-
-    # first check for jobs that have already been collected from child
-    # targets
-    for my $p (@finished)
-    {
-        if ($queue->{$p})
-        {
-            $pid = $p;
-            last;
-        }
-    }
-
-    while (!$queue->{$pid})
-    {
-        $pid = wait();
-        if ($pid < 1)
-        {
-            die "wait returned invalid pid $pid";
-        }
-        else
-        {
-
-            # this job was meant for a parent, save it so that it can be
-            # found later
-            if (!$queue->{$pid})
-            {
-                push @finished, $pid;
-            }
-        }
-    }
-
-    my $child = $queue->{$pid};
-    my $tgt   = $queue->{$pid}->{'tgt'};
-    my $com   = $child->{'com'};
-    $tgt->{status} = 'built';
-
-    #print "waited: ", $tgt->path; 
-    #print "on: ",  keys %{$queue}, "\n";
-
-    my ($b0, $b1) = ($? & 0xFF, $? >> 8);
-
-    # Don't actually see 0177 on stopped process; is this necessary?
-    # next if $b0 == 0177; # process stopped; we can wait.
-    if ($b0)
-    {
-        my ($core, $sig) = ($b0 & 0200, $b0 & 0177);
-        my ($coremsg) = $core ? "; core dumped" : "";
-        $com =~ s/\s.*//;
-        my ($path) = $tgt->path;
-        warn qq($0: *** [$path] $com terminated by signal $sig$coremsg\n);
-        $parent->{status} = $tgt->{status} = 'errors';
-    }
-    if ($b1)
-    {
-        my ($path) = $tgt->path;
-        warn qq($0: *** [$path] Error $b1\n);    # trying to be like make.
-        $parent->{status} = $tgt->{status} = 'errors';
-    }
-    if ($tgt->{status} eq 'built')
-    {
-        $tgt->{builder}->cachout($tgt, $tgt->{sign});
-
-        #'sig'->set($tgt, $tgt->{sign});
-        'sig'->bsig($tgt, $tgt->{sign});
-    }
-    else
-    {
-        die ("$0: errors constructing ${\$tgt->path}\n") unless $param::kflag;
-    }
-    delete $queue->{$pid};
-
-}
-
-#
-# pcons END
-########################################
-
-# Bind an action to a file, with the specified sources. No return value.
-sub bind
-{
-    my ($self, $builder, @sources) = @_;
-    if ($self->{builder} && !$self->{builder}->compatible($builder))
-    {
-
-        # Even if not "compatible", we can still check to see if the
-        # derivation is identical. It should be identical if the builder is
-        # the same and the sources are the same.
-        if ("$self->{builder} @{$self->{sources}}" ne "$builder @sources")
-        {
-            $main::errors++;
-            my ($_foo1, $script1, $line1, $sub1) = @{$self->creator};
-            my ($_foo2, $script2, $line2, $sub2) = script::caller_info;
-            my $err =
-              "\t${\$self->path}\n"
-              . "\tbuilt (at least) two different ways:\n"
-              . "\t\t$script1, line $line1:  $sub1\n"
-              . "\t\t$script2, line $line2:  $sub2\n";
-            die $err;
-        }
-        return;
-    }
-    if ($param::wflag)
-    {
-        my ($script, $line, $sub);
-        (undef, $script, $line, $sub) = script::caller_info;
-        $self->{script} = '' if !defined $self->{script};
-        $self->{script} .= "; " if $self->{script};
-        $self->{script} .= qq($sub in "$script", line $line);
-    }
-    $self->{builder} = $builder;
-    push (@{$self->{sources}}, @sources);
-    @{$self->{dep}} = () if !defined $self->{dep};
-    $self->{conscript} = $priv::self->{script};
-}
-
-sub is_under
-{
-    $_[0]->{dir}->is_under($_[1]);
-}
-
-sub relpath
-{
-    my $dirpath = $_[0]->relpath($_[1]->{dir});
-    if (!$dirpath)
-    {
-        return $_[1]->{entry};
-    }
-    else
-    {
-        File::Spec->catfile($dirpath, $_[1]->{entry});
-    }
-}
-
-# Return the signature array for this file.
-# This probably belongs in its own "sigarray" package,
-# which would make it easier to optimize performance.
-sub sigarray
-{
-    if ($_[0]->{sigaref})
-    {
-        return @{$_[0]->{sigaref}};
-    }
-    my $self = shift;
-
-    # glob2pat based on The Perl Cookbook, p. 180.
-    sub glob2pat
-    {
-        my $globstr = shift;
-        my %patmap = (
-                     '*' => '.*',
-                     '?' => '.',
-                     '[' => '[',
-                     ']' => ']',
-                     '/' => "\Q$dir::SEPARATOR",    # Cons-specific modification
-                     );
-        $globstr =~ s{(.)} { $patmap{$1} || "\Q$1" }ge;
-        return '^' . $globstr . '$';
-    }
-    my @sigarray;
-    my $default;
-    my $builder = $self->lfile->{builder};
-    if (!$builder)
-    {
-        @sigarray = @$param::sourcesig;
-        $default  = [qw(content)];
-    }
-    else
-    {
-        if ($builder->{env} && $builder->{env}->{SIGNATURE})
-        {
-            @sigarray = @{$builder->{env}->{SIGNATURE}};
-        }
-        else
-        {
-            my $class = ref $builder;
-            my $path  = $self->path;
-            warn qq($0: Warning:  Builder package $class did not record\n)
-              . qq(\tthe calling environment for '$path'.\n)
-              . qq(\tUnable to use any %SIGNATURE construction variable\n)
-              . qq(\tfor signature configuration.\n);
-        }
-        $default = [qw(build)];
-    }
-    my $path = $self->path;
-    while (@sigarray)
-    {
-        my ($glob, $aref) = splice(@sigarray, 0, 2);
-        my $re = glob2pat($glob);
-        if ($path =~ /$re/)
-        {
-            $aref = [split (/\s+/, $aref)] if !ref $aref;
-            $self->{sigaref} = $aref;
-            return @$aref;
-        }
-    }
-    $self->{sigaref} = $default;
-    return @{$self->{sigaref}};
-}
-
-# Decide if this file's signature should be the content or build signature.
-sub sigtype
-{
-    if ($_[0]->{sigtype})
-    {
-        return $_[0]->{sigtype};
-    }
-    my $self     = shift;
-    my @sigarray = $self->sigarray;
-    my $sigtype;
-    if (grep($_ eq "build", @sigarray))
-    {
-        $sigtype = 'bsig';
-    }
-    elsif (grep($_ =~ /content$/, @sigarray))
-    {
-        $sigtype = 'csig';
-    }
-    return $self->{sigtype} = $sigtype;
-}
-
-# Return whether this file is configured to use stored
-# signature values from the .consign file.
-sub stored
-{
-    if (!defined $_[0]->{stored})
-    {
-        $_[0]->{stored} = grep($_ eq "stored-content", $_[0]->sigarray);
-    }
-    return $_[0]->{stored};
-}
-
-# Generic entry (file or directory) handling.
-# This is an empty subclass for nodes that haven't
-# quite decided whether they're files or dirs.
-# Use file methods until someone blesses them one way or the other.
-package entry;
-
-use vars qw( @ISA );
-
-BEGIN { @ISA = qw(file) }
-
-# File utilities
-package futil;
-
-# Install one file as another.
-# Links them if possible (hard link), otherwise copies.
-# Don't ask why, but the source is a path, the tgt is a file obj.
-sub install
-{
-    my ($sp, $tgt) = @_;
-    my ($tp) = $tgt->path;
-    return 1 if $tp eq $sp;
-    return 1 if eval { link($sp, $tp) };
-    unlink($tp);
-    if (!futil::mkdir($tgt->{dir}))
-    {
-        return undef;
-    }
-    return 1 if eval { link($sp, $tp) };
-    futil::copy($sp, $tp);
-}
-
-# Copy one file to another. Arguments are actual file names.
-# Returns undef on failure. Preserves mtime and mode.
-sub copy
-{
-    my ($sp, $tp) = @_;
-    my ($mode, $length, $atime, $mtime) = (stat($sp))[2, 7, 8, 9];
-
-    # Use Perl standard library module for file copying, which handles
-    # binary copies. <schwarze at isa.de> 1998-06-18
-    if (!File::Copy::copy($sp, $tp))
-    {
-        warn qq($0: can\'t install "$sp" to "$tp" ($!)\n);    #'
-        return undef;
-    }
-
-    # The file has been created, so try both the chmod and utime,
-    # first making sure the copy is writable (because permissions
-    # affect the ability to modify file times on some operating
-    # systems), and then changing permissions back if necessary.
-    my $ret   = 1;
-    my $wmode = $mode | 0700;
-    if (!chmod $wmode, $tp)
-    {
-        warn qq($0: can\'t set mode $wmode on file "$tp" ($!)\n);    #'
-        $ret = undef;
-    }
-    if (!utime $atime, $mtime, $tp)
-    {
-        warn qq($0: can\'t set modification time for file "$tp" ($!)\n);    #'
-        $ret = undef;
-    }
-    if ($mode != $wmode && !chmod $mode, $tp)
-    {
-        warn qq($0: can\'t set mode $mode on file "$tp" ($!)\n);    #'
-        $ret = undef;
-    }
-    return $ret;
-}
-
-# Ensure that the specified directory exists.
-# Aborts on failure.
-sub mkdir
-{
-    return 1 if $_[0]->{'exists'};
-    if (!futil::mkdir($_[0]->{dir}))
-    {    # Recursively make parent.
-        return undef;
-    }
-    my ($path) = $_[0]->path;
-    if (!-d $path && !mkdir($path, 0777))
-    {
-        warn qq($0: can't create directory $path ($!).\n);    #'
-        return undef;
-    }
-    $_[0]->{'exists'} = 1;
-}
-
-# Signature package.
-package sig::hash;
-
-use vars qw( $called );
-
-sub init
-{
-    my ($dir)     = @_;
-    my ($consign) = $dir->prefix . ".consign";
-    my ($dhash)   = $dir->{consign} = {};
-    if (-f $consign)
-    {
-        open(CONSIGN, $consign) || die ("$0: can't open $consign ($!)\n");
-        while (<CONSIGN>)
-        {
-            chop;
-            my ($file, $sig) = split (/:/, $_);
-            $dhash->{$file} = $sig;
-        }
-        close(CONSIGN);
-    }
-    $dhash;
-}
-
-# Read the hash entry for a particular file.
-sub in
-{
-    my ($dir) = $_[0]->{dir};
-    ($dir->{consign} || init($dir))->{$_[0]->{entry}};
-}
-
-# Write the hash entry for a particular file.
-sub out
-{
-    my ($file, $sig) = @_;
-    my ($dir) = $file->{dir};
-    ($dir->{consign} || init($dir))->{$file->{entry}} = $sig;
-    $sig::hash::dirty{$dir} = $dir;
-}
-
-# Eliminate the hash entry for a particular file.
-sub clear
-{
-    my ($file) = @_;
-    my ($dir)  = $file->{dir};
-    delete $dir->{consign}->{$file->{entry}} if $dir->{consign};
-    $sig::hash::dirty{$dir} = $dir;
-}
-
-# Flush hash entries. Called at end or via ^C interrupt.
-sub END
-{
-    return if $called++;    # May be called twice.
-    close(CONSIGN);         # in case this came in via ^C.
-    my $dir;
-    for $dir (values %sig::hash::dirty)
-    {
-        my ($consign)  = $dir->prefix . ".consign";
-        my ($constemp) = $consign . ".$$";
-        if (!open(CONSIGN, ">$constemp"))
-        {
-            die ("$0: can't create $constemp ($!)\n");
-        }
-        my ($entry, $sig);
-        while (($entry, $sig) = each %{$dir->{consign}})
-        {
-            if (!print CONSIGN "$entry:$sig\n")
-            {
-                die ("$0: error writing to $constemp ($!)\n");
-            }
-        }
-        close(CONSIGN);
-        if (!rename($constemp, $consign))
-        {
-            if (futil::copy($constemp, $consign))
-            {
-                unlink($constemp);
-            }
-            else
-            {
-                die ("$0: couldn't rename or copy $constemp to $consign "
-                     . "($!)\n");
-            }
-        }
-    }
-}
-
-# Derived file caching.
-package cache;
-
-# Find a file in the cache. Return non-null if the file is in the cache.
-sub in
-{
-    return undef unless $param::cache;
-    my ($file, $sig) = @_;
-
-    # Add the path to the signature, to make it unique.
-    $sig = 'sig'->collect($sig, $file->path) unless $param::mixtargets;
-    my ($dir) = substr($sig, 0, 1);
-    my ($cp) = File::Spec->catfile($param::cache, $dir, $sig);
-    return -f $cp && futil::install($cp, $file);
-}
-
-# Try to flush a file to the cache, if not already there.
-# If it doesn't make it out, due to an error, then that doesn't
-# really matter.
-sub out
-{
-    return unless $param::cache;
-    my ($file, $sig) = @_;
-
-    # Add the path to the signature, to make it unique.
-    $sig = 'sig'->collect($sig, $file->path) unless $param::mixtargets;
-    my ($dir) = substr($sig, 0, 1);
-    my ($sp) = $file->path;
-    my ($cp) = File::Spec->catfile($param::cache, $dir, $sig);
-    my ($cdir) = File::Spec->catfile($param::cache, $dir);
-    if (!-d $cdir)
-    {
-        mkdir($cdir, 0777)
-          || die ("$0: can't create cache directory $cdir ($!).\n");
-    }
-    elsif (-f $cp)
-    {
-
-        # Already cached: try to use that instead, to save space.
-        # This can happen if the -cs option is used on a previously
-        # uncached build, or if two builds occur simultaneously.
-        my ($lp) = ".$sig";
-        unlink($lp);
-        return if !eval { link($cp, $lp) };
-        rename($lp, $sp);
-
-        # Unix98 says, "If the old argument and the new argument both
-        # [refer] to the same existing file, the rename() function
-        # returns successfully and performs no other action."  So, if
-        # $lp and $sp are links (i.e., $cp and $sp are links), $lp is
-        # left, and we must unlink it ourselves.  If the rename failed
-        # for any reason, it is also good form to unlink the temporary
-        # $lp.  Otherwise $lp no longer exists and, barring some race,
-        # the unlink fails silently.
-        unlink($lp);
-        return;
-    }
-
-    return if eval { link($sp, $cp) };
-    return if !-f $sp;    # if nothing to cache.
-    if (futil::copy($sp, "$cp.new"))
-    {
-        rename("$cp.new", $cp);
-    }
-}
-
-# Generic signature handling package.
-# This handles the higher-layer distinction between content and build
-# signatures, relying on an underlying calculation package like
-# "sig::md5"" to provide the signature values themselves.
-package sig;
-
-use vars qw( @ISA );
-
-# Select the underlying package to be used for signature calculation.
-# We play a few namespace games here.  Specifically, we append
-# "sig::" to the beginning of the subclass we're passed.  Then,
-# if the package ends in "::debug", we actually subclass the
-# "sig::debug" package and as a wrapper around the underlying
-# (e.g.) "sig::md5" package that's doing the real calculation.
-sub select
-{
-    my ($package, $subclass) = @_;
-    my $p      = $package . "::" . $subclass;
-    my $sigpkg = $p;
-    if ($p =~ /(.*)::debug$/)
-    {
-        $sigpkg = $1;
-        $p      = 'sig::debug';
-    }
-    @ISA = ($p);
-    $p->init($sigpkg);
-};
-
-# Set or return the build signature of a file.
-# This is computed elsewhere and passed in to us.
-sub bsig
-{
-    my ($self, $file, $sig) = @_;
-    if (defined $sig)
-    {
-        $file->{'bsig'} = $sig;
-        $self->set($file);
-    }
-    elsif (!defined $file->{'bsig'})
-    {
-        $file->{'bsig'} = '';
-    }
-    $file->{'bsig'};
-}
-
-# Determine the content signature of a file.
-# This also sets the .consign entry unless the file is in a
-# repository; we don't write into repositories, only read from them.
-sub csig
-{
-    my ($self, $file) = @_;
-    if (!$file->{'csig'})
-    {
-        $file->{'csig'} = $self->srcsig($file->path);
-        $self->set($file) if !$file->is_on_rpath;
-    }
-    $_[1]->{'csig'};
-}
-
-# Determine the current signature of an already-existing or
-# non-existant file.  Unless a specific signature type (bsig
-# or csig) is requested, this consults the file's signature
-# array to decide whether to return content or build signature,
-# and whether to use a cached value from a .consign file.
-sub signature
-{
-    my ($self, $file, $sigtype) = @_;
-    $sigtype = $file->sigtype if !$sigtype;
-
-    #open(TTY, ">/dev/tty");
-    #print TTY $file->path, ": $sigtype\n";
-    #close(TTY);
-    my ($path) = $file->path;
-    my ($time) = (stat($path))[9];
-    if ($time)
-    {
-        if ($file->{$sigtype})
-        {
-            return $file->{$sigtype};
-        }
-        if ($file->is_on_rpath || $file->stored)
-        {
-            if ('sig'->fetch($file) && $file->{$sigtype})
-            {
-                if ($file->{'sigtime'} == $time
-                    || !$param::rep_sig_times_ok && $file->is_on_rpath)
-                {
-                    return $file->{$sigtype};
-                }
-            }
-            $file->{$sigtype} = undef;
-        }
-        if ($file->is_on_rpath || !File::Spec->file_name_is_absolute($path))
-        {
-            my $sig = '';
-            if    ($sigtype eq 'bsig') { $sig = $self->bsig($file); }
-            elsif ($sigtype eq 'csig') { $sig = $self->csig($file); }
-            return $sig;
-        }
-
-        # This file is not in a repository or under the local directory
-        # structure.  In the canonical case, it's a utility that will be
-        # executed by a command.  Historically, Cons has returned the
-        # name of the command concatenated with the modification time.
-        # Note that this is *not* the path ("cc" not "/bin/cc"), so it
-        # would lose in the unlikely event that a different copy of the
-        # utility was used that happened to have the same modification
-        # time (due to living in a different directory on the PATH, for
-        # example).  The obvious "fix" of using the path like so, however:
-        #	return $path . $time;
-        # is wrong.  In a multi-machine build environment, different
-        # systems may have the same utility in different locations (due
-        # to different NFS mount points, for example), which would
-        # cause a lot of unnecessary builds if we used the full path.
-        # A better solution to strengthen this signature would be to
-        # also concatenate the size of the file, but that would cause
-        # unnecessary rebuilds when coming from .consign files that used
-        # the old scheme.  All of which is to merely explain why we're
-        # leaving this as it has been, but documenting it here in case
-        # there's reason to change it in the future.
-        return $file->{entry} . $time;
-    }
-    return $file->{$sigtype} = '';
-}
-
-sub bsignature
-{
-    my ($self, $file) = @_;
-    my ($path) = $file->path;
-    my ($time) = (stat($path))[9];
-    if ($time)
-    {
-        if ($file->{'bsig'})
-        {
-            return $file->{'bsig'};
-        }
-        if ('sig'->fetch($file, 'bsig') && $file->{'bsig'})
-        {
-            if ($file->{'sigtime'} == $time
-                || !$param::rep_sig_times_ok && $file->is_on_rpath)
-            {
-                return $file->{'bsig'};
-            }
-        }
-        if ($file->is_on_rpath || !File::Spec->file_name_is_absolute($path))
-        {
-            return $self->bsig($file);
-        }
-        return $path . $time;
-    }
-    return $file->{'bsig'} = '';
-}
-
-# Invalidate a file's signature, also clearing its .consign entry.
-sub invalidate
-{
-    my ($self, $file) = @_;
-    delete $file->{'sigtime'};
-    delete $file->{'bsig'};
-    delete $file->{'csig'};
-    sig::hash::clear($file);
-}
-
-# Store the signature for a file.
-sub set
-{
-    my ($self, $file) = @_;
-    my $sig = (stat($file->path))[9];
-    $sig .= " " . ($file->{'bsig'} || '-');
-    $sig .= " " . $file->{'csig'} if $file->{'csig'};
-    sig::hash::out($file, $sig);
-}
-
-# Fetch the signature(s) for a file.
-# Returns whether there was a signature to fetch.
-sub fetch
-{
-    my ($self, $file, @kw) = @_;
-    @kw = ('bsig', 'csig') if !@kw;
-    my $sig = sig::hash::in($file) || '';
-    my ($sigtime, $bsig, $csig) = split (/ /, $sig);
-    $file->{'sigtime'} = $sigtime;
-    $file->{'bsig'}    = $bsig || '' if grep($_ eq 'bsig', @kw);
-    $file->{'csig'}    = $csig || '' if grep($_ eq 'csig', @kw);
-    $file->{'bsig'} = '' if $file->{'bsig'} eq '-';
-    return $sig ne '';
-}
-
-# MD5-based signature package.
-package sig::md5;
-
-use vars qw( $md5 );
-
-# Initialize MD5 signature calculation by finding an appropriate
-# module and creating the proper object.
-sub init
-{
-    my $self        = shift;
-    my @md5_modules = qw(Digest::MD5 MD5 Digest::Perl::MD5);
-
-    # We used to find the right module more simply, using $_ as the
-    # loop iterator and just doing:
-    #
-    #		eval "use $_";
-    #		$module = $_, $last if ! $@;
-    #
-    # in the loop.  Empirically, though, this doesn't pass back the
-    # right value in $module on some ActiveState versions.  (Maybe
-    # it's something to do with the eval in a for loop, I dunno.)
-    # Work around it by using $_ to pass the value out of the loop,
-    # which seems to work everywhere.
-    my $module;
-    for $module (@md5_modules)
-    {
-        eval "use $module";
-        $_ = $module, last if !$@;
-    }
-    $module = $_;
-    die "Cannot find any MD5 module from:  @md5_modules" if $@;
-
-    $md5 = new $module;
-}
-
-# Is the provided signature equal to the signature of the current
-# instantiation of the target (and does the target exist)?
-sub current
-{
-    my ($self, $file, $sig, $sigtype) = @_;
-    $self->bsignature($file) eq $sig;
-}
-
-# Return an aggregate signature for a list of signature values.
-sub collect
-{
-    my ($self, @sigs) = @_;
-
-    # The following sequence is faster than calling the hex interface.
-    $md5->reset();
-    $md5->add(join ('', $param::salt, @sigs));
-    unpack("H*", $md5->digest());
-}
-
-# Directly compute a file signature as the MD5 checksum of the
-# bytes in the file.
-sub srcsig
-{
-    my ($self, $path) = @_;
-    $md5->reset();
-    open(FILE, $path) || return '';
-    binmode(FILE);
-    $md5->addfile(\*FILE);
-    close(FILE);
-    unpack("H*", $md5->digest());
-}
-
-# Compute the signature of a command string.
-# For MD5, this is just the string itself, since MD5 will condense
-# the string contents into the ultimate signature.  Other signature
-# schemes may need to figure this out differently.
-sub cmdsig
-{
-    my ($self, $sig) = @_;
-    return $sig;
-}
-
-# Generic debug package for signature calculation.
-# Because of the way we're called by sig::select() and then use
-# the specified value to set up @ISA, this package is essentially a
-# factory that creates packages like sig::md5::debug, etc., on the fly.
-package sig::debug;
-
-use vars qw( @ISA $sigpkg $outfh );
-
-local *FH;
-
-sub init
-{
-    my $self = shift;
-    $sigpkg = shift;
-    @ISA    = ($sigpkg);
-    $sigpkg->init();
-    my $file = $ENV{CONS_SIG_DEBUG};
-    if ($file)
-    {
-        if (!open(FH, ">$file"))
-        {
-            die "Cannot open $file: $!";
-        }
-        $outfh = \*FH;
-    }
-    else
-    {
-        $outfh = \*STDOUT;
-    }
-}
-
-sub current
-{
-    my ($self, $file, $sig, $sigtype) = @_;
-    my $fsig = $self->bsignature($file);
-    my $sub  = "${sigpkg}::current";
-    my $sep  = "\n" . ' ' x (length($sub) + 1 - 3);
-    print $outfh "$sub(|$fsig|${sep}eq |$sig|)\n";
-    return $fsig eq $sig;
-}
-
-sub collect
-{
-    my ($self, @sigs) = @_;
-    my $sig = $sigpkg->collect(@sigs);
-    my $sub = "${sigpkg}::collect";
-    my $sep = ",\n" . ' ' x (length($sub) + 1);
-    my $buf = join ($sep, @sigs);
-    $buf = $param::salt . $sep . $buf if $param::salt;
-    print $outfh "$sub($buf)\n\t=> |$sig|\n";
-    return $sig;
-}
-
-sub srcsig
-{
-    my ($self, $path) = @_;
-    my $sig = $sigpkg->srcsig($path);
-    print $outfh "${sigpkg}::srcsig($path)\n\t=> |$sig|\n";
-    return $sig;
-}
-
-__END__;
-
-=head1 NAME
-
-Cons - A Software Construction System
-
-=head1 DESCRIPTION
-
-A guide and reference for version __VERSION____REVISION__
-
-Copyright (c) 1996-2001 Free Software Foundation, Inc.
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
-
-=head1 Introduction
-
-B<Cons> is a system for constructing, primarily, software, but is quite
-different from previous software construction systems. Cons was designed
-from the ground up to deal easily with the construction of software spread
-over multiple source directories. Cons makes it easy to create build scripts
-that are simple, understandable and maintainable. Cons ensures that complex
-software is easily and accurately reproducible.
-
-Cons uses a number of techniques to accomplish all of this. Construction
-scripts are just Perl scripts, making them both easy to comprehend and very
-flexible. Global scoping of variables is replaced with an import/export
-mechanism for sharing information between scripts, significantly improving
-the readability and maintainability of each script. B<Construction
-environments> are introduced: these are Perl objects that capture the
-information required for controlling the build process. Multiple
-environments are used when different semantics are required for generating
-products in the build tree. Cons implements automatic dependency analysis
-and uses this to globally sequence the entire build. Variant builds are
-easily produced from a single source tree. Intelligent build subsetting is
-possible, when working on localized changes. Overrides can be setup to
-easily override build instructions without modifying any scripts. MD5
-cryptographic B<signatures> are associated with derived files, and are used
-to accurately determine whether a given file needs to be rebuilt.
-
-While offering all of the above, and more, Cons remains simple and easy to
-use. This will, hopefully, become clear as you read the remainder of this
-document.
-
-
-=head1 Why Cons? Why not Make?
-
-Cons is a B<make> replacement. In the following paragraphs, we look at a few
-of the undesirable characteristics of make--and typical build environments
-based on make--that motivated the development of Cons.
-
-=head2 Build complexity
-
-Traditional make-based systems of any size tend to become quite complex. The
-original make utility and its derivatives have contributed to this tendency
-in a number of ways. Make is not good at dealing with systems that are
-spread over multiple directories. Various work-arounds are used to overcome
-this difficulty; the usual choice is for make to invoke itself recursively
-for each sub-directory of a build. This leads to complicated code, in which
-it is often unclear how a variable is set, or what effect the setting of a
-variable will have on the build as a whole. The make scripting language has
-gradually been extended to provide more possibilities, but these have
-largely served to clutter an already overextended language. Often, builds
-are done in multiple passes in order to provide appropriate products from
-one directory to another directory. This represents a further increase in
-build complexity.
-
-
-=head2 Build reproducibility
-
-The bane of all makes has always been the correct handling of
-dependencies. Most often, an attempt is made to do a reasonable job of
-dependencies within a single directory, but no serious attempt is made to do
-the job between directories. Even when dependencies are working correctly,
-make's reliance on a simple time stamp comparison to determine whether a
-file is out of date with respect to its dependents is not, in general,
-adequate for determining when a file should be rederived. If an external
-library, for example, is rebuilt and then ``snapped'' into place, the
-timestamps on its newly created files may well be earlier than the last
-local build, since it was built before it became visible.
-
-
-=head2 Variant builds
-
-Make provides only limited facilities for handling variant builds. With the
-proliferation of hardware platforms and the need for debuggable
-vs. optimized code, the ability to easily create these variants is
-essential. More importantly, if variants are created, it is important to
-either be able to separate the variants or to be able to reproduce the
-original or variant at will. With make it is very difficult to separate the
-builds into multiple build directories, separate from the source. And if
-this technique isn't used, it's also virtually impossible to guarantee at
-any given time which variant is present in the tree, without resorting to a
-complete rebuild.
-
-
-=head2 Repositories
-
-Make provides only limited support for building software from code that
-exists in a central repository directory structure.  The VPATH feature of
-GNU make (and some other make implementations) is intended to provide this,
-but doesn't work as expected: it changes the path of target file to the
-VPATH name too early in its analysis, and therefore searches for all
-dependencies in the VPATH directory.  To ensure correct development builds,
-it is important to be able to create a file in a local build directory and
-have any files in a code repository (a VPATH directory, in make terms) that
-depend on the local file get rebuilt properly.  This isn't possible with
-VPATH, without coding a lot of complex repository knowledge directly into
-the makefiles.
-
-
-=head1 Keeping it simple
-
-A few of the difficulties with make have been cited above. In this and
-subsequent sections, we shall introduce Cons and show how these issues are
-addressed.
-
-=head2 Perl scripts
-
-Cons is Perl-based. That is, Cons scripts--F<Conscript> and F<Construct>
-files, the equivalent to F<Makefile> or F<makefile>--are all written in
-Perl. This provides an immediate benefit: the language for writing scripts
-is a familiar one. Even if you don't happen to be a Perl programmer, it
-helps to know that Perl is basically just a simple declarative language,
-with a well-defined flow of control, and familiar semantics. It has
-variables that behave basically the way you would expect them to,
-subroutines, flow of control, and so on. There is no special syntax
-introduced for Cons. The use of Perl as a scripting language simplifies
-the task of expressing the appropriate solution to the often complex
-requirements of a build.
-
-
-=head2 Hello, World!
-
-To ground the following discussion, here's how you could build the B<Hello,
-World!> C application with Cons:
-
-
-
-  $env = new cons();
-  Program $env 'hello', 'hello.c';
-
-If you install this script in a directory, naming the script F<Construct>,
-and create the F<hello.c> source file in the same directory, then you can
-type C<cons hello> to build the application:
-
-
-
-  % cons hello
-  cc -c hello.c -o hello.o
-  cc -o hello hello.o
-
-
-=head2 Construction environments
-
-A key simplification of Cons is the idea of a B<construction environment>. A
-construction environment is an B<object> characterized by a set of key/value
-pairs and a set of B<methods>. In order to tell Cons how to build something,
-you invoke the appropriate method via an appropriate construction
-environment. Consider the following example:
-
-
-
-  $env = new cons(
-	CC	=>	'gcc',
-	LIBS	=>	'libworld.a'
-  );
-
-  Program $env 'hello', 'hello.c';
-
-In this case, rather than using the default construction environment, as is,
-we have overridden the value of C<CC> so that the GNU C Compiler equivalent
-is used, instead. Since this version of B<Hello, World!> requires a library,
-F<libworld.a>, we have specified that any program linked in this environment
-should be linked with that library. If the library exists already, well and
-good, but if not, then we'll also have to include the statement:
-
-
-
-  Library $env 'libworld', 'world.c';
-
-Now if you type C<cons hello>, the library will be built before the program
-is linked, and, of course, C<gcc> will be used to compile both modules:
-
-
-
-  % cons hello
-  gcc -c hello.c -o hello.o
-  gcc -c world.c -o world.o
-  ar r libworld.a world.o
-  ar: creating libworld.a
-  ranlib libworld.a
-  gcc -o hello hello.o libworld.a
-
-
-=head2 Automatic and complete dependency analysis
-
-With Cons, dependencies are handled automatically. Continuing the previous
-example, note that when we modify F<world.c>, F<world.o> is recompiled,
-F<libworld.a> recreated, and F<hello> relinked:
-
-
-
-  % vi world.c
-    [EDIT]
-  % cons hello
-  gcc -c world.c -o world.o
-  ar r libworld.a world.o
-  ar: creating libworld.a
-  ranlib libworld.a
-  gcc -o hello hello.o libworld.a
-
-This is a relatively simple example: Cons ``knows'' F<world.o> depends upon
-F<world.c>, because the dependency is explicitly set up by the C<Library>
-method. It also knows that F<libworld.a> depends upon F<world.o> and that
-F<hello> depends upon F<libworld.a>, all for similar reasons.
-
-Now it turns out that F<hello.c> also includes the interface definition
-file, F<world.h>:
-
-
-
-  % emacs world.h
-    [EDIT]
-  % cons hello
-  gcc -c hello.c -o hello.o
-  gcc -o hello hello.o libworld.a
-
-How does Cons know that F<hello.c> includes F<world.h>, and that F<hello.o>
-must therefore be recompiled? For now, suffice it to say that when
-considering whether or not F<hello.o> is up-to-date, Cons invokes a scanner
-for its dependency, F<hello.c>. This scanner enumerates the files included
-by F<hello.c> to come up with a list of further dependencies, beyond those
-made explicit by the Cons script. This process is recursive: any files
-included by included files will also be scanned.
-
-Isn't this expensive? The answer is--it depends. If you do a full build of a
-large system, the scanning time is insignificant. If you do a rebuild of a
-large system, then Cons will spend a fair amount of time thinking about it
-before it decides that nothing has to be done (although not necessarily more
-time than make!). The good news is that Cons makes it very easy to
-intelligently subset your build, when you are working on localized changes.
-
-
-=head2 Automatic global build sequencing
-
-Because Cons does full and accurate dependency analysis, and does this
-globally, for the entire build, Cons is able to use this information to take
-full control of the B<sequencing> of the build. This sequencing is evident
-in the above examples, and is equivalent to what you would expect for make,
-given a full set of dependencies. With Cons, this extends trivially to
-larger, multi-directory builds. As a result, all of the complexity involved
-in making sure that a build is organized correctly--including multi-pass
-hierarchical builds--is eliminated. We'll discuss this further in the next
-sections.
-
-=head1 Building large trees--still just as simple
-
-
-=head2 A hierarchy of build scripts
-
-A larger build, in Cons, is organized by creating a hierarchy of B<build
-scripts>. At the top of the tree is a script called F<Construct>. The rest
-of the scripts, by convention, are each called F<Conscript>. These scripts
-are connected together, very simply, by the C<Build>, C<Export>, and
-C<Import> commands.
-
-
-=head2 The Build command
-
-The C<Build> command takes a list of F<Conscript> file names, and arranges
-for them to be included in the build. For example:
-
-  Build qw(
-	drivers/display/Conscript
-	drivers/mouse/Conscript
-	parser/Conscript
-	utilities/Conscript
-  );
-
-This is a simple two-level hierarchy of build scripts: all the subsidiary
-F<Conscript> files are mentioned in the top-level F<Construct> file. Notice
-that not all directories in the tree necessarily have build scripts
-associated with them.
-
-This could also be written as a multi-level script. For example, the
-F<Construct> file might contain this command:
-
-  Build qw(
-	parser/Conscript
-	drivers/Conscript
-	utilities/Conscript
-  );
-
-and the F<Conscript> file in the F<drivers> directory might contain this:
-
-  Build qw(
-	display/Conscript
-	mouse/Conscript
-  );
-
-Experience has shown that the former model is a little easier to understand,
-since the whole construction tree is laid out in front of you, at the
-top-level. Hybrid schemes are also possible. A separately maintained
-component that needs to be incorporated into a build tree, for example,
-might hook into the build tree in one place, but define its own construction
-hierarchy.
-
-By default, Cons does not change its working directory to the directory
-containing a subsidiary F<Conscript> file it is including.  This behavior
-can be enabled for a build by specifying, in the top-level F<Construct>
-file:
-
-  Conscript_chdir 1;
-
-When enabled, Cons will change to the subsidiary F<Conscript> file's
-containing directory while reading in that file, and then change back
-to the top-level directory once the file has been processed.
-
-It is expected that this behavior will become the default in some future
-version of Cons.  To prepare for this transition, builds that expect
-Cons to remain at the top of the build while it reads in a subsidiary
-F<Conscript> file should explicitly disable this feature as follows:
-
-  Conscript_chdir 0;
-
-
-=head2 Relative, top-relative, and absolute file names
-
-You may have noticed that the file names specified to the Build command are
-relative to the location of the script it is invoked from. This is generally
-true for other filename arguments to other commands, too, although we might
-as well mention here that if you begin a file name with a hash mark, ``#'',
-then that file is interpreted relative to the top-level directory (where the
-F<Construct> file resides). And, not surprisingly, if you begin it with ``/'',
-then it is considered to be an absolute pathname. This is true even on
-systems which use a back slash rather than a forward slash to name absolute
-paths.
-
-(There is another file prefix, ``!'', that is interpreted specially by
-Cons.  See discussion of the C<Link> command, below, for details.)
-
-
-=head2 Using modules in build scripts
-
-You may pull modules into each F<Conscript> file using the normal Perl
-C<use> or C<require> statements:
-
-  use English;
-  require My::Module;
-
-Each C<use> or C<require> only affects the one F<Conscript> file in which
-it appears.  To use a module in multiple F<Conscript> files, you must
-put a C<use> or C<require> statement in each one that needs the module.
-
-
-=head2 Scope of variables
-
-The top-level F<Construct> file and all F<Conscript> files begin life in
-a common, separate Perl package.  B<Cons> controls the symbol table for
-the package so that, the symbol table for each script is empty, except
-for the F<Construct> file, which gets some of the command line arguments.
-All of the variables that are set or used, therefore, are set by the
-script itself--not by some external script.
-
-Variables can be explicitly B<imported> by a script from its parent
-script. To import a variable, it must have been B<exported> by the parent
-and initialized (otherwise an error will occur).
-
-
-=head2 The Export command
-
-The C<Export> command is used as in the following example:
-
-  $env = new cons();
-  $INCLUDE = "#export/include";
-  $LIB = "#export/lib";
-  Export qw( env INCLUDE LIB );
-  Build qw( util/Conscript );
-
-The values of the simple variables mentioned in the C<Export> list will be
-squirreled away by any subsequent C<Build> commands. The C<Export> command
-will only export Perl B<scalar> variables, that is, variables whose name
-begins with C<$>. Other variables, objects, etc. can be exported by
-reference--but all scripts will refer to the same object, and this object
-should be considered to be read-only by the subsidiary scripts and by the
-original exporting script. It's acceptable, however, to assign a new value
-to the exported scalar variable--that won't change the underlying variable
-referenced. This sequence, for example, is OK:
-
-  $env = new cons();
-  Export qw( env INCLUDE LIB );
-  Build qw( util/Conscript );
-  $env = new cons(CFLAGS => '-O');
-  Build qw( other/Conscript );
-
-It doesn't matter whether the variable is set before or after the C<Export>
-command. The important thing is the value of the variable at the time the
-C<Build> command is executed. This is what gets squirreled away. Any
-subsequent C<Export> commands, by the way, invalidate the first: you must
-mention all the variables you wish to export on each C<Export> command.
-
-
-=head2 The Import command
-
-Variables exported by the C<Export> command can be imported into subsidiary
-scripts by the C<Import> command. The subsidiary script always imports
-variables directly from the superior script. Consider this example:
-
-  Import qw( env INCLUDE );
-
-This is only legal if the parent script exported both C<$env> and
-C<$INCLUDE>. It also must have given each of these variables values. It is
-OK for the subsidiary script to only import a subset of the exported
-variables (in this example, C<$LIB>, which was exported by the previous
-example, is not imported).
-
-All the imported variables are automatically re-exported, so the sequence:
-
-  Import qw ( env INCLUDE );
-  Build qw ( beneath-me/Conscript );
-
-will supply both C<$env> and C<$INCLUDE> to the subsidiary file. If only
-C<$env> is to be exported, then the following will suffice:
-
-  Import qw ( env INCLUDE );
-  Export qw ( env );
-  Build qw ( beneath-me/Conscript );
-
-Needless to say, the variables may be modified locally before invoking
-C<Build> on the subsidiary script.
-
-
-=head2 Build script evaluation order
-
-The only constraint on the ordering of build scripts is that superior
-scripts are evaluated before their inferior scripts. The top-level
-F<Construct> file, for instance, is evaluated first, followed by any
-inferior scripts. This is all you really need to know about the evaluation
-order, since order is generally irrelevant. Consider the following C<Build>
-command:
-
-  Build qw(
-	drivers/display/Conscript
-	drivers/mouse/Conscript
-	parser/Conscript
-	utilities/Conscript
-  );
-
-We've chosen to put the script names in alphabetical order, simply because
-that's the most convenient for maintenance purposes. Changing the order will
-make no difference to the build.
-
-
-=head1 A Model for sharing files
-
-
-=head2 Some simple conventions
-
-In any complex software system, a method for sharing build products needs to
-be established. We propose a simple set of conventions which are trivial to
-implement with Cons, but very effective.
-
-The basic rule is to require that all build products which need to be shared
-between directories are shared via an intermediate directory. We have
-typically called this F<export>, and, in a C environment, provided
-conventional sub-directories of this directory, such as F<include>, F<lib>,
-F<bin>, etc.
-
-These directories are defined by the top-level F<Construct> file. A simple
-F<Construct> file for a B<Hello, World!> application, organized using
-multiple directories, might look like this:
-
-  # Construct file for Hello, World!
-
-  # Where to put all our shared products.
-  $EXPORT = '#export';
-
-  Export qw( CONS INCLUDE LIB BIN );
-
-  # Standard directories for sharing products.
-  $INCLUDE = "$EXPORT/include";
-  $LIB = "$EXPORT/lib";
-  $BIN = "$EXPORT/bin";
-
-  # A standard construction environment.
-  $CONS = new cons (
-	CPPPATH => $INCLUDE,	# Include path for C Compilations
-	LIBPATH => $LIB,	# Library path for linking programs
-	LIBS => '-lworld',	# List of standard libraries
-  );
-
-  Build qw(
-	hello/Conscript
-	world/Conscript
-  );
-
-The F<world> directory's F<Conscript> file looks like this:
-
-  # Conscript file for directory world
-  Import qw( CONS INCLUDE LIB );
-
-  # Install the products of this directory
-  Install $CONS $LIB, 'libworld.a';
-  Install $CONS $INCLUDE, 'world.h';
-
-  # Internal products
-  Library $CONS 'libworld.a', 'world.c';
-
-and the F<hello> directory's F<Conscript> file looks like this:
-
-  # Conscript file for directory hello
-  Import qw( CONS BIN );
-
-  # Exported products
-  Install $CONS $BIN, 'hello';
-
-  # Internal products
-  Program $CONS 'hello', 'hello.c';
-
-To construct a B<Hello, World!> program with this directory structure, go to
-the top-level directory, and invoke C<cons> with the appropriate
-arguments. In the following example, we tell Cons to build the directory
-F<export>. To build a directory, Cons recursively builds all known products
-within that directory (only if they need rebuilding, of course). If any of
-those products depend upon other products in other directories, then those
-will be built, too.
-
-  % cons export
-  Install world/world.h as export/include/world.h
-  cc -Iexport/include -c hello/hello.c -o hello/hello.o
-  cc -Iexport/include -c world/world.c -o world/world.o
-  ar r world/libworld.a world/world.o
-  ar: creating world/libworld.a
-  ranlib world/libworld.a
-  Install world/libworld.a as export/lib/libworld.a
-  cc -o hello/hello hello/hello.o -Lexport/lib -lworld
-  Install hello/hello as export/bin/hello
-
-
-=head2 Clean, understandable, location-independent scripts
-
-You'll note that the two F<Conscript> files are very clean and
-to-the-point. They simply specify products of the directory and how to build
-those products. The build instructions are minimal: they specify which
-construction environment to use, the name of the product, and the name of
-the inputs. Note also that the scripts are location-independent: if you wish
-to reorganize your source tree, you are free to do so: you only have to
-change the F<Construct> file (in this example), to specify the new locations
-of the F<Conscript> files. The use of an export tree makes this goal easy.
-
-Note, too, how Cons takes care of little details for you. All the F<export>
-directories, for example, were made automatically. And the installed files
-were really hard-linked into the respective export directories, to save
-space and time. This attention to detail saves considerable work, and makes
-it even easier to produce simple, maintainable scripts.
-
-
-=head1 Separating source and build trees
-
-It's often desirable to keep any derived files from the build completely
-separate from the source files. This makes it much easier to keep track of
-just what is a source file, and also makes it simpler to handle B<variant>
-builds, especially if you want the variant builds to co-exist.
-
-
-=head2 Separating build and source directories using the Link command
-
-Cons provides a simple mechanism that handles all of these requirements. The
-C<Link> command is invoked as in this example:
-
-  Link 'build' => 'src';
-
-The specified directories are ``linked'' to the specified source
-directory. Let's suppose that you setup a source directory, F<src>, with the
-sub-directories F<world> and F<hello> below it, as in the previous
-example. You could then substitute for the original build lines the
-following:
-
-  Build qw(
-	build/world/Conscript
-	build/hello/Conscript
-  );
-
-Notice that you treat the F<Conscript> file as if it existed in the build
-directory. Now if you type the same command as before, you will get the
-following results:
-
-  % cons export
-  Install build/world/world.h as export/include/world.h
-  cc -Iexport/include -c build/hello/hello.c -o build/hello/hello.o
-  cc -Iexport/include -c build/world/world.c -o build/world/world.o
-  ar r build/world/libworld.a build/world/world.o
-  ar: creating build/world/libworld.a
-  ranlib build/world/libworld.a
-  Install build/world/libworld.a as export/lib/libworld.a
-  cc -o build/hello/hello build/hello/hello.o -Lexport/lib -lworld
-  Install build/hello/hello as export/bin/hello
-
-Again, Cons has taken care of the details for you. In particular, you will
-notice that all the builds are done using source files and object files from
-the build directory. For example, F<build/world/world.o> is compiled from
-F<build/world/world.c>, and F<export/include/world.h> is installed from
-F<build/world/world.h>. This is accomplished on most systems by the simple
-expedient of ``hard'' linking the required files from each source directory
-into the appropriate build directory.
-
-The links are maintained correctly by Cons, no matter what you do to the
-source directory. If you modify a source file, your editor may do this ``in
-place'' or it may rename it first and create a new file. In the latter case,
-any hard link will be lost. Cons will detect this condition the next time
-the source file is needed, and will relink it appropriately.
-
-You'll also notice, by the way, that B<no> changes were required to the
-underlying F<Conscript> files. And we can go further, as we shall see in the
-next section.
-
-=head2 Explicit references to the source directory
-
-When using the C<Link> command on some operating systems or with some
-tool chains, it's sometimes useful to have a command actually use
-the path name to the source directory, not the build directory.  For
-example, on systems that must copy, not "hard link," the F<src/> and
-F<build/> copies of C<Linked> files, using the F<src/> path of a file
-name might make an editor aware that a syntax error must be fixed in the
-source directory, not the build directory.
-
-You can tell Cons that you want to use the "source path" for a file by
-preceding the file name with a ``!'' (exclamation point).  For example,
-if we add a ``!'' to the beginning of a source file:
-
-  Program $env "foo", "!foo.c";	# Notice initial ! on foo.c
-
-Cons will compile the target as follows:
-
-  cc -c src/foo.c -o build/foo.o
-  cc -o build/foo build/foo.o
-
-Notice that Cons has compiled the program from the the F<src/foo.c>
-source file.  Without the initial ``!'', Cons would have compiled the
-program using the F<build/foo.c> path name.
-
-
-
-=head1 Variant builds
-
-
-=head2 Hello, World! for baNaNa and peAcH OS's
-
-Variant builds require just another simple extension. Let's take as an
-example a requirement to allow builds for both the baNaNa and peAcH
-operating systems. In this case, we are using a distributed file system,
-such as NFS to access the particular system, and only one or the other of
-the systems has to be compiled for any given invocation of C<cons>. Here's
-one way we could set up the F<Construct> file for our B<Hello, World!>
-application:
-
-  # Construct file for Hello, World!
-
-  die qq(OS must be specified) unless $OS = $ARG{OS};
-  die qq(OS must be "peach" or "banana")
-	if $OS ne "peach" && $OS ne "banana";
-
-  # Where to put all our shared products.
-  $EXPORT = "#export/$OS";
-
-  Export qw( CONS INCLUDE LIB BIN );
-
-  # Standard directories for sharing products.
-  $INCLUDE = "$EXPORT/include";
-  $LIB = "$EXPORT/lib";
-  $BIN = "$EXPORT/bin";
-
-  # A standard construction environment.
-  $CONS = new cons (
-	CPPPATH => $INCLUDE,	# Include path for C Compilations
-	LIBPATH => $LIB,	# Library path for linking programs
-	LIBS => '-lworld',	# List of standard libraries
-  );
-
-  # $BUILD is where we will derive everything.
-  $BUILD = "#build/$OS";
-
-  # Tell cons where the source files for $BUILD are.
-  Link $BUILD => 'src';
-
-  Build (
-	"$BUILD/hello/Conscript",
-	"$BUILD/world/Conscript",
-  );
-
-Now if we login to a peAcH system, we can build our B<Hello, World!>
-application for that platform:
-
-  % cons export OS=peach
-  Install build/peach/world/world.h as export/peach/include/world.h
-  cc -Iexport/peach/include -c build/peach/hello/hello.c -o build/peach/hello/hello.o
-  cc -Iexport/peach/include -c build/peach/world/world.c -o build/peach/world/world.o
-  ar r build/peach/world/libworld.a build/peach/world/world.o
-  ar: creating build/peach/world/libworld.a
-  ranlib build/peach/world/libworld.a
-  Install build/peach/world/libworld.a as export/peach/lib/libworld.a
-  cc -o build/peach/hello/hello build/peach/hello/hello.o -Lexport/peach/lib -lworld
-  Install build/peach/hello/hello as export/peach/bin/hello
-
-
-=head2 Variations on a theme
-
-Other variations of this model are possible. For example, you might decide
-that you want to separate out your include files into platform dependent and
-platform independent files. In this case, you'd have to define an
-alternative to C<$INCLUDE> for platform-dependent files. Most F<Conscript>
-files, generating purely platform-independent include files, would not have
-to change.
-
-You might also want to be able to compile your whole system with debugging
-or profiling, for example, enabled. You could do this with appropriate
-command line options, such as C<DEBUG=on>. This would then be translated
-into the appropriate platform-specific requirements to enable debugging
-(this might include turning off optimization, for example). You could
-optionally vary the name space for these different types of systems, but, as
-we'll see in the next section, it's not B<essential> to do this, since Cons
-is pretty smart about rebuilding things when you change options.
-
-
-=head1 Signatures
-
-Cons uses file B<signatures> to decide if a derived file is out-of-date
-and needs rebuilding.  In essence, if the contents of a file change,
-or the manner in which the file is built changes, the file's signature
-changes as well.  This allows Cons to decide with certainty when a file
-needs rebuilding, because Cons can detect, quickly and reliably, whether
-any of its dependency files have been changed.
-
-
-=head2 MD5 content and build signatures
-
-Cons uses the B<MD5> (B<Message Digest 5>) algorithm to compute file
-signatures.  The MD5 algorithm computes a strong cryptographic checksum
-for any given input string.  Cons can, based on configuration, use two
-different MD5 signatures for a given file:
-
-The B<content signature> of a file is an MD5 checksum of the file's
-contents.  Consequently, when the contents of a file change, its content
-signature changes as well.
-
-The B<build signature> of a file is a combined MD5 checksum of:
-
-=over 4
-
-the signatures of all the input files used to build the file
-
-the signatures of all dependency files discovered by source scanners
-(for example, C<.h> files)
-
-the signatures of all dependency files specified explicitly via the
-C<Depends> method)
-
-the command-line string used to build the file
-
-=back
-
-The build signature is, in effect, a digest of all the dependency
-information for the specified file.  Consequently, a file's build
-signature changes whenever any part of its dependency information
-changes: a new file is added, the contents of a file on which it depends
-change, there's a change to the command line used to build the file (or
-any of its dependency files), etc.
-
-For example, in the previous section, the build signature of the
-F<world.o> file will include:
-
-=over 4
-
-the signature of the F<world.c> file
-
-the signatures of any header files that Cons detects are included,
-directly or indirectly, by F<world.c>
-
-the text of the actual command line was used to generate F<world.o>
-
-=back
-
-Similarly, the build signature of the F<libworld.a> file will include
-all the signatures of its constituents (and hence, transitively, the
-signatures of B<their> constituents), as well as the command line that
-created the file.
-
-Note that there is no need for a derived file to depend upon any
-particular F<Construct> or F<Conscript> file.  If changes to these files
-affect a file, then this will be automatically reflected in its build
-signature, since relevant parts of the command line are included in the
-signature. Unrelated F<Construct> or F<Conscript> changes will have no
-effect.
-
-
-=head2 Storing signatures in .consign files
-
-Before Cons exits, it stores the calculated signatures for all of the
-files it built or examined in F<.consign> files, one per directory.
-Cons uses this stored information on later invocations to decide if
-derived files need to be rebuilt.
-
-After the previous example was compiled, the F<.consign> file in the
-F<build/peach/world> directory looked like this:
-
-  world.h:985533370 - d181712f2fdc07c1f05d97b16bfad904
-  world.o:985533372 2a0f71e0766927c0532977b0d2158981
-  world.c:985533370 - c712f77189307907f4189b5a7ab62ff3
-  libworld.a:985533374 69e568fc5241d7d25be86d581e1fb6aa
-
-After the file name and colon, the first number is a timestamp of the
-file's modification time (on UNIX systems, this is typically the number
-of seconds since January 1st, 1970).  The second value is the build
-signature of the file (or ``-'' in the case of files with no build
-signature--that is, source files).  The third value, if any, is the
-content signature of the file.
-
-
-=head2 Using build signatures to decide when to rebuild files
-
-When Cons is deciding whether to build or rebuild a derived file, it
-first computes the file's current build signature.  If the file doesn't
-exist, it must obviously be built.
-
-If, however, the file already exists, Cons next compares the
-modification timestamp of the file against the timestamp value in
-the F<.consign> file.  If the timestamps match, Cons compares the
-newly-computed build signature against the build signature in the
-F<.consign> file.  If the timestamps do not match or the build
-signatures do not match, the derived file is rebuilt.
-
-After the file is built or rebuilt, Cons arranges to store the
-newly-computed build signature in the F<.consign> file when it exits.
-
-
-=head2 Signature example
-
-The use of these signatures is an extremely simple, efficient, and
-effective method of improving--dramatically--the reproducibility of a
-system.
-
-We'll demonstrate this with a simple example:
-
-  # Simple "Hello, World!" Construct file
-  $CFLAGS = '-g' if $ARG{DEBUG} eq 'on';
-  $CONS = new cons(CFLAGS => $CFLAGS);
-  Program $CONS 'hello', 'hello.c';
-
-Notice how Cons recompiles at the appropriate times:
-
-  % cons hello
-  cc -c hello.c -o hello.o
-  cc -o hello hello.o
-  % cons hello
-  cons: "hello" is up-to-date.
-  % cons DEBUG=on hello
-  cc -g -c hello.c -o hello.o
-  cc -o hello hello.o
-  % cons DEBUG=on hello
-  cons: "hello" is up-to-date.
-  % cons hello
-  cc -c hello.c -o hello.o
-  cc -o hello hello.o
-
-
-=head2 Source-file signature configuration
-
-Cons provides a C<SourceSignature> method that allows you to configure
-how the signature should be calculated for any source file when its
-signature is being used to decide if a dependent file is up-to-date.
-The arguments to the C<SourceSignature> method consist of one or more
-pairs of strings:
-
-  SourceSignature 'auto/*.c' => 'content',
-		  '*' => 'stored-content';
-
-The first string in each pair is a pattern to match against derived file
-path names. The pattern is a file-globbing pattern, not a Perl regular
-expression; the pattern <*.l> will match all Lex source files.  The C<*>
-wildcard will match across directory separators; the pattern C<foo/*.c>
-would match all C source files in any subdirectory underneath the C<foo>
-subdirectory.
-
-The second string in each pair contains one of the following keywords to
-specify how signatures should be calculated for source files that match
-the pattern.  The available keywords are:
-
-=over 4
-
-=item content
-
-Use the content signature of the source file when calculating signatures
-of files that depend on it.  This guarantees correct calculation of the
-file's signature for all builds, by telling Cons to read the contents of
-a source file to calculate its content signature each time it is run.
-
-=item stored-content
-
-Use the source file's content signature as stored in the F<.consign>
-file, provided the file's timestamp matches the cached timestamp value
-in the F<.consign> file.  This optimizes performance, with the slight
-risk of an incorrect build if a source file's contents have been changed
-so quickly after its previous update that the timestamp still matches
-the stored timestamp in the F<.consign> file even though the contents
-have changed.
-
-=back
-
-The Cons default behavior of always calculating a source file's
-signature from the file's contents is equivalent to specifying:
-
-  SourceSignature '*' => 'content';
-
-The C<*> will match all source files.  The C<content> keyword
-specifies that Cons will read the contents of a source file to calculate
-its signature each time it is run.
-
-A useful global performance optimization is:
-
-  SourceSignature '*' => 'stored-content';
-
-This specifies that Cons will use pre-computed content signatures
-from F<.consign> files, when available, rather than re-calculating a
-signature from the the source file's contents each time Cons is run.  In
-practice, this is safe for most build situations, and only a problem
-when source files are changed automatically (by scripts, for example).
-The Cons default, however, errs on the side of guaranteeing a correct
-build in all situations.
-
-Cons tries to match source file path names against the patterns in the
-order they are specified in the C<SourceSignature> arguments:
-
-  SourceSignature '/usr/repository/objects/*' => 'stored-content',
-		  '/usr/repository/*' => 'content',
-		  '*.y' => 'content',
-		  '*' => 'stored-content';
-
-In this example, all source files under the F</usr/repository/objects>
-directory will use F<.consign> file content signatures, source files
-anywhere else underneath F</usr/repository> will not use F<.consign>
-signature values, all Yacc source files (C<*.y>) anywhere else will not
-use F<.consign> signature values, and any other source file will use
-F<.consign> signature values.
-
-
-=head2 Derived-file signature configuration
-
-Cons provides a C<SIGNATURE> construction variable that allows you to
-configure how signatures are calculated for any derived file when its
-signature is being used to decide if a dependent file is up-to-date.
-The value of the C<SIGNATURE> construction variable is a Perl array
-reference that holds one or more pairs of strings, like the arguments to
-the C<SourceSignature> method.
-
-The first string in each pair is a pattern to match against derived file
-path names. The pattern is a file-globbing pattern, not a Perl regular
-expression; the pattern `*.obj' will match all (Win32) object files.
-The C<*> wildcard will match across directory separators; the pattern
-`foo/*.a' would match all (UNIX) library archives in any subdirectory
-underneath the foo subdirectory.
-
-The second string in each pair contains one of the following keywords
-to specify how signatures should be calculated for derived files that
-match the pattern.  The available keywords are the same as for the
-C<SourceSignature> method, with an additional keyword:
-
-=over 4
-
-=item build
-
-Use the build signature of the derived file when calculating signatures
-of files that depend on it.  This guarantees correct builds by forcing
-Cons to rebuild any and all files that depend on the derived file.
-
-=item content
-
-Use the content signature of the derived file when calculating signatures
-of files that depend on it.  This guarantees correct calculation of the
-file's signature for all builds, by telling Cons to read the contents of
-a derived file to calculate its content signature each time it is run.
-
-=item stored-content
-
-Use the derived file's content signature as stored in the F<.consign>
-file, provided the file's timestamp matches the cached timestamp value
-in the F<.consign> file.  This optimizes performance, with the slight
-risk of an incorrect build if a derived file's contents have been
-changed so quickly after a Cons build that the file's timestamp still
-matches the stored timestamp in the F<.consign> file.
-
-=back
-
-The Cons default behavior (as previously described) for using
-derived-file signatures is equivalent to:
-
-  $env = new cons(SIGNATURE => ['*' => 'build']);
-
-The C<*> will match all derived files.  The C<build> keyword specifies
-that all derived files' build signatures will be used when calculating
-whether a dependent file is up-to-date.
-
-A useful alternative default C<SIGNATURE> configuration for many sites:
-
-  $env = new cons(SIGNATURE => ['*' => 'content']);
-
-In this configuration, derived files have their signatures calculated
-from the file contents.  This adds slightly to Cons' workload, but has
-the useful effect of "stopping" further rebuilds if a derived file is
-rebuilt to exactly the same file contents as before, which usually
-outweighs the additional computation Cons must perform.
-
-For example, changing a comment in a C file and recompiling should
-generate the exact same object file (assuming the compiler doesn't
-insert a timestamp in the object file's header).  In that case,
-specifying C<content> or C<stored-content> for the signature calculation
-will cause Cons to recognize that the object file did not actually
-change as a result of being rebuilt, and libraries or programs that
-include the object file will not be rebuilt.  When C<build> is
-specified, however, Cons will only "know" that the object file was
-rebuilt, and proceed to rebuild any additional files that include the
-object file.
-
-Note that Cons tries to match derived file path names against the
-patterns in the order they are specified in the C<SIGNATURE> array
-reference:
-
-  $env = new cons(SIGNATURE => ['foo/*.o' => 'build',
-				'*.o' => 'content',
-				'*.a' => 'stored-content',
-				'*' => 'content']);
-
-In this example, all object files underneath the F<foo> subdirectory
-will use build signatures, all other object files (including object
-files underneath other subdirectories!) will use F<.consign> file
-content signatures, libraries will use F<.consign> file build
-signatures, and all other derived files will use content signatures.
-
-
-=head2 Debugging signature calculation
-
-Cons provides a C<-S> option that can be used to specify what internal
-Perl package Cons should use to calculate signatures.  The default Cons
-behavior is equivalent to specifying C<-S md5> on the command line.
-
-The only other package (currently) available is an C<md5::debug>
-package that prints out detailed information about the MD5 signature
-calculations performed by Cons:
-
-  % cons -S md5::debug hello
-  sig::md5::srcsig(hello.c)
-          => |52d891204c62fe93ecb95281e1571938|
-  sig::md5::collect(52d891204c62fe93ecb95281e1571938)
-          => |fb0660af4002c40461a2f01fbb5ffd03|
-  sig::md5::collect(52d891204c62fe93ecb95281e1571938,
-                    fb0660af4002c40461a2f01fbb5ffd03,
-                    cc   -c %< -o %>)
-          => |f7128da6c3fe3c377dc22ade70647b39|
-  sig::md5::current(||
-                 eq |f7128da6c3fe3c377dc22ade70647b39|)
-  cc -c hello.c -o hello.o
-  sig::md5::collect()
-          => |d41d8cd98f00b204e9800998ecf8427e|
-  sig::md5::collect(f7128da6c3fe3c377dc22ade70647b39,
-                    d41d8cd98f00b204e9800998ecf8427e,
-                    cc  -o %> %<  )
-          => |a0bdce7fd09e0350e7efbbdb043a00b0|
-  sig::md5::current(||
-                 eq |a0bdce7fd09e0350e7efbbdb043a00b0|)
-  cc -o hello, hello.o
-
-
-=head1 Code Repositories
-
-Many software development organizations will have one or more central
-repository directory trees containing the current source code for one or
-more projects, as well as the derived object files, libraries, and
-executables.  In order to reduce unnecessary recompilation, it is useful to
-use files from the repository to build development software--assuming, of
-course, that no newer dependency file exists in the local build tree.
-
-
-=head2 Repository
-
-Cons provides a mechanism to specify a list of code repositories that will
-be searched, in-order, for source files and derived files not found in the
-local build directory tree.
-
-The following lines in a F<Construct> file will instruct Cons to look first
-under the F</usr/experiment/repository> directory and then under the
-F</usr/product/repository> directory:
-
-  Repository qw (
-	/usr/experiment/repository
-	/usr/product/repository
-  );
-
-The repository directories specified may contain source files, derived files
-(objects, libraries and executables), or both.  If there is no local file
-(source or derived) under the directory in which Cons is executed, then the
-first copy of a same-named file found under a repository directory will be
-used to build any local derived files.
-
-Cons maintains one global list of repositories directories.  Cons will
-eliminate the current directory, and any non-existent directories, from the
-list.
-
-
-=head2 Finding the Construct file in a Repository
-
-Cons will also search for F<Construct> and F<Conscript> files in the
-repository tree or trees.  This leads to a chicken-and-egg situation,
-though: how do you look in a repository tree for a F<Construct> file if the
-F<Construct> file tells you where the repository is?  To get around this,
-repositories may be specified via C<-R> options on the command line:
-
-  % cons -R /usr/experiment/repository -R /usr/product/repository .
-
-Any repository directories specified in the F<Construct> or F<Conscript>
-files will be appended to the repository directories specified by
-command-line C<-R> options.
-
-=head2 Repository source files
-
-If the source code (include the F<Conscript> file) for the library version
-of the I<Hello, World!> C application is in a repository (with no derived
-files), Cons will use the repository source files to create the local object
-files and executable file:
-
-  % cons -R /usr/src_only/repository hello
-  gcc -c /usr/src_only/repository/hello.c -o hello.o
-  gcc -c /usr/src_only/repository/world.c -o world.o
-  ar r libworld.a world.o
-  ar: creating libworld.a
-  ranlib libworld.a
-  gcc -o hello hello.o libworld.a
-
-Creating a local source file will cause Cons to rebuild the appropriate
-derived file or files:
-
-  % pico world.c
-    [EDIT]
-  % cons -R /usr/src_only/repository hello
-  gcc -c world.c -o world.o
-  ar r libworld.a world.o
-  ar: creating libworld.a
-  ranlib libworld.a
-  gcc -o hello hello.o libworld.a
-
-And removing the local source file will cause Cons to revert back to
-building the derived files from the repository source:
-
-  % rm world.c
-  % cons -R /usr/src_only/repository hello
-  gcc -c /usr/src_only/repository/world.c -o world.o
-  ar r libworld.a world.o
-  ar: creating libworld.a
-  ranlib libworld.a
-  gcc -o hello hello.o libworld.a
-
-
-=head2 Repository derived files
-
-If a repository tree contains derived files (usually object files,
-libraries, or executables), Cons will perform its normal signature
-calculation to decide whether the repository file is up-to-date or a derived
-file must be built locally.  This means that, in order to ensure correct
-signature calculation, a repository tree must also contain the F<.consign>
-files that were created by Cons when generating the derived files.
-
-This would usually be accomplished by building the software in the
-repository (or, alternatively, in a build directory, and then copying the
-result to the repository):
-
-  % cd /usr/all/repository
-  % cons hello
-  gcc -c hello.c -o hello.o
-  gcc -c world.c -o world.o
-  ar r libworld.a world.o
-  ar: creating libworld.a
-  ranlib libworld.a
-  gcc -o hello hello.o libworld.a
-
-(This is safe even if the F<Construct> file lists the F</usr/all/repository>
-directory in a C<Repository> command because Cons will remove the current
-directory from the repository list.)
-
-Now if we want to build a copy of the application with our own F<hello.c>
-file, we only need to create the one necessary source file, and use the
-C<-R> option to have Cons use other files from the repository:
-
-  % mkdir $HOME/build1
-  % cd $HOME/build1
-  % ed hello.c
-    [EDIT]
-  % cons -R /usr/all/repository hello
-  gcc -c hello.c -o hello.o
-  gcc -o hello hello.o /usr/all/repository/libworld.a
-
-Notice that Cons has not bothered to recreate a local F<libworld.a> library
-(or recompile the F<world.o> module), but instead uses the already-compiled
-version from the repository.
-
-Because the MD5 signatures that Cons puts in the F<.consign> file contain
-timestamps for the derived files, the signature timestamps must match the
-file timestamps for a signature to be considered valid.
-
-Some software systems may alter the timestamps on repository files (by
-copying them, e.g.), in which case Cons will, by default, assume the
-repository signatures are invalid and rebuild files unnecessarily.  This
-behavior may be altered by specifying:
-
-  Repository_Sig_Times_OK 0;
-
-This tells Cons to ignore timestamps when deciding whether a signature is
-valid.  (Note that avoiding this sanity check means there must be proper
-control over the repository tree to ensure that the derived files cannot be
-modified without updating the F<.consign> signature.)
-
-
-=head2 Local copies of files
-
-If the repository tree contains the complete results of a build, and we try
-to build from the repository without any files in our local tree, something
-moderately surprising happens:
-
-  % mkdir $HOME/build2
-  % cd $HOME/build2
-  % cons -R /usr/all/repository hello
-  cons: "hello" is up-to-date.
-
-Why does Cons say that the F<hello> program is up-to-date when there is no
-F<hello> program in the local build directory?  Because the repository (not
-the local directory) contains the up-to-date F<hello> program, and Cons
-correctly determines that nothing needs to be done to rebuild this
-up-to-date copy of the file.
-
-There are, however, many times in which it is appropriate to ensure that a
-local copy of a file always exists.  A packaging or testing script, for
-example, may assume that certain generated files exist locally.  Instead of
-making these subsidiary scripts aware of the repository directory, the
-C<Local> command may be added to a F<Construct> or F<Conscript> file to
-specify that a certain file or files must appear in the local build
-directory:
-
-  Local qw(
-	hello
-  );
-
-Then, if we re-run the same command, Cons will make a local copy of the
-program from the repository copy (telling you that it is doing so):
-
-  % cons -R /usr/all/repository hello
-  Local copy of hello from /usr/all/repository/hello
-  cons: "hello" is up-to-date.
-
-Notice that, because the act of making the local copy is not considered a
-"build" of the F<hello> file, Cons still reports that it is up-to-date.
-
-Creating local copies is most useful for files that are being installed into
-an intermediate directory (for sharing with other directories) via the
-C<Install> command.  Accompanying the C<Install> command for a file with a
-companion C<Local> command is so common that Cons provides a
-C<Install_Local> command as a convenient way to do both:
-
-  Install_Local $env, '#export', 'hello';
-
-is exactly equivalent to:
-
-  Install $env '#export', 'hello';
-  Local '#export/hello';
-
-Both the C<Local> and C<Install_Local> commands update the local F<.consign>
-file with the appropriate file signatures, so that future builds are
-performed correctly.
-
-
-=head2 Repository dependency analysis
-
-Due to its built-in scanning, Cons will search the specified repository
-trees for included F<.h> files.  Unless the compiler also knows about the
-repository trees, though, it will be unable to find F<.h> files that only
-exist in a repository.  If, for example, the F<hello.c> file includes the
-F<hello.h> file in its current directory:
-
-  % cons -R /usr/all/repository hello
-  gcc -c /usr/all/repository/hello.c -o hello.o
-  /usr/all/repository/hello.c:1: hello.h: No such file or directory
-
-Solving this problem forces some requirements onto the way construction
-environments are defined and onto the way the C C<#include> preprocessor
-directive is used to include files.
-
-In order to inform the compiler about the repository trees, Cons will add
-appropriate C<-I> flags to the compilation commands.  This means that the
-C<CPPPATH> variable in the construction environment must explicitly specify
-all subdirectories which are to be searched for included files, including the
-current directory.  Consequently, we can fix the above example by changing
-the environment creation in the F<Construct> file as follows:
-
-  $env = new cons(
-	CC	=> 'gcc',
-	CPPPATH	=> '.',
-	LIBS	=> 'libworld.a',
-  );
-
-Due to the definition of the C<CPPPATH> variable, this yields, when we
-re-execute the command:
-
-  % cons -R /usr/all/repository hello
-  gcc -c -I. -I/usr/all/repository /usr/all/repository/hello.c -o hello.o
-  gcc -o hello hello.o /usr/all/repository/libworld.a
-
-The order of the C<-I> flags replicates, for the C preprocessor, the same
-repository-directory search path that Cons uses for its own dependency
-analysis.  If there are multiple repositories and multiple C<CPPPATH>
-directories, Cons will append the repository directories to the beginning of
-each C<CPPPATH> directory, rapidly multiplying the number of C<-I> flags.
-As an extreme example, a F<Construct> file containing:
-
-  Repository qw(
-	/u1
-	/u2
-  );
-
-  $env = new cons(
-	CPPPATH	=> 'a:b:c',
-  );
-
-Would yield a compilation command of:
-
-  cc -Ia -I/u1/a -I/u2/a -Ib -I/u1/b -I/u2/b -Ic -I/u1/c -I/u2/c -c hello.c -o hello.o
-
-In order to shorten the command lines as much as possible, Cons will
-remove C<-I> flags for any directories, locally or in the repositories,
-which do not actually exist.  (Note that the C<-I> flags are not included
-in the MD5 signature calculation for the target file, so the target will
-not be recompiled if the compilation command changes due to a directory
-coming into existence.)
-
-Because Cons relies on the compiler's C<-I> flags to communicate the
-order in which repository directories must be searched, Cons' handling
-of repository directories is fundamentally incompatible with using
-double-quotes on the C<#include> directives in any C source code that
-you plan to modify:
-
-  #include "file.h"	/* DON'T USE DOUBLE-QUOTES LIKE THIS */
-
-This is because most C preprocessors, when faced with such a directive, will
-always first search the directory containing the source file.  This
-undermines the elaborate C<-I> options that Cons constructs to make the
-preprocessor conform to its preferred search path.
-
-Consequently, when using repository trees in Cons, B<always> use
-angle-brackets for included files in any C source (.c or .h) files that
-you plan to modify locally:
-
-  #include <file.h>	/* USE ANGLE-BRACKETS INSTEAD */
-
-Code that will not change can still safely use double quotes on #include
-lines.
-
-
-=head2 Repository_List
-
-Cons provides a C<Repository_List> command to return a list of all
-repository directories in their current search order.  This can be used for
-debugging, or to do more complex Perl stuff:
-
-  @list = Repository_List;
-  print join(' ', @list), "\n";
-
-
-=head2 Repository interaction with other Cons features
-
-Cons' handling of repository trees interacts correctly with other Cons
-features--which is to say, it generally does what you would expect.
-
-Most notably, repository trees interact correctly, and rather powerfully,
-with the 'Link' command.  A repository tree may contain one or more
-subdirectories for version builds established via C<Link> to a source
-subdirectory.  Cons will search for derived files in the appropriate build
-subdirectories under the repository tree.
-
-
-=head1 Default targets
-
-Until now, we've demonstrated invoking Cons with an explicit target
-to build:
-
-  % cons hello
-
-Normally, Cons does not build anything unless a target is specified,
-but specifying '.' (the current directory) will build everything:
-
-  % cons		# does not build anything
-
-  % cons .		# builds everything under the top-level directory
-
-Adding the C<Default> method to any F<Construct> or F<Conscript> file will add
-the specified targets to a list of default targets.  Cons will build
-these defaults if there are no targets specified on the command line.
-So adding the following line to the top-level F<Construct> file will mimic
-Make's typical behavior of building everything by default:
-
-  Default '.';
-
-The following would add the F<hello> and F<goodbye> commands (in the
-same directory as the F<Construct> or F<Conscript> file) to the default list:
-
-  Default qw(
-	hello
-	goodbye
-  );
-
-The C<Default> method may be used more than once to add targets to the
-default list.
-
-=head1 Selective builds
-
-Cons provides two methods for reducing the size of given build. The first is
-by specifying targets on the command line, and the second is a method for
-pruning the build tree. We'll consider target specification first.
-
-
-=head2 Selective targeting
-
-Like make, Cons allows the specification of ``targets'' on the command
-line. Cons targets may be either files or directories. When a directory is
-specified, this is simply a short-hand notation for every derivable
-product--that Cons knows about--in the specified directory and below. For
-example:
-
-  % cons build/hello/hello.o
-
-means build F<hello.o> and everything that F<hello.o> might need. This is
-from a previous version of the B<Hello, World!> program in which F<hello.o>
-depended upon F<export/include/world.h>. If that file is not up-to-date
-(because someone modified F<src/world/world.h)>, then it will be rebuilt,
-even though it is in a directory remote from F<build/hello>.
-
-In this example:
-
-  % cons build
-
-Everything in the F<build> directory is built, if necessary. Again, this may
-cause more files to be built. In particular, both F<export/include/world.h>
-and F<export/lib/libworld.a> are required by the F<build/hello> directory,
-and so they will be built if they are out-of-date.
-
-If we do, instead:
-
-  % cons export
-
-then only the files that should be installed in the export directory will be
-rebuilt, if necessary, and then installed there. Note that C<cons build>
-might build files that C<cons export> doesn't build, and vice-versa.
-
-
-=head2 No ``special'' targets
-
-With Cons, make-style ``special'' targets are not required. The simplest
-analog with Cons is to use special F<export> directories, instead. Let's
-suppose, for example, that you have a whole series of unit tests that are
-associated with your code. The tests live in the source directory near the
-code. Normally, however, you don't want to build these tests. One solution
-is to provide all the build instructions for creating the tests, and then to
-install the tests into a separate part of the tree. If we install the tests
-in a top-level directory called F<tests>, then:
-
-  % cons tests
-
-will build all the tests.
-
-  % cons export
-
-will build the production version of the system (but not the tests), and:
-
-  % cons build
-
-should probably be avoided (since it will compile tests unnecessarily).
-
-If you want to build just a single test, then you could explicitly name the
-test (in either the F<tests> directory or the F<build> directory). You could
-also aggregate the tests into a convenient hierarchy within the tests
-directory. This hierarchy need not necessarily match the source hierarchy,
-in much the same manner that the include hierarchy probably doesn't match
-the source hierarchy (the include hierarchy is unlikely to be more than two
-levels deep, for C programs).
-
-If you want to build absolutely everything in the tree (subject to whatever
-options you select), you can use:
-
-  % cons .
-
-This is not particularly efficient, since it will redundantly walk all the
-trees, including the source tree. The source tree, of course, may have
-buildable objects in it--nothing stops you from doing this, even if you
-normally build in a separate build tree.
-
-
-=head1 Build Pruning
-
-In conjunction with target selection, B<build pruning> can be used to reduce
-the scope of the build. In the previous peAcH and baNaNa example, we have
-already seen how script-driven build pruning can be used to make only half
-of the potential build available for any given invocation of C<cons>. Cons
-also provides, as a convenience, a command line convention that allows you
-to specify which F<Conscript> files actually get ``built''--that is,
-incorporated into the build tree. For example:
-
-  % cons build +world
-
-The C<+> argument introduces a Perl regular expression. This must, of
-course, be quoted at the shell level if there are any shell meta-characters
-within the expression. The expression is matched against each F<Conscript>
-file which has been mentioned in a C<Build> statement, and only those
-scripts with matching names are actually incorporated into the build
-tree. Multiple such arguments are allowed, in which case a match against any
-of them is sufficient to cause a script to be included.
-
-In the example, above, the F<hello> program will not be built, since Cons
-will have no knowledge of the script F<hello/Conscript>. The F<libworld.a>
-archive will be built, however, if need be.
-
-There are a couple of uses for build pruning via the command line. Perhaps
-the most useful is the ability to make local changes, and then, with
-sufficient knowledge of the consequences of those changes, restrict the size
-of the build tree in order to speed up the rebuild time. A second use for
-build pruning is to actively prevent the recompilation of certain files that
-you know will recompile due to, for example, a modified header file. You may
-know that either the changes to the header file are immaterial, or that the
-changes may be safely ignored for most of the tree, for testing
-purposes.With Cons, the view is that it is pragmatic to admit this type of
-behavior, with the understanding that on the next full build everything that
-needs to be rebuilt will be. There is no equivalent to a ``make touch''
-command, to mark files as permanently up-to-date. So any risk that is
-incurred by build pruning is mitigated. For release quality work, obviously,
-we recommend that you do not use build pruning (it's perfectly OK to use
-during integration, however, for checking compilation, etc. Just be sure to
-do an unconstrained build before committing the integration).
-
-
-=head1 Temporary overrides
-
-Cons provides a very simple mechanism for overriding aspects of a build. The
-essence is that you write an override file containing one or more
-C<Override> commands, and you specify this on the command line, when you run
-C<cons>:
-
-  % cons -o over export
-
-will build the F<export> directory, with all derived files subject to the
-overrides present in the F<over> file. If you leave out the C<-o> option,
-then everything necessary to remove all overrides will be rebuilt.
-
-
-=head2 Overriding environment variables
-
-The override file can contain two types of overrides. The first is incoming
-environment variables. These are normally accessible by the F<Construct>
-file from the C<%ENV> hash variable. These can trivially be overridden in
-the override file by setting the appropriate elements of C<%ENV> (these
-could also be overridden in the user's environment, of course).
-
-
-=head2 The Override command
-
-The second type of override is accomplished with the C<Override> command,
-which looks like this:
-
-  Override <regexp>, <var1> => <value1>, <var2> => <value2>, ...;
-
-The regular expression I<regexp> is matched against every derived file that
-is a candidate for the build. If the derived file matches, then the
-variable/value pairs are used to override the values in the construction
-environment associated with the derived file.
-
-Let's suppose that we have a construction environment like this:
-
-  $CONS = new cons(
-	COPT => '',
-	CDBG => '-g',
-	CFLAGS => '%COPT %CDBG',
-  );
-
-Then if we have an override file F<over> containing this command:
-
-  Override '\.o$', COPT => '-O', CDBG => '';
-
-then any C<cons> invocation with C<-o over> that creates F<.o> files via
-this environment will cause them to be compiled with C<-O >and no C<-g>. The
-override could, of course, be restricted to a single directory by the
-appropriate selection of a regular expression.
-
-Here's the original version of the Hello, World! program, built with this
-environment. Note that Cons rebuilds the appropriate pieces when the
-override is applied or removed:
-
-  % cons hello
-  cc -g -c hello.c -o hello.o
-  cc -o hello hello.o
-  % cons -o over hello
-  cc -O -c hello.c -o hello.o
-  cc -o hello hello.o
-  % cons -o over hello
-  cons: "hello" is up-to-date.
-  % cons hello
-  cc -g -c hello.c -o hello.o
-  cc -o hello hello.o
-
-It's important that the C<Override> command only be used for temporary,
-on-the-fly overrides necessary for development because the overrides are not
-platform independent and because they rely too much on intimate knowledge of
-the workings of the scripts. For temporary use, however, they are exactly
-what you want.
-
-Note that it is still useful to provide, say, the ability to create a fully
-optimized version of a system for production use--from the F<Construct> and
-F<Conscript> files. This way you can tailor the optimized system to the
-platform. Where optimizer trade-offs need to be made (particular files may
-not be compiled with full optimization, for example), then these can be
-recorded for posterity (and reproducibility) directly in the scripts.
-
-
-=head1 More on construction environments
-
-As previously mentioned, a B<construction environment> is an object that
-has a set of keyword/value pairs and a set of methods, and which is used
-to tell Cons how target files should be built.  This section describes
-how Cons uses and expands construction environment values to control its
-build behavior.
-
-=head2 Construction variable expansion
-
-Construction variables from a construction environment are expanded
-by preceding the keyword with a C<%> (percent sign):
-
-  Construction variables:
-	XYZZY => 'abracadabra',
-
-  The string:  "The magic word is:  %XYZZY!"
-  expands to:  "The magic word is:  abracadabra!"
-
-A construction variable name may be surrounded by C<{> and C<}> (curly
-braces), which are stripped as part of the expansion.  This can
-sometimes be necessary to separate a variable expansion from trailing
-alphanumeric characters:
-
-  Construction variables:
-	OPT    => 'value1',
-	OPTION => 'value2',
-
-  The string:  "%OPT %{OPT}ION %OPTION %{OPTION}"
-  expands to:  "value1 value1ION value2 value2"
-
-Construction variable expansion is recursive--that is, a string
-containing C<%->expansions after substitution will be re-expanded until
-no further substitutions can be made:
-
-  Construction variables:
-	STRING => 'The result is:  %FOO',
-	FOO    => '%BAR',
-	BAR    => 'final value',
-
-  The string:  "The string says:  %STRING"
-  expands to:  "The string says:  The result is:  final value"
-
-If a construction variable is not defined in an environment, then the
-null string is substituted:
-
-  Construction variables:
-	FOO => 'value1',
-	BAR => 'value2',
-
-  The string:  "%FOO <%NO_VARIABLE> %BAR"
-  expands to:  "value1 <> value2"
-
-A doubled C<%%> will be replaced by a single C<%>:
-
-  The string:  "Here is a percent sign:  %%"
-  expands to:  "Here is a percent sign: %"
-
-=head2 Default construction variables
-
-When you specify no arguments when creating a new construction
-environment:
-
-  $env = new cons();
-
-Cons creates a reference to a new, default construction
-environment. This contains a number of construction variables and some
-methods. At the present writing, the default construction variables on a
-UNIX system are:
-
-  CC            => 'cc',
-  CFLAGS        => '',
-  CCCOM         => '%CC %CFLAGS %_IFLAGS -c %< -o %>',
-  CXX           => '%CC',
-  CXXFLAGS      => '%CFLAGS',
-  CXXCOM        => '%CXX %CXXFLAGS %_IFLAGS -c %< -o %>',
-  INCDIRPREFIX  => '-I',
-  INCDIRSUFFIX  => '',
-  LINK          => '%CXX',
-  LINKCOM       => '%LINK %LDFLAGS -o %> %< %_LDIRS %LIBS',
-  LINKMODULECOM => '%LD -r -o %> %<',
-  LIBDIRPREFIX  => '-L',
-  LIBDIRSUFFIX  => '',
-  AR		=> 'ar',
-  ARFLAGS	=> 'r',
-  ARCOM		=> ['%AR %ARFLAGS %> %<', '%RANLIB %>'],
-  RANLIB	=> 'ranlib',
-  AS		=> 'as',
-  ASFLAGS	=> '',
-  ASCOM		=> '%AS %ASFLAGS %< -o %>',
-  LD		=> 'ld',
-  LDFLAGS	=> '',
-  PREFLIB	=> 'lib',
-  SUFLIB	=> '.a',
-  SUFLIBS	=> '.so:.a',
-  SUFOBJ	=> '.o',
-  SIGNATURE     => [ '*' => 'build' ],
-  ENV		=> { 'PATH' => '/bin:/usr/bin' },
-
-
-And on a Win32 system (Windows NT), the default construction variables
-are (unless the default rule style is set using the B<DefaultRules>
-method):
-
-  CC		=> 'cl',
-  CFLAGS	=> '/nologo',
-  CCCOM		=> '%CC %CFLAGS %_IFLAGS /c %< /Fo%>',
-  CXXCOM        => '%CXX %CXXFLAGS %_IFLAGS /c %< /Fo%>',
-  INCDIRPREFIX  => '/I',
-  INCDIRSUFFIX  => '',
-  LINK          => 'link',
-  LINKCOM       => '%LINK %LDFLAGS /out:%> %< %_LDIRS %LIBS',
-  LINKMODULECOM => '%LD /r /o %> %<',
-  LIBDIRPREFIX  => '/LIBPATH:',
-  LIBDIRSUFFIX  => '',
-  AR            => 'lib',
-  ARFLAGS       => '/nologo ',
-  ARCOM         => "%AR %ARFLAGS /out:%> %<",
-  RANLIB        => '',
-  LD            => 'link',
-  LDFLAGS       => '/nologo ',
-  PREFLIB       => '',
-  SUFEXE	=> '.exe',
-  SUFLIB	=> '.lib',
-  SUFLIBS	=> '.dll:.lib',
-  SUFOBJ	=> '.obj',
-  SIGNATURE     => [ '*' => 'build' ],
-
-These variables are used by the various methods associated with the
-environment. In particular, any method that ultimately invokes an external
-command will substitute these variables into the final command, as
-appropriate. For example, the C<Objects> method takes a number of source
-files and arranges to derive, if necessary, the corresponding object
-files:
-
-  Objects $env 'foo.c', 'bar.c';
-
-This will arrange to produce, if necessary, F<foo.o> and F<bar.o>. The
-command invoked is simply C<%CCCOM>, which expands, through substitution,
-to the appropriate external command required to build each object. The
-substitution rules will be discussed in detail in the next section.
-
-The construction variables are also used for other purposes. For example,
-C<CPPPATH> is used to specify a colon-separated path of include
-directories. These are intended to be passed to the C preprocessor and are
-also used by the C-file scanning machinery to determine the dependencies
-involved in a C Compilation.
-
-Variables beginning with underscore are created by various methods,
-and should normally be considered ``internal'' variables. For example,
-when a method is called which calls for the creation of an object from
-a C source, the variable C<_IFLAGS> is created: this corresponds to the
-C<-I> switches required by the C compiler to represent the directories
-specified by C<CPPPATH>.
-
-Note that, for any particular environment, the value of a variable is set
-once, and then never reset (to change a variable, you must create a new
-environment. Methods are provided for copying existing environments for this
-purpose). Some internal variables, such as C<_IFLAGS> are created on demand,
-but once set, they remain fixed for the life of the environment.
-
-The C<CFLAGS>, C<LDFLAGS>, and C<ARFLAGS> variables all supply a place
-for passing options to the compiler, loader, and archiver, respectively.
-
-The C<INCDIRPREFIX> and C<INCDIRSUFFIX> variables specify option
-strings to be appended to the beginning and end, respectively, of each
-include directory so that the compiler knows where to find F<.h> files.
-Similarly, the C<LIBDIRPREFIX> and C<LIBDIRSUFFIX> variables specify the
-option string to be appended to the beginning of and end, respectively,
-of each directory that the linker should search for libraries.
-
-Another variable, C<ENV>, is used to determine the system environment during
-the execution of an external command. By default, the only environment
-variable that is set is C<PATH>, which is the execution path for a UNIX
-command. For the utmost reproducibility, you should really arrange to set
-your own execution path, in your top-level F<Construct> file (or perhaps by
-importing an appropriate construction package with the Perl C<use>
-command). The default variables are intended to get you off the ground.
-
-=head2 Expanding variables in construction commands
-
-Within a construction command, construction variables will be expanded
-according to the rules described above.  In addition to normal variable
-expansion from the construction environment, construction commands also
-expand the following pseudo-variables to insert the specific input and
-output files in the command line that will be executed:
-
-=over 10
-
-=item %>
-
-The target file name.  In a multi-target command, this expands to the
-first target mentioned.)
-
-=item %0
-
-Same as C<%E<gt>>.
-
-=item %1, %2, ..., %9
-
-These refer to the first through ninth input file, respectively.
-
-=item %E<lt>
-
-The full set of input file names. If any of these have been used
-anywhere else in the current command line (via C<%1>, C<%2>, etc.), then
-those will be deleted from the list provided by C<%E<lt>>. Consider the
-following command found in a F<Conscript> file in the F<test> directory:
-
-  Command $env 'tgt', qw(foo bar baz), qq(
-	echo %< -i %1 > %>
-	echo %< -i %2 >> %>
-	echo %< -i %3 >> %>
-  );
-
-If F<tgt> needed to be updated, then this would result in the execution of
-the following commands, assuming that no remapping has been established for
-the F<test> directory:
-
-  echo test/bar test/baz -i test/foo > test/tgt
-  echo test/foo test/baz -i test/bar >> test/tgt
-  echo test/foo test/bar -i test/baz >> test/tgt
-
-=back
-
-Any of the above pseudo-variables may be followed immediately by one of
-the following suffixes to select a portion of the expanded path name:
-
-  :a    the absolute path to the file name
-  :b    the directory plus the file name stripped of any suffix
-  :d    the directory
-  :f    the file name
-  :s    the file name suffix
-  :F    the file name stripped of any suffix
-  :S    the absolute path path to a Linked source file
-
-Continuing with the above example, C<%E<lt>:f> would expand to C<foo bar baz>,
-and C<%E<gt>:d> would expand to C<test>.
-
-There are additional C<%> elements which affect the command line(s):
-
-=over 10
-
-=item %[ %]
-
-It is possible to programmatically rewrite part of the command by
-enclosing part of it between C<%[> and C<%]>.  This will call the
-construction variable named as the first word enclosed in the brackets
-as a Perl code reference; the results of this call will be used to
-replace the contents of the brackets in the command line.  For example,
-given an existing input file named F<tgt.in>:
-
-  @keywords = qw(foo bar baz);
-  $env = new cons(X_COMMA => sub { join(",", @_) });
-  Command $env 'tgt', 'tgt.in', qq(
-	echo '# Keywords: %[X_COMMA @keywords %]' > %>
-	cat %< >> %>
-  );
-
-This will execute:
-
-  echo '# Keywords: foo,bar,baz' > tgt
-  cat tgt.in >> tgt
-
-=item %( %)
-
-Cons includes the text of the command line in the MD5 signature for a
-build, so that targets get rebuilt if you change the command line (to
-add or remove an option, for example).  Command-line text in between
-C<%(> and C<%)>, however, will be ignored for MD5 signature calculation.
-
-Internally, Cons uses C<%(> and C<%)> around include and library
-directory options (C<-I> and C<-L> on UNIX systems, C</I> and
-C</LIBPATH> on Windows NT) to avoid rebuilds just because the directory
-list changes.  Rebuilds occur only if the changed directory list causes
-any included I<files> to change, and a changed include file is detected
-by the MD5 signature calculation on the actual file contents.
-
-=back
-
-=head2 Expanding construction variables in file names
-
-Cons expands construction variables in the source and target file names
-passed to the various construction methods according to the expansion
-rules described above:
-
-  $env = new cons(
-	DESTDIR	=>	'programs',
-	SRCDIR	=>	'src',
-  );
-  Program $env '%DESTDIR/hello', '%SRCDIR/hello.c';
-
-This allows for flexible configuration, through the construction
-environment, of directory names, suffixes, etc.
-
-
-=head1 Build actions
-
-Cons supports several types of B<build actions> that can be performed
-to construct one or more target files.  Usually, a build action is
-a construction command--that is, a command-line string that invokes
-an external command.  Cons can also execute Perl code embedded in a
-command-line string, and even supports an experimental ability to build
-a target file by executing a Perl code reference directly.
-
-A build action is usually specified as the value of a construction
-variable:
-
-  $env = new cons(
-	CCCOM         => '%CC %CFLAGS %_IFLAGS -c %< -o %>',
-	LINKCOM       => '[perl] &link_executable("%>", "%<")',
-	ARCOM         => sub { my($env, $target, @sources) = @_;
-				 # code to create an archive
-				}
-  );
-
-A build action may be associated directly with one or more target files
-via the C<Command> method; see below.
-
-=head2 Construction commands
-
-A construction command goes through expansion of construction variables
-and C<%-> pseudo-variables, as described above, to create the actual
-command line that Cons will execute to generate the target file or
-files.
-
-After substitution occurs, strings of white space are converted into
-single blanks, and leading and trailing white space is eliminated. It
-is therefore currently not possible to introduce variable length white
-space in strings passed into a command.
-
-If a multi-line command string is provided, the commands are executed
-sequentially. If any of the commands fails, then none of the rest are
-executed, and the target is not marked as updated, i.e. a new signature is
-not stored for the target.
-
-Normally, if all the commands succeed, and return a zero status (or whatever
-platform-specific indication of success is required), then a new signature
-is stored for the target. If a command erroneously reports success even
-after a failure, then Cons will assume that the target file created by that
-command is accurate and up-to-date.
-
-The first word of each command string, after expansion, is assumed to be an
-executable command looked up on the C<PATH> environment variable (which is,
-in turn, specified by the C<ENV> construction variable). If this command is
-found on the path, then the target will depend upon it: the command will
-therefore be automatically built, as necessary. It's possible to write
-multi-part commands to some shells, separated by semi-colons. Only the first
-command word will be depended upon, however, so if you write your command
-strings this way, you must either explicitly set up a dependency (with the
-C<Depends> method), or be sure that the command you are using is a system
-command which is expected to be available. If it isn't available, you will,
-of course, get an error.
-
-Cons normally prints a command before executing it.  This behavior is
-suppressed if the first character of the command is C<@>.  Note that
-you may need to separate the C<@> from the command name or escape it to
-prevent C<@cmd> from looking like an array to Perl quote operators that
-perform interpolation:
-
-  # The first command line is incorrect,
-  # because "@cp" looks like an array
-  # to the Perl qq// function.
-  # Use the second form instead.
-  Command $env 'foo', 'foo.in', qq(
-	@cp %< tempfile
-	@ cp tempfile %>
-  );
-
-If there are shell meta characters anywhere in the expanded command line,
-such as C<E<lt>>, C<E<gt>>, quotes, or semi-colon, then the command
-will actually be executed by invoking a shell. This means that a command
-such as:
-
-  cd foo
-
-alone will typically fail, since there is no command C<cd> on the path. But
-the command string:
-
-  cd $<:d; tar cf $>:f $<:f
-
-when expanded will still contain the shell meta character semi-colon, and a
-shell will be invoked to interpret the command. Since C<cd> is interpreted
-by this sub-shell, the command will execute as expected.
-
-=head2 Perl expressions
-
-If any command (even one within a multi-line command) begins with
-C<[perl]>, the remainder of that command line will be evaluated by the
-running Perl instead of being forked by the shell.  If an error occurs
-in parsing the Perl code, or if the Perl expression returns 0 or undef,
-the command will be considered to have failed.  For example, here is a
-simple command which creates a file C<foo> directly from Perl:
-
-  $env = new cons();
-  Command $env 'foo',
-    qq([perl] open(FOO,'>foo');print FOO "hi\\n"; close(FOO); 1);
-
-Note that when the command is executed, you are in the same package as
-when the F<Construct> or F<Conscript> file was read, so you can call
-Perl functions you've defined in the same F<Construct> or F<Conscript>
-file in which the C<Command> appears:
-
-  $env = new cons();
-  sub create_file {
-	my $file = shift;
-	open(FILE, ">$file");
-	print FILE "hi\n";
-	close(FILE);
-	return 1;
-  }
-  Command $env 'foo', "[perl] &create_file('%>')";
-
-The Perl string will be used to generate the signature for the derived
-file, so if you change the string, the file will be rebuilt.  The contents
-of any subroutines you call, however, are not part of the signature,
-so if you modify a called subroutine such as C<create_file> above,
-the target will I<not> be rebuilt.  Caveat user.
-
-=head2 Perl code references [EXPERIMENTAL]
-
-Cons supports the ability to create a derived file by directly executing
-a Perl code reference.  This feature is considered EXPERIMENTAL and
-subject to change in the future.
-
-A code reference may either be a named subroutine referenced by the
-usual C<\&> syntax:
-
-  sub build_output {
-	my($env, $target, @sources) = @_;
-	print "build_output building $target\n";
-	open(OUT, ">$target");
-	foreach $src (@sources) {
-	    if (! open(IN, "<$src")) {
-		print STDERR "cannot open '$src': $!\n";
-		return undef;
-	    }
-	    print OUT, <IN>;
-	}
-	close(OUT);
-	return 1;
-  }
-  Command $env 'output', \&build_output;
-
-or the code reference may be an anonymous subroutine:
-
-  Command $env 'output', sub {
-	my($env, $target, @sources) = @_;
-	print "building $target\n";
-	open(FILE, ">$target");
-	print FILE "hello\n";
-	close(FILE);
-	return 1;
-  };
-
-To build the target file, the referenced subroutine is passed, in order:
-the construction environment used to generate the target; the path
-name of the target itself; and the path names of all the source files
-necessary to build the target file.
-
-The code reference is expected to generate the target file, of course,
-but may manipulate the source and target files in any way it chooses.
-The code reference must return a false value (C<undef> or C<0>) if
-the build of the file failed.  Any true value indicates a successful
-build of the target.
-
-Building target files using code references is considered EXPERIMENTAL
-due to the following current limitations:
-
-=over 4
-
-Cons does I<not> print anything to indicate the code reference is being
-called to build the file.  The only way to give the user any indication
-is to have the code reference explicitly print some sort of "building"
-message, as in the above examples.
-
-Cons does not generate any signatures for code references, so if the
-code in the reference changes, the target will I<not> be rebuilt.
-
-Cons has no public method to allow a code reference to extract
-construction variables.  This would be good to allow generalization of
-code references based on the current construction environment, but would
-also complicate the problem of generating meaningful signatures for code
-references.
-
-=back
-
-Support for building targets via code references has been released in
-this version to encourage experimentation and the seeking of possible
-solutions to the above limitations.
-
-
-=head1 Default construction methods
-
-The list of default construction methods includes the following:
-
-
-=head2 The C<new> constructor
-
-The C<new> method is a Perl object constructor. That is, it is not invoked
-via a reference to an existing construction environment B<reference>, but,
-rather statically, using the name of the Perl B<package> where the
-constructor is defined. The method is invoked like this:
-
-  $env = new cons(<overrides>);
-
-The environment you get back is blessed into the package C<cons>, which
-means that it will have associated with it the default methods described
-below. Individual construction variables can be overridden by providing
-name/value pairs in an override list. Note that to override any command
-environment variable (i.e. anything under C<ENV>), you will have to override
-all of them. You can get around this difficulty by using the C<copy> method
-on an existing construction environment.
-
-
-=head2 The C<clone> method
-
-The C<clone> method creates a clone of an existing construction environment,
-and can be called as in the following example:
-
-  $env2 = $env1->clone(<overrides>);
-
-You can provide overrides in the usual manner to create a different
-environment from the original. If you just want a new name for the same
-environment (which may be helpful when exporting environments to existing
-components), you can just use simple assignment.
-
-
-=head2 The C<copy> method
-
-The C<copy> method extracts the externally defined construction variables
-from an environment and returns them as a list of name/value
-pairs. Overrides can also be provided, in which case, the overridden values
-will be returned, as appropriate. The returned list can be assigned to a
-hash, as shown in the prototype, below, but it can also be manipulated in
-other ways:
-
-  %env = $env1->copy(<overrides>);
-
-The value of C<ENV>, which is itself a hash, is also copied to a new hash,
-so this may be changed without fear of affecting the original
-environment. So, for example, if you really want to override just the
-C<PATH> variable in the default environment, you could do the following:
-
-  %cons = new cons()->copy();
-  $cons{ENV}{PATH} = "<your path here>";
-  $cons = new cons(%cons);
-
-This will leave anything else that might be in the default execution
-environment undisturbed.
-
-
-=head2 The C<Install> method
-
-The C<Install> method arranges for the specified files to be installed in
-the specified directory. The installation is optimized: the file is not
-copied if it can be linked. If this is not the desired behavior, you will
-need to use a different method to install the file. It is called as follows:
-
-  Install $env <directory>, <names>;
-
-Note that, while the files to be installed may be arbitrarily named,
-only the last component of each name is used for the installed target
-name. So, for example, if you arrange to install F<foo/bar> in F<baz>,
-this will create a F<bar> file in the F<baz> directory (not F<foo/bar>).
-
-
-=head2 The C<InstallAs> method
-
-The C<InstallAs> method arranges for the specified source file(s) to be
-installed as the specified target file(s). Multiple files should be
-specified as a file list. The installation is optimized: the file is not
-copied if it can be linked. If this is not the desired behavior, you will
-need to use a different method to install the file. It is called as follows:
-
-C<InstallAs> works in two ways:
-
-Single file install:
-
-  InstallAs $env TgtFile, SrcFile;
-
-Multiple file install:
-
-  InstallAs $env ['tgt1', 'tgt2'], ['src1', 'src2'];
-
-Or, even as:
-
-  @srcs = qw(src1 src2 src3);
-  @tgts = qw(tgt1 tgt2 tgt3);
-  InstallAs $env [@tgts], [@srcs];
-
-Both the target and the sources lists should be of the same length.
-
-=head2 The C<Precious> method
-
-The C<Precious> method asks cons not to delete the specified file or
-list of files before building them again.  It is invoked as:
-
-  Precious <files>;
-
-This is especially useful for allowing incremental updates to libraries
-or debug information files which are updated rather than rebuilt anew each
-time.  Cons will still delete the files when the C<-r> flag is specified.
-
-=head2 The C<AfterBuild> method
-
-The C<AfterBuild> method evaluates the specified perl string after
-building the given file or files (or finding that they are up to date).
-The eval will happen once per specified file.  C<AfterBuild> is called
-as follows:
-
-  AfterBuild $env 'foo.o', qq(print "foo.o is up to date!\n");
-
-The perl string is evaluated in the C<script> package, and has access
-to all variables and subroutines defined in the F<Conscript> file in
-which the C<AfterBuild> method is called.
-
-=head2 The C<Command> method
-
-The C<Command> method is a catchall method which can be used to arrange for
-any build action to be executed to update the target. For this command, a
-target file and list of inputs is provided. In addition, a build action
-is specified as the last argument.  The build action is typically a
-command line or lines, but may also contain Perl code to be executed;
-see the section above on build actions for details.
-
-The C<Command> method is called as follows:
-
-  Command $env <target>, <inputs>, <build action>;
-
-The target is made dependent upon the list of input files specified, and the
-inputs must be built successfully or Cons will not attempt to build the
-target.
-
-To specify a command with multiple targets, you can specify a reference to a
-list of targets. In Perl, a list reference can be created by enclosing a
-list in square brackets. Hence the following command:
-
-  Command $env ['foo.h', 'foo.c'], 'foo.template', q(
-	gen %1
-  );
-
-could be used in a case where the command C<gen> creates two files, both
-F<foo.h> and F<foo.c>.
-
-
-=head2 The C<Objects> method
-
-The C<Objects> method arranges to create the object files that correspond to
-the specified source files. It is invoked as shown below:
-
-  @files = Objects $env <source or object files>;
-
-Under Unix, source files ending in F<.s> and F<.c> are currently
-supported, and will be compiled into a name of the same file ending
-in F<.o>. By default, all files are created by invoking the external
-command which results from expanding the C<CCCOM> construction variable,
-with C<%E<lt>> and C<%E<gt>> set to the source and object files,
-respectively. (See the section above on construction variable expansion
-for details).  The variable C<CPPPATH> is also used when scanning source
-files for dependencies. This is a colon separated list of pathnames, and
-is also used to create the construction variable C<_IFLAGS,> which will
-contain the appropriate list of -C<I> options for the compilation. Any
-relative pathnames in C<CPPPATH> is interpreted relative to the
-directory in which the associated construction environment was created
-(absolute and top-relative names may also be used). This variable is
-used by C<CCCOM>. The behavior of this command can be modified by
-changing any of the variables which are interpolated into C<CCCOM>, such
-as C<CC>, C<CFLAGS>, and, indirectly, C<CPPPATH>. It's also possible
-to replace the value of C<CCCOM>, itself. As a convenience, this file
-returns the list of object filenames.
-
-
-=head2 The C<Program> method
-
-The C<Program> method arranges to link the specified program with the
-specified object files. It is invoked in the following manner:
-
-  Program $env <program name>, <source or object files>;
-
-The program name will have the value of the C<SUFEXE> construction
-variable appended (by default, C<.exe> on Win32 systems, nothing on Unix
-systems) if the suffix is not already present.
-
-Source files may be specified in place of objects files--the C<Objects>
-method will be invoked to arrange the conversion of all the files into
-object files, and hence all the observations about the C<Objects> method,
-above, apply to this method also.
-
-The actual linking of the program will be handled by an external command
-which results from expanding the C<LINKCOM> construction variable, with
-C<%E<lt>> set to the object files to be linked (in the order presented),
-and C<%E<gt>> set to the target. (See the section above on construction
-variable expansion for details.)  The user may set additional variables
-in the construction environment, including C<LINK>, to define which
-program to use for linking, C<LIBPATH>, a colon-separated list of
-library search paths, for use with library specifications of the form
-I<-llib>, and C<LIBS>, specifying the list of libraries to link against
-(in either I<-llib> form or just as pathnames. Relative pathnames in
-both C<LIBPATH> and C<LIBS> are interpreted relative to the directory
-in which the associated construction environment is created (absolute
-and top-relative names may also be used). Cons automatically sets up
-dependencies on any libraries mentioned in C<LIBS>: those libraries will
-be built before the command is linked.
-
-
-=head2 The C<Library> method
-
-The C<Library> method arranges to create the specified library from the
-specified object files. It is invoked as follows:
-
-  Library $env <library name>, <source or object files>;
-
-The library name will have the value of the C<SUFLIB> construction
-variable appended (by default, C<.lib> on Win32 systems, C<.a> on Unix
-systems) if the suffix is not already present.
-
-Source files may be specified in place of objects files--the C<Objects>
-method will be invoked to arrange the conversion of all the files into
-object files, and hence all the observations about the C<Objects> method,
-above, apply to this method also.
-
-The actual creation of the library will be handled by an external
-command which results from expanding the C<ARCOM> construction variable,
-with C<%E<lt>> set to the library members (in the order presented),
-and C<%E<gt>> to the library to be created.  (See the section above
-on construction variable expansion for details.)  The user may set
-variables in the construction environment which will affect the
-operation of the command. These include C<AR>, the archive program
-to use, C<ARFLAGS>, which can be used to modify the flags given to
-the program specified by C<AR>, and C<RANLIB>, the name of a archive
-index generation program, if needed (if the particular need does not
-require the latter functionality, then C<ARCOM> must be redefined to not
-reference C<RANLIB>).
-
-The C<Library> method allows the same library to be specified in multiple
-method invocations. All of the contributing objects from all the invocations
-(which may be from different directories) are combined and generated by a
-single archive command. Note, however, that if you prune a build so that
-only part of a library is specified, then only that part of the library will
-be generated (the rest will disappear!).
-
-
-=head2 The C<Module> method
-
-The C<Module> method is a combination of the C<Program> and C<Command>
-methods. Rather than generating an executable program directly, this command
-allows you to specify your own command to actually generate a module. The
-method is invoked as follows:
-
-  Module $env <module name>, <source or object files>, <construction command>;
-
-This command is useful in instances where you wish to create, for example,
-dynamically loaded modules, or statically linked code libraries.
-
-
-=head2 The C<Depends> method
-
-The C<Depends> method allows you to specify additional dependencies for a
-target.  It is invoked as follows:
-
-  Depends $env <target>, <dependencies>;
-
-This may be occasionally useful, especially in cases where no scanner exists
-(or is writable) for particular types of files. Normally, dependencies are
-calculated automatically from a combination of the explicit dependencies set
-up by the method invocation or by scanning source files.
-
-A set of identical dependencies for multiple targets may be specified
-using a reference to a list of targets. In Perl, a list reference can
-be created by enclosing a list in square brackets. Hence the following
-command:
-
-  Depends $env ['foo', 'bar'], 'input_file_1', 'input_file_2';
-
-specifies that both the F<foo> and F<bar> files depend on the listed
-input files.
-
-
-=head2 The C<RuleSet> method
-
-The C<RuleSet> method returns the construction variables for building
-various components with one of the rule sets supported by Cons.  The
-currently supported rule sets are:
-
-=over 4
-
-=item msvc
-
-Rules for the Microsoft Visual C++ compiler suite.
-
-=item unix
-
-Generic rules for most UNIX-like compiler suites.
-
-=back
-
-On systems with more than one available compiler suite, this allows you
-to easily create side-by-side environments for building software with
-multiple tools:
-
-    $msvcenv = new cons(RuleSet("msvc"));
-    $cygnusenv = new cons(RuleSet("unix"));
-
-In the future, this could also be extended to other platforms that
-have different default rule sets.
-
-
-=head2 The C<DefaultRules> method
-
-The C<DefaultRules> method sets the default construction variables that
-will be returned by the C<new> method to the specified arguments:
-
-  DefaultRules(CC     => 'gcc',
-	       CFLAGS => '',
-	       CCCOM  => '%CC %CFLAGS %_IFLAGS -c %< -o %>');
-  $env = new cons();
-  # $env now contains *only* the CC, CFLAGS,
-  # and CCCOM construction variables
-
-Combined with the C<RuleSet> method, this also provides an easy way
-to set explicitly the default build environment to use some supported
-toolset other than the Cons defaults:
-
-    # use a UNIX-like tool suite (like cygwin) on Win32
-    DefaultRules(RuleSet('unix'));
-    $env = new cons();
-
-Note that the C<DefaultRules> method completely replaces the default
-construction environment with the specified arguments, it does not
-simply override the existing defaults.  To override one or more
-variables in a supported C<RuleSet>, append the variables and values:
-
-  DefaultRules(RuleSet('unix'), CFLAGS => '-O3');
-  $env1 = new cons();
-  $env2 = new cons();
-  # both $env1 and $env2 have 'unix' defaults
-  # with CFLAGS set to '-O3'
-
-
-=head2 The C<Ignore> method
-
-The C<Ignore> method allows you to ignore explicitly dependencies that
-Cons infers on its own.  It is invoked as follows:
-
-  Ignore <patterns>;
-
-This can be used to avoid recompilations due to changes in system header
-files or utilities that are known to not affect the generated targets.
-
-If, for example, a program is built in an NFS-mounted directory on
-multiple systems that have different copies of F<stdio.h>, the differences
-will affect the signatures of all derived targets built from source files
-that C<#include E<lt>stdio.hE<gt>>.  This will cause all those targets to
-be rebuilt when changing systems.  If this is not desirable behavior, then
-the following line will remove the dependencies on the F<stdio.h> file:
-
-  Ignore '^/usr/include/stdio\.h$';
-
-Note that the arguments to the C<Ignore> method are regular expressions,
-so special characters must be escaped and you may wish to anchor the
-beginning or end of the expression with C<^> or C<$> characters.
-
-
-=head2 The C<Salt> method
-
-The C<Salt> method adds a constant value to the signature calculation
-for every derived file.  It is invoked as follows:
-
-  Salt $string;
-
-Changing the Salt value will force a complete rebuild of every derived
-file.  This can be used to force rebuilds in certain desired
-circumstances.  For example,
-
-  Salt `uname -s`;
-
-Would force a complete rebuild of every derived file whenever the
-operating system on which the build is performed (as reported by C<uname
--s>) changes.
-
-
-=head2 The C<UseCache> method
-
-The C<UseCache> method instructs Cons to maintain a cache of derived
-files, to be shared among separate build trees of the same project.
-
-  UseCache("cache/<buildname>") || warn("cache directory not found");
-
-
-=head2 The C<SourcePath> method
-
-The C<SourcePath> mathod returns the real source path name of a file,
-as opposed to the path name within a build directory.  It is invoked
-as follows:
-
-  $path = SourcePath <buildpath>;
-
-
-=head2 The C<ConsPath> method
-
-The C<ConsPath> method returns true if the supplied path is a derivable
-file, and returns undef (false) otherwise.
-It is invoked as follows:
-
-  $result = ConsPath <path>;
-
-
-=head2 The C<SplitPath> method
-
-The C<SplitPath> method looks up multiple path names in a string separated
-by the default path separator for the operating system (':' on UNIX
-systems, ';' on Windows NT), and returns the fully-qualified names.
-It is invoked as follows:
-
-  @paths = SplitPath <pathlist>;
-
-The C<SplitPath> method will convert  names prefixed '#' to the
-appropriate top-level build name (without the '#') and will convert
-relative names to top-level names.
-
-
-=head2 The C<DirPath> method
-
-The C<DirPath> method returns the build path name(s) of a directory or
-list of directories.  It is invoked as follows:
-
-  $cwd = DirPath <paths>;
-
-The most common use for the C<DirPath> method is:
-
-  $cwd = DirPath '.';
-
-to fetch the path to the current directory of a subsidiary F<Conscript>
-file.
-
-
-=head2 The C<FilePath> method
-
-The C<FilePath> method returns the build path name(s) of a file or
-list of files.  It is invoked as follows:
-
-  $file = FilePath <path>;
-
-
-=head2 The C<Help> method
-
-The C<Help> method specifies help text that will be displayed when the
-user invokes C<cons -h>.  This can be used to provide documentation
-of specific targets, values, build options, etc. for the build tree.
-It is invoked as follows:
-
-  Help <helptext>;
-
-The C<Help> method may only be called once, and should typically be
-specified in the top-level F<Construct> file.
-
-
-=head1 Extending Cons
-
-
-=head2 Overriding construction variables
-
-There are several ways of extending Cons, which vary in degree of
-difficulty. The simplest method is to define your own construction
-environment, based on the default environment, but modified to reflect your
-particular needs. This will often suffice for C-based applications. You can
-use the C<new> constructor, and the C<clone> and C<copy> methods to create
-hybrid environments. These changes can be entirely transparent to the
-underlying F<Conscript> files.
-
-
-=head2 Adding new methods
-
-For slightly more demanding changes, you may wish to add new methods to the
-C<cons> package. Here's an example of a very simple extension,
-C<InstallScript>, which installs a tcl script in a requested location, but
-edits the script first to reflect a platform-dependent path that needs to be
-installed in the script:
-
-  # cons::InstallScript - Create a platform dependent version of a shell
-  # script by replacing string ``#!your-path-here'' with platform specific
-  # path $BIN_DIR.
-
-  sub cons::InstallScript {
-	my ($env, $dst, $src) = @_;
-	Command $env $dst, $src, qq(
-		sed s+your-path-here+$BIN_DIR+ %< > %>
-		chmod oug+x %>
-	);
-  }
-
-Notice that this method is defined directly in the C<cons> package (by
-prefixing the name with C<cons::>). A change made in this manner will be
-globally visible to all environments, and could be called as in the
-following example:
-
-  InstallScript $env "$BIN/foo", "foo.tcl";
-
-For a small improvement in generality, the C<BINDIR> variable could be
-passed in as an argument or taken from the construction environment--as
-C<%BINDIR>.
-
-
-=head2 Overriding methods
-
-Instead of adding the method to the C<cons> name space, you could define a
-new package which inherits existing methods from the C<cons> package and
-overrides or adds others. This can be done using Perl's inheritance
-mechanisms.
-
-The following example defines a new package C<cons::switch> which
-overrides the standard C<Library> method. The overridden method builds
-linked library modules, rather than library archives. A new
-constructor is provided. Environments created with this constructor
-will have the new library method; others won't.
-
-  package cons::switch;
-  BEGIN {@ISA = 'cons'}
-
-  sub new {
-	shift;
-	bless new cons(@_);
-  }
-
-  sub Library {
-	my($env) = shift;
-	my($lib) = shift;
-	my(@objs) = Objects $env @_;
-	Command $env $lib, @objs, q(
-		%LD -r %LDFLAGS %< -o %>
-	);
-  }
-
-This functionality could be invoked as in the following example:
-
-  $env = new cons::switch(@overrides);
-  ...
-  Library $env 'lib.o', 'foo.c', 'bar.c';
-
-
-=head1 Invoking Cons
-
-The C<cons> command is usually invoked from the root of the build tree. A
-F<Construct> file must exist in that directory. If the C<-f> argument is
-used, then an alternate F<Construct> file may be used (and, possibly, an
-alternate root, since C<cons> will cd to F<Construct> file's containing
-directory).
-
-If C<cons> is invoked from a child of the root of the build tree with
-the C<-t> argument, it will walk up the directory hierarchy looking for a
-F<Construct> file.  (An alternate name may still be specified with C<-f>.)
-The targets supplied on the command line will be modified to be relative
-to the discovered F<Construct> file.  For example, from a directory
-containing a top-level F<Construct> file, the following invocation:
-
-  % cd libfoo/subdir
-  % cons -t target
-
-is exactly equivalent to:
-
-  % cons libfoo/subdir/target
-
-If there are any C<Default> targets specified in the directory hierarchy's
-F<Construct> or F<Conscript> files, only the default targets at or below
-the directory from which C<cons -t> was invoked will be built.
-
-The command is invoked as follows:
-
-  cons <arguments> -- <construct-args>
-
-where I<arguments> can be any of the following, in any order:
-
-=over 10
-
-=item I<target>
-
-Build the specified target. If I<target> is a directory, then recursively
-build everything within that directory.
-
-=item I<+pattern>
-
-Limit the F<Conscript> files considered to just those that match I<pattern>,
-which is a Perl regular expression. Multiple C<+> arguments are accepted.
-
-=item I<name>=<val>
-
-Sets I<name> to value I<val> in the C<ARG> hash passed to the top-level
-F<Construct> file.
-
-=item C<-cc>
-
-Show command that would have been executed, when retrieving from cache. No
-indication that the file has been retrieved is given; this is useful for
-generating build logs that can be compared with real build logs.
-
-=item C<-cd>
-
-Disable all caching. Do not retrieve from cache nor flush to cache.
-
-=item C<-cr>
-
-Build dependencies in random order. This is useful when building multiple
-similar trees with caching enabled.
-
-=item C<-cs>
-
-Synchronize existing build targets that are found to be up-to-date with
-cache. This is useful if caching has been disabled with -cc or just recently
-enabled with UseCache.
-
-=item C<-d>
-
-Enable dependency debugging.
-
-=item C<-f> <file>
-
-Use the specified file instead of F<Construct> (but first change to
-containing directory of I<file>).
-
-=item C<-h>
-
-Show a help message local to the current build if one such is defined, and
-exit.
-
-=item C<-k>
-
-Keep going as far as possible after errors.
-
-=item C<-o> <file>
-
-Read override file I<file>.
-
-=item C<-p>
-
-Show construction products in specified trees. No build is attempted.
-
-=item C<-pa>
-
-Show construction products and associated actions. No build is attempted.
-
-=item C<-pw>
-
-Show products and where they are defined. No build is attempted.
-
-=item C<-q>
-
-Make the build quiet.  Multiple C<-q> options may be specified.
-
-A single C<-q> options suppress messages about Installing and Removing
-targets.
-
-Two C<-q> options suppress build command lines and target up-to-date
-messages.
-
-=item C<-r>
-
-Remove construction products associated with <targets>. No build is
-attempted.
-
-=item C<-R> <repos>
-
-Search for files in I<repos>.  Multiple B<-R> I<repos> directories are
-searched in the order specified.
-
-=item C<-S> <pkg>
-
-Use the sig::<pkg> package to calculate.  Supported <pkg> values
-include "md5" for MD5 signature calculation and "md5::debug" for debug
-information about MD5 signature calculation.
-
-If the specified package ends in <::debug>, signature debug information
-will be printed to the file name specified in the C<CONS_SIG_DEBUG>
-environment variable, or to standard output if the environment variable
-is not set.
-
-=item C<-t>
-
-Traverse up the directory hierarchy looking for a F<Construct> file,
-if none exists in the current directory.  Targets will be modified to
-be relative to the F<Construct> file.
-
-Internally, C<cons> will change its working directory to the directory
-which contains the top-level F<Construct> file and report:
-
-  cons: Entering directory `top-level-directory'
-
-This message indicates to an invoking editor (such as emacs) or build
-environment that Cons will now report all file names relative to the
-top-level directory.  This message can not be suppressed with the C<-q>
-option.
-
-=item C<-v>
-
-Show C<cons> version and continue processing.
-
-=item C<-V>
-
-Show C<cons> version and exit.
-
-=item C<-wf> <file>
-
-Write all filenames considered into I<file>.
-
-=item C<-x>
-
-Show a help message similar to this one, and exit.
-
-=back
-
-And I<construct-args> can be any arguments that you wish to process in the
-F<Construct> file. Note that there should be a B<--> separating the arguments
-to cons and the arguments that you wish to process in the F<Construct> file.
-
-Processing of I<construct-args> can be done by any standard package like
-B<Getopt> or its variants, or any user defined package. B<cons> will pass in
-the I<construct-args> as B<@ARGV> and will not attempt to interpret anything
-after the B<-->.
-
-  % cons -R /usr/local/repository -d os=solaris +driver -- -c test -f DEBUG
-
-would pass the following to cons
-
-  -R /usr/local/repository -d os=solaris +driver
-
-and the following, to the top level F<Construct> file as B<@ARGV>
-
-  -c test -f DEBUG
-
-Note that C<cons -r .> is equivalent to a full recursive C<make clean>,
-but requires no support in the F<Construct> file or any F<Conscript>
-files. This is most useful if you are compiling files into source
-directories (if you separate the F<build> and F<export> directories,
-then you can just remove the directories).
-
-The options C<-p>, C<-pa>, and C<-pw> are extremely useful for use as an aid
-in reading scripts or debugging them. If you want to know what script
-installs F<export/include/foo.h>, for example, just type:
-
-  % cons -pw export/include/foo.h
-
-
-=head1 Using and writing dependency scanners
-
-QuickScan allows simple target-independent scanners to be set up for
-source files. Only one QuickScan scanner may be associated with any given
-source file and environment, although the same scanner may (and should)
-be used for multiple files of a given type.
-
-A QuickScan scanner is only ever invoked once for a given source file,
-and it is only invoked if the file is used by some target in the tree
-(i.e., there is a dependency on the source file).
-
-QuickScan is invoked as follows:
-
-  QuickScan CONSENV CODEREF, FILENAME [, PATH]
-
-The subroutine referenced by CODEREF is expected to return a list of
-filenames included directly by FILE. These filenames will, in turn, be
-scanned. The optional PATH argument supplies a lookup path for finding
-FILENAME and/or files returned by the user-supplied subroutine.  The PATH
-may be a reference to an array of lookup-directory names, or a string of
-names separated by the system's separator character (':' on UNIX systems,
-';' on Windows NT).
-
-The subroutine is called once for each line in the file, with $_ set to the
-current line. If the subroutine needs to look at additional lines, or, for
-that matter, the entire file, then it may read them itself, from the
-filehandle SCAN. It may also terminate the loop, if it knows that no further
-include information is available, by closing the filehandle.
-
-Whether or not a lookup path is provided, QuickScan first tries to lookup
-the file relative to the current directory (for the top-level file
-supplied directly to QuickScan), or from the directory containing the
-file which referenced the file. This is not very general, but seems good
-enough--especially if you have the luxury of writing your own utilities
-and can control the use of the search path in a standard way.
-
-Here's a real example, taken from a F<Construct> file here:
-
-  sub cons::SMFgen {
-      my($env, @tables) = @_;
-      foreach $t (@tables) {
-	  $env->QuickScan(sub { /\b\S*?\.smf\b/g }, "$t.smf",
-			  $env->{SMF_INCLUDE_PATH});
-	  $env->Command(["$t.smdb.cc","$t.smdb.h","$t.snmp.cc",
-			 "$t.ami.cc", "$t.http.cc"], "$t.smf",
-			q(smfgen %( %SMF_INCLUDE_OPT %) %<));
-      }
-  }
-
-The subroutine above finds all names of the form <name>.smf in the
-file. It will return the names even if they're found within comments,
-but that's OK (the mechanism is forgiving of extra files; they're just
-ignored on the assumption that the missing file will be noticed when
-the program, in this example, smfgen, is actually invoked).
-
-[NOTE that the form C<$env-E<gt>QuickScan ...>  and C<$env-E<gt>Command
-...> should not be necessary, but, for some reason, is required
-for this particular invocation. This appears to be a bug in Perl or
-a misunderstanding on my part; this invocation style does not always
-appear to be necessary.]
-
-Here is another way to build the same scanner. This one uses an
-explicit code reference, and also (unnecessarily, in this case) reads
-the whole file itself:
-
-  sub myscan {
-      my(@includes);
-      do {
-	  push(@includes, /\b\S*?\.smf\b/g);
-      } while <SCAN>;
-      @includes
-  }
-
-Note that the order of the loop is reversed, with the loop test at the
-end. This is because the first line is already read for you. This scanner
-can be attached to a source file by:
-
-  QuickScan $env \&myscan, "$_.smf";
-
-This final example, which scans a different type of input file, takes
-over the file scanning rather than being called for each input line:
-
-  $env->QuickScan(
-      sub { my(@includes) = ();
-	  do {
-	     push(@includes, $3)
-		 if /^(#include|import)\s+(\")(.+)(\")/ && $3
-	  } while <SCAN>;
-	  @includes
-      },
-      "$idlFileName",
-      "$env->{CPPPATH};$BUILD/ActiveContext/ACSCLientInterfaces"
-  );
-
-=head1 SUPPORT AND SUGGESTIONS
-
-Cons is maintained by the user community.  To subscribe, send mail to
-B<cons-discuss-request at gnu.org> with body B<subscribe>.
-
-Please report any suggestions through the B<cons-discuss at gnu.org> mailing
-list.
-
-=head1 BUGS
-
-Sure to be some. Please report any bugs through the B<bug-cons at gnu.org>
-mailing list.
-
-=head1 INFORMATION ABOUT CONS
-
-Information about CONS can be obtained from the official cons web site
-B<http://www.dsmit.com/cons/> or its mirrors listed there.
-
-The cons maintainers can be contacted by email at
-B<cons-maintainers at gnu.org>
-
-=head1 AUTHORS
-
-Originally by Bob Sidebotham. Then significantly enriched by the members
-of the Cons community B<cons-discuss at gnu.org>.
-
-The Cons community would like to thank Ulrich Pfeifer for the original pod
-documentation derived from the F<cons.html> file. Cons documentation is now
-a part of the program itself.
-
-=cut
-




More information about the quake3-commits mailing list