cons (225463B)
1 #!/usr/bin/env perl 2 3 # NOTE: Cons intentionally does not use the "perl -w" option or 4 # "use strict." Because Cons "configuration files" are actually 5 # Perl scripts, enabling those restrictions here would force them 6 # on every user's config files, wanted or not. Would users write 7 # "better" Construct and Conscript files if we forced "use strict" 8 # on them? Probably. But we want people to use Cons to get work 9 # done, not force everyone to become a Perl guru to use it, so we 10 # don't insist. 11 # 12 # That said, Cons' code is both "perl -w" and "use strict" clean. 13 # Regression tests keep the code honest by checking for warnings 14 # and "use strict" failures. 15 16 use vars qw( $CVS_id $CVS_ver $ver_num $ver_rev $version ); 17 18 $CVS_id = 'Id'; 19 $CVS_ver = (split(/\s+/, $CVS_id))[2]; 20 21 $ver_num = "2.3"; 22 $ver_rev = ".1"; 23 24 $version = "This is Cons $ver_num$ver_rev ($CVS_id)\n"; 25 26 # Cons: A Software Construction Tool. 27 # Copyright (c) 1996-2001 Free Software Foundation, Inc. 28 # 29 # This program is free software; you can redistribute it and/or modify 30 # it under the terms of the GNU General Public License as published by 31 # the Free Software Foundation; either version 2 of the License, or 32 # (at your option) any later version. 33 # 34 # This program is distributed in the hope that it will be useful, 35 # but WITHOUT ANY WARRANTY; without even the implied warranty of 36 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 37 # GNU General Public License for more details. 38 # 39 # You should have received a copy of the GNU General Public License 40 # along with this program; see the file COPYING. If not, write to 41 # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 42 # Boston, MA 02111-1307, USA. 43 44 require 5.003; 45 # See the NOTE above about why Cons doesn't "use strict". 46 use integer; 47 use Cwd; 48 use File::Copy; 49 50 use vars qw( $_WIN32 $_a $_exe $_o $_so ); 51 52 #------------------------------------------------------------------ 53 # Determine if running on win32 platform - either Windows NT or 95 54 #------------------------------------------------------------------ 55 56 use vars qw( $PATH_SEPARATOR $iswin32 $_WIN32 $usage $indent @targets ); 57 58 BEGIN { 59 use Config; 60 61 # if the version is 5.003, we can check $^O 62 if ($] < 5.003) { 63 eval("require Win32"); 64 $_WIN32 = (!$@); 65 } else { 66 $_WIN32 = ($^O eq "MSWin32") ? 1 : 0; 67 } 68 69 # Fetch the PATH separator from Config; 70 # provide our old defaults in case it's not set. 71 $PATH_SEPARATOR = $Config{path_sep}; 72 $PATH_SEPARATOR = $_WIN32 ? ';' : ':' if ! defined $PATH_SEPARATOR; 73 74 # Fetch file suffixes from Config, 75 # accomodating differences in the Config variables 76 # used by different Perl versions. 77 $_exe = $Config{_exe}; 78 $_exe = $Config{exe_ext} if ! defined $_exe; 79 $_exe = $_WIN32 ? '.exe' : '' if ! defined $_exe; 80 $_o = $Config{_o}; 81 $_o = $Config{obj_ext} if ! defined $_o; 82 $_o = $_WIN32 ? '.obj' : '.o' if ! defined $_o; 83 $_a = $Config{_a}; 84 $_a = $Config{lib_ext} if ! defined $_a; 85 $_a = $_WIN32 ? '.lib' : '.a' if ! defined $_a; 86 $_so = ".$Config{so}"; 87 $_so = $_WIN32 ? '.dll' : '.so' if ! defined $_so; 88 } 89 90 # Flush stdout each time. 91 $| = 1; 92 93 # Seed random number generator. 94 srand(time . $$); # this works better than time ^ $$ in perlfunc manpage. 95 96 $usage = q( 97 Usage: cons <arguments> -- <construct-args> 98 99 Arguments can be any of the following, in any order: 100 101 <targets> Build the specified targets. If <target> is a directory 102 recursively build everything within that directory. 103 104 +<pattern> Limit the cons scripts considered to just those that 105 match <pattern>. Multiple + arguments are accepted. 106 107 <name>=<val> Sets <name> to value <val> in the ARG hash passed to the 108 top-level Construct file. 109 110 -cc Show command that would have been executed, when 111 retrieving from cache. No indication that the file 112 has been retrieved is given; this is useful for 113 generating build logs that can be compared with 114 real build logs. 115 116 -cd Disable all caching. Do not retrieve from cache nor 117 flush to cache. 118 119 -cr Build dependencies in random order. This is useful when 120 building multiple similar trees with caching enabled. 121 122 -cs Synchronize existing build targets that are found to be 123 up-to-date with cache. This is useful if caching has 124 been disabled with -cc or just recently enabled with 125 UseCache. 126 127 -d Enable dependency debugging. 128 129 -f <file> Use the specified file instead of "Construct" (but first 130 change to containing directory of <file>). 131 132 -h Show a help message local to the current build if 133 one such is defined, and exit. 134 135 -k Keep going as far as possible after errors. 136 137 -o <file> Read override file <file>. 138 139 -p Show construction products in specified trees. 140 -pa Show construction products and associated actions. 141 -pw Show products and where they are defined. 142 143 -q Be quiet; multiple -q flags increase quietness level: 144 1: quiet about Installing and Removing targets 145 2: quiet about build commands, up-to-date targets 146 147 -r Remove construction products associated with <targets> 148 149 -R <repos> Search for files in <repos>. Multiple -R <repos> 150 directories are searched in the order specified. 151 152 -S <pkg> Use package sig::<pkg> to calculate file signatures. 153 Currently supported values are "md5" for MD5 154 signatures (the default) and "md5::debug" for MD5 155 signature debug information. 156 157 -t Traverse up the directory hierarchy looking for a 158 Construct file, if none exists in the current directory. 159 (Targets will be modified to be relative to the 160 Construct file.) 161 162 -v Show cons version and continue processing. 163 -V Show cons version and exit. 164 165 -wf <file> Write all filenames considered into <file>. 166 167 -x Show this message and exit. 168 169 170 Please report any suggestions through the cons-discuss@gnu.org mailing 171 list. 172 173 To subscribe, send mail to cons-discuss-request@gnu.org with body 174 'subscribe'. 175 176 If you find a bug, please report it through the bug-cons@gnu.org 177 mailing list. 178 179 Information about CONS can be obtained from the official cons web site 180 http://www.dsmit.com/cons/ or its mirrors (listed there). 181 182 The cons maintainers can be contacted by email at cons-maintainers@gnu.org 183 184 User documentation of cons is contained in cons and can be obtained 185 by doing 'perldoc /path/to/cons'. 186 187 ); 188 189 # Simplify program name, if it is a path. 190 { 191 my ($vol, $dir, $file) = File::Spec->splitpath(File::Spec->canonpath($0)); 192 $0 = $file; 193 } 194 195 # Default parameters. 196 $param::topfile = 'Construct'; # Top-level construction file. 197 $param::install = 1; # Show installations 198 $param::build = 1; # Build targets 199 ### $param::show = 1; # Show building of targets. 200 $param::sigpro = 'md5'; # Signature protocol. 201 $param::depfile = ''; # Write all deps out to this file 202 $param::salt = ''; # Salt derived file signatures with this. 203 $param::sourcesig = ['*' => 'content'];# Source file signature calculation 204 $param::rep_sig_times_ok = 1; # Repository .consign times are in sync 205 # w/files. 206 $param::conscript_chdir = 0; # Change dir to Conscript directory 207 $param::quiet = 0; # should we show the command being executed. 208 209 @param::defaults = (); 210 211 # 212 $indent = ''; 213 214 # Display a command while executing or otherwise. This 215 # should be called by command builder action methods. 216 sub showcom { 217 print($indent . $_[0] . "\n") if ($param::quiet < 2); 218 } 219 220 # Default environment. 221 # This contains only the completely platform-independent information 222 # we can figure out. Platform-specific information (UNIX, Win32) 223 # gets added below. 224 @param::base = ( 225 'SIGNATURE' => [ '*' => 'build' ], 226 'SUFEXE' => $_exe, # '' on UNIX systems 227 'SUFLIB' => $_a, # '.a' on UNIX systems 228 'SUFLIBS' => "$_so:$_a", # '.so:.a' on UNIX 229 'SUFOBJ' => $_o, # '.o' on UNIX systems 230 'SUFMAP' => { 231 '.c' => 'build::command::cc', 232 '.s' => 'build::command::cc', 233 '.S' => 'build::command::cc', 234 '.C' => 'build::command::cxx', 235 '.cc' => 'build::command::cxx', 236 '.cxx'=> 'build::command::cxx', 237 '.cpp'=> 'build::command::cxx', 238 '.c++'=> 'build::command::cxx', 239 '.C++'=> 'build::command::cxx', 240 }, 241 'PERL' => $^X, 242 ); 243 244 %param::rulesets = 245 ( 246 # Defaults for Win32. 247 # Defined for VC++ 6.0 by Greg Spencer <greg_spencer@acm.org> 248 # Your mileage may vary. 249 'msvc' => [ 250 'CC' => 'cl', 251 'CFLAGS' => '/nologo', 252 'CCCOM' => '%CC %CFLAGS %_IFLAGS /c %< /Fo%>', 253 'CXX' => '%CC', 254 'CXXFLAGS' => '%CFLAGS', 255 'CXXCOM' => '%CXX %CXXFLAGS %_IFLAGS /c %< /Fo%>', 256 'INCDIRPREFIX' => '/I', 257 'INCDIRSUFFIX' => '', 258 'LINK' => 'link', 259 'LINKCOM' => '%LINK %LDFLAGS /out:%> %< %_LDIRS %LIBS', 260 'LINKMODULECOM' => '%LD /r /o %> %<', 261 'LIBDIRPREFIX' => '/LIBPATH:', 262 'LIBDIRSUFFIX' => '', 263 'AR' => 'lib', 264 'ARFLAGS' => '/nologo ', 265 'ARCOM' => "%AR %ARFLAGS /out:%> %<", 266 'RANLIB' => '', 267 'LD' => 'link', 268 'LDFLAGS' => '/nologo ', 269 'PREFLIB' => '', 270 ], 271 # Defaults for a typical (?) UNIX platform. 272 # Your mileage may vary. 273 'unix' => [ 274 'CC' => 'cc', 275 'CFLAGS' => '', 276 'CCCOM' => '%CC %CFLAGS %_IFLAGS -c %< -o %>', 277 'CXX' => '%CC', 278 'CXXFLAGS' => '%CFLAGS', 279 'CXXCOM' => '%CXX %CXXFLAGS %_IFLAGS -c %< -o %>', 280 'INCDIRPREFIX' => '-I', 281 'INCDIRSUFFIX' => '', 282 'LINK' => '%CXX', 283 'LINKCOM' => '%LINK %LDFLAGS -o %> %< %_LDIRS %LIBS', 284 'LINKMODULECOM' => '%LD -r -o %> %<', 285 'LIBDIRPREFIX' => '-L', 286 'LIBDIRSUFFIX' => '', 287 'AR' => 'ar', 288 'ARFLAGS' => 'r', # rs? 289 'ARCOM' => ['%AR %ARFLAGS %> %<', '%RANLIB %>'], 290 'RANLIB' => 'ranlib', 291 'AS' => 'as', 292 'ASFLAGS' => '', 293 'ASCOM' => '%AS %ASFLAGS %< -o %>', 294 'LD' => 'ld', 295 'LDFLAGS' => '', 296 'PREFLIB' => 'lib', 297 'ENV' => { 'PATH' => '/bin:/usr/bin' }, 298 ], 299 ); 300 301 # Set the rules based on the platform. 302 script::DefaultRules(script::RuleSet($_WIN32 ? 'msvc' : 'unix')); 303 304 # Handle command line arguments. 305 while (@ARGV) { 306 $_ = shift @ARGV; 307 last if /^--$/; # Argument passing to Construct. 308 &option, next if s/^-//; 309 push (@param::include, $_), next if s/^\+//; 310 &equate, next if /=/; 311 push (@targets, $_), next; 312 } 313 314 sub option { 315 my %opt = ( 316 'cc' => sub { $param::cachecom = 1; }, 317 'cd' => sub { $param::cachedisable = 1; }, 318 'cr' => sub { $param::random = 1; }, 319 'cs' => sub { $param::cachesync = 1; }, 320 'd' => sub { $param::depends = 1; }, 321 'h' => sub { $param::localhelp = 1; }, 322 'k' => sub { $param::kflag = 1; }, 323 'p' => sub { $param::pflag = 1; 324 $param::build = 0; }, 325 'pa' => sub { $param::pflag = 1; 326 $param::aflag = 1; 327 $indent = "... "; 328 $param::build = 0; }, 329 'pw' => sub { $param::pflag = 1; 330 $param::wflag = 1; 331 $param::build = 0; }, 332 'q' => sub { $param::quiet++; }, 333 'r' => sub { $param::rflag = 1; 334 $param::build = 0; }, 335 't' => sub { $param::traverse = 1; }, 336 'v' => sub { print($version); }, 337 'V' => sub { print($version), exit(0); }, 338 'x' => sub { print($usage), exit 0; }, 339 ); 340 341 my %opt_arg = ( 342 'f' => sub { $param::topfile = $_[0]; }, 343 'o' => sub { $param::overfile = $_[0]; }, 344 'R' => sub { script::Repository($_[0]); }, 345 'S' => sub { $param::sigpro = $_[0]; }, 346 'wf' => sub { $param::depfile = $_[0]; }, 347 ); 348 349 if (defined $opt{$_}) { 350 &{$opt{$_}}(); 351 return; 352 } 353 while ($_) { 354 $_ =~ m/(.)(.*)/; 355 if (defined $opt{$1}) { 356 &{$opt{$1}}(); 357 $_ = $2; 358 next; 359 } 360 if (defined $opt_arg{$1}) { 361 if (! $2) { 362 $_ = shift @ARGV; 363 die("$0: -$1 option requires an argument.\n") if ! $_; 364 } 365 &{$opt_arg{$1}}($2 || $_); 366 return; 367 } 368 $_ =~ m/(..)(.*)/; 369 if (defined $opt_arg{$1}) { 370 if (! $2) { 371 $_ = shift @ARGV; 372 die("$0: -$1 option requires an argument.\n") if ! $_; 373 } 374 &{$opt_arg{$1}}($2 || $_); 375 return; 376 } 377 if ($_) { 378 die qq($0: unrecognized option "-$_". Use -x for a usage message.\n); 379 } 380 } 381 } 382 383 # Process an equate argument (var=val). 384 sub equate { 385 my($var, $val) = /([^=]*)=(.*)/; 386 $script::ARG{$var} = $val; 387 } 388 389 # Define file signature protocol. 390 'sig'->select($param::sigpro); 391 392 # Cleanup after an interrupt. 393 $SIG{INT} = $SIG{QUIT} = $SIG{TERM} = sub { 394 $SIG{PIPE} = $SIG{INT} = $SIG{QUIT} = $SIG{TERM} = 'IGNORE'; 395 $SIG{HUP} = $SIG{INT} if ! $main::_WIN32; 396 warn("\n$0: killed\n"); 397 # Call this first, to make sure that this processing 398 # occurs even if a child process does not die (and we 399 # hang on the wait). 400 sig::hash::END(); 401 wait(); 402 exit(1); 403 }; 404 $SIG{HUP} = $SIG{INT} if ! $main::_WIN32; 405 406 # Cleanup after a broken pipe (someone piped our stdout?) 407 $SIG{PIPE} = sub { 408 $SIG{PIPE} = $SIG{HUP} = $SIG{INT} = $SIG{QUIT} = $SIG{TERM} = 'IGNORE'; 409 warn("\n$0: broken pipe\n"); 410 sig::hash::END(); 411 wait(); 412 exit(1); 413 }; 414 415 if ($param::depfile) { 416 open (main::DEPFILE, ">".$param::depfile) || 417 die ("$0: couldn't open $param::depfile ($!)\n"); 418 } 419 420 # If the supplied top-level Conscript file is not in the 421 # current directory, then change to that directory. 422 { 423 my ($vol, $dir, $file) = 424 File::Spec->splitpath(File::Spec->canonpath($param::topfile)); 425 if ($vol || $dir) { 426 my($cd) = File::Spec->catpath($vol, $dir, undef); 427 chdir($cd) || die("$0: couldn't change to directory $cd ($!)\n"); 428 $param::topfile = $file; 429 } 430 } 431 432 # Walk up the directory hierarchy looking for a Conscript file (if -t set). 433 my($target_top); 434 my(@targetdir) = (); 435 if ($param::traverse && ! -f $param::topfile) { 436 my($vol, $dirs, $file) = File::Spec->splitpath(cwd()); 437 my(@dirs) = (File::Spec->splitdir($dirs), $file); 438 while (! -f File::Spec->catpath($vol, File::Spec->catdir(@dirs), 439 $param::topfile)) { 440 die("$0: unable to find $param::topfile.\n") if ! @dirs; 441 unshift(@targetdir, pop(@dirs)); 442 } 443 my($cwd) = File::Spec->catpath($vol, File::Spec->catdir(@dirs), ''); 444 print "$0: Entering directory `$cwd'\n"; 445 chdir($cwd); 446 @targets = map {File::Spec->catdir(@targetdir, $_)} @targets; 447 } 448 449 # Set up $dir::top and $dir::cwd, now that we are in the right directory. 450 dir::init(); 451 452 # 453 if (@targetdir) { 454 $target_top = $dir::top->lookupdir(File::Spec->catdir(@targetdir)); 455 } 456 457 # Now handle override file. 458 package override; 459 if ($param::overfile) { 460 my($ov) = $param::overfile; 461 die qq($0: can\'t read override file "$ov" ($!)\n) if ! -f $ov; #' 462 do $ov; 463 if ($@) { 464 chop($@); 465 die qq($0: errors in override file "$ov" ($@)\n); 466 } 467 } 468 469 # Provide this to user to setup override patterns. 470 sub Override { 471 my($re, @env) = @_; 472 return if $param::overrides{$re}; # if identical, first will win. 473 $param::overrides = 1; 474 $param::overrides{$re} = \@env; 475 push(@param::overrides, $re); 476 } 477 478 package main; 479 480 use vars qw( %priority $errors ); 481 482 # Check script inclusion regexps 483 my $re; 484 for $re (@param::include) { 485 if (! defined eval {"" =~ /$re/}) { 486 my($err) = $@; 487 $err =~ s/in regexp at .*$//; 488 die("$0: error in regexp $err"); 489 } 490 } 491 492 # Read the top-level construct file and its included scripts. 493 doscripts($param::topfile); 494 495 # Status priorities. This lets us aggregate status for directories 496 # and print an appropriate message (at the top-level). 497 %priority = 498 ('none' => 1, 'handled' => 2, 'built' => 3, 'unknown' => 4, 'errors' => 5); 499 500 # If no targets were specified, supply default targets (if any). 501 @targets = @param::default_targets if ! @targets; 502 503 $errors = 0; 504 505 # Build the supplied target patterns. 506 my $tgt; 507 for $tgt (map($dir::top->lookup($_), @targets)) { 508 if ($target_top && ! $tgt->is_under($target_top)) { 509 # A -t option was used, and this target is not underneath 510 # the directory where we were invoked via -t. 511 # If the target is a directory and the -t directory 512 # is underneath it, then build the -t directory. 513 if (ref $tgt ne "dir" || ! $target_top->is_under($tgt)) { 514 next; 515 } 516 $tgt = $target_top; 517 } 518 buildtoptarget($tgt); 519 } 520 521 exit 0 + ($errors != 0); 522 523 sub buildtoptarget { 524 my($tgt) = @_; 525 return if ! $tgt; 526 my($status) = buildtarget($tgt); 527 if ($status ne 'built') { 528 my($path) = $tgt->path; 529 if ($status eq "errors") { 530 print qq($0: "$path" not remade because of errors.\n); 531 $errors++; 532 } elsif ($status eq "handled") { 533 print qq($0: "$path" is up-to-date.\n) if ($param::quiet < 2); 534 } elsif ($status eq "unknown") { 535 # cons error already reported. 536 $errors++; 537 } elsif ($status eq "none") { 538 # search for targets that may be linked to the given path. 539 my @linked = dir::linked_targets($tgt) if $target_top; 540 if (@linked) { 541 my @names = map($_->path, @linked); 542 print "Linked targets: @names\n" if ($param::quiet < 1); 543 map(buildtoptarget($_), @linked); 544 } else { 545 print qq($0: nothing to be built in "$path".\n) 546 if $param::build && ($param::quiet < 2); 547 } 548 } else { 549 print qq($0: don\'t know how to construct "$path".\n); #' 550 $errors++; 551 } 552 } 553 } 554 555 # Build the supplied target directory or files. Return aggregated status. 556 sub buildtarget { 557 my($tgt) = @_; 558 if (ref($tgt) eq "dir") { 559 my($result) = "none"; 560 my($priority) = $priority{$result}; 561 if (exists $tgt->{member}) { 562 my($members) = $tgt->{member}; 563 my $entry; 564 for $entry (sort keys %$members) { 565 next if $entry eq $dir::CURDIR || $entry eq $dir::UPDIR; 566 my($tgt) = $members->{$entry}; 567 next if ref($tgt) ne "dir" && !exists($tgt->{builder}); 568 my($stat) = buildtarget($members->{$entry}); 569 my($pri) = $priority{$stat}; 570 if ($pri > $priority) { 571 $priority = $pri; 572 $result = $stat; 573 } 574 } 575 } 576 return $result; 577 } 578 if ($param::depends) { 579 my($path) = $tgt->path; 580 if ($tgt->{builder}) { 581 my(@dep) = (@{$tgt->{dep}}, @{$tgt->{sources}}); 582 my($dep) = join(' ',map($_->path, @dep)); 583 print("Target $path: $dep\n"); 584 } else { 585 print("Target $path: not a derived file\n"); 586 } 587 } 588 if ($param::build) { 589 return build $tgt; 590 } elsif ($param::pflag || $param::wflag || $param::aflag) { 591 if ($tgt->{builder}) { 592 if ($param::wflag) { 593 print qq(${\$tgt->path}: $tgt->{script}\n); 594 } elsif ($param::pflag) { 595 print qq(${\$tgt->path}:\n) if $param::aflag; 596 print qq(${\$tgt->path}\n) if !$param::aflag; 597 } 598 if ($param::aflag) { 599 $tgt->{builder}->action($tgt); 600 } 601 } 602 } elsif ($param::rflag && $tgt->{builder}) { 603 my($path) = $tgt->path; 604 if (-f $path) { 605 if (unlink($path)) { 606 print("Removed $path\n") if ($param::quiet < 1); 607 } else { 608 warn("$0: couldn't remove $path\n"); 609 } 610 } 611 } 612 613 return "none"; 614 } 615 616 package NameSpace; 617 618 # Return a hash that maps the name of symbols in a namespace to an 619 # array of refs for all types for which the name has a defined value. 620 # A list of symbols may be specified; default is all symbols in the 621 # name space. 622 sub save { 623 my $package = shift; 624 my(%namerefs, $var, $type); 625 no strict 'refs'; 626 @_ = keys %{$package."::"} if ! @_; 627 foreach $var (@_) { 628 $namerefs{$var} = []; 629 my $fqvar = $package."::".$var; 630 # If the scalar for this variable name doesn't already 631 # exist, *foo{SCALAR} will autovivify the reference 632 # instead of returning undef, so unlike the other types, 633 # we have to dereference to find out if it exists. 634 push(@{$namerefs{$var}}, *{$fqvar}{SCALAR}) 635 if defined ${*{$fqvar}{SCALAR}}; 636 foreach $type (qw(ARRAY HASH CODE IO)) { 637 push(@{$namerefs{$var}}, *{$fqvar}{$type}) 638 if defined *{$fqvar}{$type}; 639 } 640 } 641 return \%namerefs; 642 } 643 644 # Remove the specified symbols from the namespace. 645 # Default is to remove all. 646 sub remove { 647 my $package = shift; 648 my(%namerefs, $var); 649 no strict 'refs'; 650 @_ = keys %{$package."::"} if ! @_; 651 foreach $var (@_) { 652 delete ${$package."::"}{$var}; 653 } 654 } 655 656 # Restore values to symbols specified in a hash as returned 657 # by NameSpace::save. 658 sub restore { 659 my($package, $namerefs) = @_; 660 my($var, $ref); 661 no strict 'refs'; 662 foreach $var (keys %$namerefs) { 663 my $fqvar = $package."::".$var; 664 foreach $ref (@{$namerefs->{$var}}) { 665 *{$fqvar} = $ref; 666 } 667 } 668 } 669 670 # Support for "building" scripts, importing and exporting variables. 671 # With the exception of the top-level routine here (invoked from the 672 # main package by cons), these are all invoked by user scripts. 673 package script; 674 675 use vars qw( $ARG $caller_dir_path %special_var ); 676 677 BEGIN { 678 # We can't Export or Import the following variables because Perl always 679 # treats them as part of the "main::" package (see perlvar(1)). 680 %special_var = map {$_ => 1} qw(ENV INC ARGV ARGVOUT SIG 681 STDIN STDOUT STDERR); 682 } 683 684 # This is called from main to interpret/run the top-level Construct 685 # file, passed in as the single argument. 686 sub main::doscripts { 687 my($script) = @_; 688 Build($script); 689 # Now set up the includes/excludes (after the Construct file is read). 690 $param::include = join('|', @param::include); 691 692 # Save the original variable names from the script package. 693 # These will stay intact, but any other "script::" variables 694 # defined in a Conscript file will get saved, deleted, 695 # and (when necessary) restored. 696 my(%orig_script_var) = map {$_ => 1} keys %script::; 697 $caller_dir_path = undef; 698 my $cwd = Cwd::cwd(); 699 my(@scripts) = pop(@priv::scripts); 700 while ($priv::self = shift(@scripts)) { 701 my($path) = $priv::self->{script}->rsrcpath; 702 if (-f $path) { 703 $dir::cwd = $priv::self->{script}->{dir}; 704 # Handle chdir to the Conscript file directory, if necessary. 705 my ($vol, $dir, $file); 706 if ($param::conscript_chdir) { 707 ($vol, $dir, $file) = 708 File::Spec->splitpath(File::Spec->canonpath($path)); 709 if ($vol ne '' || $dir ne '') { 710 $caller_dir_path = File::Spec->catpath($vol, $dir, undef); 711 chdir($caller_dir_path) || 712 die "Could not chdir to $caller_dir_path: $!\n"; 713 } 714 } else { 715 $file = $path; 716 } 717 # Actually process the Conscript file. 718 do $file; 719 # Save any variables defined by the Conscript file 720 # so we can restore them later, if needed; 721 # then delete them from the script:: namespace. 722 my(@del) = grep(! $orig_script_var{$_}, keys %script::); 723 if (@del) { 724 $priv::self->{script}->{pkgvars} = NameSpace::save('script', 725 @del); 726 NameSpace::remove('script', @del); 727 } 728 if ($caller_dir_path) { 729 chdir($cwd); 730 $caller_dir_path = undef; 731 } 732 if ($@) { 733 chomp($@); 734 my $err = ($@ =~ /\n/ms) ? ":\n$@" : " ($@)"; 735 print qq($0: error in file "$path"$err\n); 736 $run::errors++; 737 } else { 738 # Only process subsidiary scripts if no errors in parent. 739 unshift(@scripts, @priv::scripts); 740 } 741 undef @priv::scripts; 742 } else { 743 my $where = ''; 744 my $cref = $priv::self->{script}->creator; 745 if (defined $cref) { 746 my($_foo, $script, $line, $sub) = @$cref; 747 $where = " ($sub in $script, line $line)"; 748 } 749 warn qq(Ignoring missing script "$path"$where); 750 } 751 } 752 die("$0: script errors encountered: construction aborted\n") 753 if $run::errors; 754 } 755 756 # Return caller info about the method being invoked. 757 # This is everything from the Perl "caller" builtin function, 758 # including which Construct/Conscript file, line number, 759 # subroutine name, etc. 760 sub caller_info { 761 my($lev) = 1; 762 my(@frame); 763 do { 764 @frame = caller ++$lev; 765 if (defined($frame[3]) && $frame[3] eq '(eval)') { 766 @frame = caller --$lev; 767 if ($caller_dir_path) { 768 $frame[1] = File::Spec->catfile($caller_dir_path, $frame[1]); 769 } 770 return @frame; 771 } 772 } while ($frame[3]); 773 return; 774 } 775 776 # Link a directory to another. This simply means set up the *source* 777 # for the directory to be the other directory. 778 sub Link { 779 dir::link(@_); 780 } 781 782 # Add directories to the repository search path for files. 783 # Strip our current directory from the list so Repository 784 # (or -R options) can be used from within the repository. 785 sub Repository { 786 my($my_dir) = Cwd::cwd(); 787 my $dir; 788 foreach $dir (@_) { 789 # The following more direct call isn't available in 790 # Cwd.pm until some time after 5.003... 791 # my($d) = Cwd::abs_path($dir); 792 chdir($dir); 793 my($d) = Cwd::cwd(); 794 chdir($my_dir); 795 # 796 next if ! $d || ! -d $d || $d eq $my_dir; 797 # We know we can get away with passing undef to lookupdir 798 # as the directory because $dir is an absolute path. 799 push(@param::rpath, dir::lookupdir(undef, $dir)); 800 push @INC, $d; 801 } 802 } 803 804 # Return the list of Repository directories specified. 805 sub Repository_List { 806 map($_->path, @param::rpath); 807 } 808 809 # Specify whether the .consign signature times in repository files are, 810 # in fact, consistent with the times on the files themselves. 811 sub Repository_Sig_Times_OK { 812 $param::rep_sig_times_ok = shift; 813 } 814 815 sub SourceSignature { 816 $param::sourcesig = [@_]; 817 } 818 819 # Specify whether we should chdir to the containing directories 820 # of Conscript files. 821 sub Conscript_chdir { 822 $param::conscript_chdir = shift; 823 } 824 825 # Specify files/targets that must be present and built locally, 826 # even if they exist already-built in a Repository. 827 sub Local { 828 my(@files) = map($dir::cwd->lookupfile($_), @_); 829 map($_->local(1), @files); 830 } 831 832 # Export variables to any scripts invoked from this one. 833 sub Export { 834 my(@illegal) = grep($special_var{$_}, @_); 835 if (@illegal) { 836 die qq($0: cannot Export special Perl variables: @illegal\n); 837 } 838 @{$priv::self->{exports}} = grep(! defined $special_var{$_}, @_); 839 } 840 841 # Import variables from the export list of the caller 842 # of the current script. 843 sub Import { 844 my(@illegal) = grep($special_var{$_}, @_); 845 if (@illegal) { 846 die qq($0: cannot Import special Perl variables: @illegal\n); 847 } 848 my($parent) = $priv::self->{parent}; 849 my($imports) = $priv::self->{imports}; 850 @{$priv::self->{exports}} = keys %$imports; 851 my($var); 852 foreach $var (grep(! defined $special_var{$_}, @_)) { 853 if (!exists $imports->{$var}) { 854 my($path) = $parent->{script}->path; 855 die qq($0: variable "$var" not exported by file "$path"\n); 856 } 857 if (!defined $imports->{$var}) { 858 my $path = $parent->{script}->path; 859 my $err = "$0: variable \"$var\" exported but not " . 860 "defined by file \"$path\"\n"; 861 die $err; 862 } 863 ${"script::$var"} = $imports->{$var}; 864 } 865 } 866 867 # Build an inferior script. That is, arrange to read and execute 868 # the specified script, passing to it any exported variables from 869 # the current script. 870 sub Build { 871 my(@files) = map($dir::cwd->lookupfile($_), @_); 872 my(%imports) = map {$_ => ${"script::$_"}} @{$priv::self->{exports}}; 873 my $file; 874 for $file (@files) { 875 next if $param::include && $file->path !~ /$param::include/o; 876 my($self) = {'script' => $file, 877 'parent' => $priv::self, 878 'imports' => \%imports}; 879 bless $self; # may want to bless into class of parent in future 880 push(@priv::scripts, $self); 881 } 882 } 883 884 # Set up regexps dependencies to ignore. Should only be called once. 885 sub Ignore { 886 die("Ignore called more than once\n") if $param::ignore; 887 $param::ignore = join("|", map("($_)", @_)) if @_; 888 } 889 890 # Specification of default targets. 891 sub Default { 892 push(@param::default_targets, map($dir::cwd->lookup($_)->path, @_)); 893 } 894 895 # Local Help. Should only be called once. 896 sub Help { 897 if ($param::localhelp) { 898 print "@_\n"; 899 exit 2; 900 } 901 } 902 903 # For windows platforms which use unix tool sets, the msvc defaults may 904 # not be useful. Also, in the future, other platforms (Mac?) may have the 905 # same problem. 906 sub RuleSet { 907 my $style = shift; 908 my @rulesets = sort keys %param::rulesets; 909 die "Unknown style for rules: $style.\n" . 910 "Supported rules are: (" . join(" ", @rulesets) . ")" 911 unless eval(join("||", map("\$style eq '$_'", @rulesets))); 912 return @param::base, @{$param::rulesets{$style}}; 913 } 914 915 sub DefaultRules { 916 @param::defaults = (); 917 push @param::defaults, @_; 918 } 919 920 # Return the build name(s) of a file or file list. 921 sub FilePath { 922 wantarray 923 ? map($dir::cwd->lookupfile($_)->path, @_) 924 : $dir::cwd->lookupfile($_[0])->path; 925 } 926 927 # Return the build name(s) of a directory or directory list. 928 sub DirPath { 929 wantarray 930 ? map($dir::cwd->lookupdir($_)->path, @_) 931 : $dir::cwd->lookupdir($_[0])->path; 932 } 933 934 # Split the search path provided into components. Look each up 935 # relative to the current directory. 936 # The usual path separator problems abound; for now we'll use : 937 sub SplitPath { 938 my($dirs) = @_; 939 if (ref($dirs) ne "ARRAY") { 940 $dirs = [ split(/$main::PATH_SEPARATOR/o, $dirs) ]; 941 } 942 map { DirPath($_) } @$dirs; 943 } 944 945 # Return true if the supplied path is available as a source file 946 # or is buildable (by rules seen to-date in the build). 947 sub ConsPath { 948 my($path) = @_; 949 my($file) = $dir::cwd->lookup($path); 950 return $file->accessible; 951 } 952 953 # Return the source path of the supplied path. 954 sub SourcePath { 955 wantarray 956 ? map($dir::cwd->lookupfile($_)->rsrcpath, @_) 957 : $dir::cwd->lookupfile($_[0])->rsrcpath; 958 } 959 960 # Search up the tree for the specified cache directory, starting with 961 # the current directory. Returns undef if not found, 1 otherwise. 962 # If the directory is found, then caching is enabled. The directory 963 # must be readable and writable. If the argument "mixtargets" is provided, 964 # then targets may be mixed in the cache (two targets may share the same 965 # cache file--not recommended). 966 sub UseCache($@) { 967 my($dir, @args) = @_; 968 # NOTE: it's important to process arguments here regardless of whether 969 # the cache is disabled temporarily, since the mixtargets option affects 970 # the salt for derived signatures. 971 for (@args) { 972 if ($_ eq "mixtargets") { 973 # When mixtargets is enabled, we salt the target signatures. 974 # This is done purely to avoid a scenario whereby if 975 # mixtargets is turned on or off after doing builds, and 976 # if cache synchronization with -cs is used, then 977 # cache files may be shared in the cache itself (linked 978 # under more than one name in the cache). This is not bad, 979 # per se, but simply would mean that a cache cleaning algorithm 980 # that looked for a link count of 1 would never find those 981 # particular files; they would always appear to be in use. 982 $param::salt = 'M' . $param::salt; 983 $param::mixtargets = 1; 984 } else { 985 die qq($0: UseCache unrecognized option "$_"\n); 986 } 987 } 988 if ($param::cachedisable) { 989 warn("Note: caching disabled by -cd flag\n"); 990 return 1; 991 } 992 my($depth) = 15; 993 while ($depth-- && ! -d $dir) { 994 $dir = File::Spec->catdir($dir::UPDIR, $dir); 995 } 996 if (-d $dir) { 997 $param::cache = $dir; 998 return 1; 999 } 1000 return undef; 1001 } 1002 1003 # Salt the signature generator. The salt (a number of string) is added 1004 # into the signature of each derived file. Changing the salt will 1005 # force recompilation of all derived files. 1006 sub Salt($) { 1007 # We append the value, so that UseCache and Salt may be used 1008 # in either order without changing the signature calculation. 1009 $param::salt .= $_[0]; 1010 } 1011 1012 # Mark files (or directories) to not be removed before building. 1013 sub Precious { 1014 map($_->{precious} = 1, map($dir::cwd->lookup($_), @_)); 1015 } 1016 1017 1018 # These methods are callable from Conscript files, via a cons 1019 # object. Procs beginning with _ are intended for internal use. 1020 package cons; 1021 1022 use vars qw( %envcache ); 1023 1024 # This is passed the name of the base environment to instantiate. 1025 # Overrides to the base environment may also be passed in 1026 # as key/value pairs. 1027 sub new { 1028 my($package) = shift; 1029 my ($env) = {@param::defaults, @_}; 1030 @{$env->{_envcopy}} = %$env; # Note: we never change PATH 1031 $env->{_cwd} = $dir::cwd; # Save directory of environment for 1032 bless $env, $package; # any deferred name interpretation. 1033 } 1034 1035 # Clone an environment. 1036 # Note that the working directory will be the initial directory 1037 # of the original environment. 1038 sub clone { 1039 my($env) = shift; 1040 my $clone = {@{$env->{_envcopy}}, @_}; 1041 @{$clone->{_envcopy}} = %$clone; # Note: we never change PATH 1042 $clone->{_cwd} = $env->{_cwd}; 1043 bless $clone, ref $env; 1044 } 1045 1046 # Create a flattened hash representing the environment. 1047 # It also contains a copy of the PATH, so that the path 1048 # may be modified if it is converted back to a hash. 1049 sub copy { 1050 my($env) = shift; 1051 (@{$env->{_envcopy}}, 'ENV' => {%{$env->{ENV}}}, @_) 1052 } 1053 1054 # Resolve which environment to actually use for a given 1055 # target. This is just used for simple overrides. 1056 sub _resolve { 1057 return $_[0] if !$param::overrides; 1058 my($env, $tgt) = @_; 1059 my($path) = $tgt->path; 1060 my $re; 1061 for $re (@param::overrides) { 1062 next if $path !~ /$re/; 1063 # Found one. Return a combination of the original environment 1064 # and the override. 1065 my($ovr) = $param::overrides{$re}; 1066 return $envcache{$env,$re} if $envcache{$env,$re}; 1067 my($newenv) = {@{$env->{_envcopy}}, @$ovr}; 1068 @{$newenv->{_envcopy}} = %$env; 1069 $newenv->{_cwd} = $env->{_cwd}; 1070 return $envcache{$env,$re} = bless $newenv, ref $env; 1071 } 1072 return $env; 1073 } 1074 1075 # Substitute construction environment variables into a string. 1076 # Internal function/method. 1077 sub _subst { 1078 my($env, $str) = @_; 1079 if (! defined $str) { 1080 return undef; 1081 } elsif (ref($str) eq "ARRAY") { 1082 return [ map($env->_subst($_), @$str) ]; 1083 } else { 1084 # % expansion. %% gets converted to % later, so expand any 1085 # %keyword construction that doesn't have a % in front of it, 1086 # modulo multiple %% pairs in between. 1087 # In Perl 5.005 and later, we could actually do this in one regex 1088 # using a conditional expression as follows, 1089 # while ($str =~ s/($pre)\%(\{)?([_a-zA-Z]\w*)(?(2)\})/"$1". 1090 # $env->{$3}/ge) {} 1091 # The following two-step approach is backwards-compatible 1092 # to (at least) Perl5.003. 1093 my $pre = '^|[^\%](?:\%\%)*'; 1094 while (($str =~ s/($pre)\%([_a-zA-Z]\w*)/$1.($env->{$2}||'')/ge) || 1095 ($str =~ s/($pre)\%\{([_a-zA-Z]\w*)\}/$1.($env->{$2}||'')/ge)) { 1096 } 1097 return $str; 1098 } 1099 } 1100 1101 sub AfterBuild { 1102 my($env) = shift; 1103 my($perl_eval_str) = pop(@_); 1104 my $file; 1105 for $file (map($dir::cwd->lookup($_), @_)) { 1106 $file->{after_build_func} = $perl_eval_str; 1107 } 1108 } 1109 1110 sub Install { 1111 my($env) = shift; 1112 my($tgtdir) = $dir::cwd->lookupdir($env->_subst(shift)); 1113 my $file; 1114 for $file (map($dir::cwd->lookupfile($env->_subst($_)), @_)) { 1115 my($tgt) = $tgtdir->lookupfile($file->{entry}); 1116 $tgt->bind(find build::install($env), $file); 1117 } 1118 } 1119 1120 sub InstallAs { 1121 my $env = shift; 1122 my $tgt = shift; 1123 my $src = shift; 1124 my @sources = (); 1125 my @targets = (); 1126 1127 if (ref $tgt) { 1128 die "InstallAs: Source is a file and target is a list!\n" 1129 if (!ref($src)); 1130 @sources = @$src; 1131 @targets = @$tgt; 1132 } elsif (ref $src) { 1133 die "InstallAs: Target is a file and source is a list!\n"; 1134 } else { 1135 push @sources, $src; 1136 push @targets, $tgt; 1137 } 1138 1139 if ($#sources != $#targets) { 1140 my $tn = $#targets+1; 1141 my $sn = $#sources+1; 1142 die "InstallAs: Source file list ($sn) and target file list ($tn) " . 1143 "are inconsistent in length!\n"; 1144 } else { 1145 foreach (0..$#sources) { 1146 my $tfile = $dir::cwd->lookupfile($env->_subst($targets[$_])); 1147 my $sfile = $dir::cwd->lookupfile($env->_subst($sources[$_])); 1148 $tfile->bind(find build::install($env), $sfile); 1149 } 1150 } 1151 } 1152 1153 # Installation in a local build directory, 1154 # copying from the repository if it's already built there. 1155 # Functionally equivalent to: 1156 # Install $env $dir, $file; 1157 # Local "$dir/$file"; 1158 sub Install_Local { 1159 my($env) = shift; 1160 my($tgtdir) = $dir::cwd->lookupdir($env->_subst(shift)); 1161 my $file; 1162 for $file (map($dir::cwd->lookupfile($env->_subst($_)), @_)) { 1163 my($tgt) = $tgtdir->lookupfile($file->{entry}); 1164 $tgt->bind(find build::install($env), $file); 1165 $tgt->local(1); 1166 } 1167 } 1168 1169 sub Objects { 1170 my($env) = shift; 1171 map($dir::cwd->relpath($_), $env->_Objects(@_)); 1172 } 1173 1174 # Called with multiple source file references (or object files). 1175 # Returns corresponding object files references. 1176 sub _Objects { 1177 my($env) = shift; 1178 my($suffix) = $env->{SUFOBJ}; 1179 map($env->_Object($_, $_->{dir}->lookupfile($_->base_suf($suffix))), 1180 map { ref $_ ? $_ : $dir::cwd->lookupfile($env->_subst($_)) } 1181 grep(defined $_, @_)); 1182 } 1183 1184 # Called with an object and source reference. If no object reference 1185 # is supplied, then the object file is determined implicitly from the 1186 # source file's extension. Sets up the appropriate rules for creating 1187 # the object from the source. Returns the object reference. 1188 sub _Object { 1189 my($env, $src, $obj) = @_; 1190 return $obj if $src eq $obj; # don't need to build self from self. 1191 my($objenv) = $env->_resolve($obj); 1192 my($suffix) = $src->suffix; 1193 1194 my($builder) = $env->{SUFMAP}{$suffix}; 1195 1196 if ($builder) { 1197 $obj->bind((find $builder($objenv)), $src); 1198 } else { 1199 die("don't know how to construct ${\$obj->path} from " . 1200 "${\$src->path}.\n"); 1201 } 1202 $obj 1203 } 1204 1205 sub Program { 1206 my($env) = shift; 1207 my($tgt) = $dir::cwd->lookupfile(file::addsuffix($env->_subst(shift), 1208 $env->{SUFEXE})); 1209 my($progenv) = $env->_resolve($tgt); 1210 $tgt->bind(find build::command::link($progenv, $progenv->{LINKCOM}), 1211 $env->_Objects(@_)); 1212 } 1213 1214 sub Module { 1215 my($env) = shift; 1216 my($tgt) = $dir::cwd->lookupfile($env->_subst(shift)); 1217 my($modenv) = $env->_resolve($tgt); 1218 my($com) = pop(@_); 1219 $tgt->bind(find build::command::link($modenv, $com), $env->_Objects(@_)); 1220 } 1221 1222 sub LinkedModule { 1223 my($env) = shift; 1224 my($tgt) = $dir::cwd->lookupfile($env->_subst(shift)); 1225 my($progenv) = $env->_resolve($tgt); 1226 $tgt->bind(find build::command::linkedmodule 1227 ($progenv, $progenv->{LINKMODULECOM}), 1228 $env->_Objects(@_)); 1229 } 1230 1231 sub Library { 1232 my($env) = shift; 1233 my($lib) = $dir::cwd->lookupfile(file::addsuffix($env->_subst(shift), 1234 $env->{SUFLIB})); 1235 my($libenv) = $env->_resolve($lib); 1236 $lib->bind(find build::command::library($libenv), $env->_Objects(@_)); 1237 } 1238 1239 # Simple derivation: you provide target, source(s), command. 1240 # Special variables substitute into the rule. 1241 # Target may be a reference, in which case it is taken 1242 # to be a multiple target (all targets built at once). 1243 sub Command { 1244 my($env) = shift; 1245 my($tgt) = $env->_subst(shift); 1246 my($builder) = find build::command::user($env, pop(@_), 'script'); 1247 my(@sources) = map($dir::cwd->lookupfile($env->_subst($_)), @_); 1248 if (ref($tgt)) { 1249 # A multi-target command. 1250 my(@tgts) = map($dir::cwd->lookupfile($_), @$tgt); 1251 die("empty target list in multi-target command\n") if !@tgts; 1252 $env = $env->_resolve($tgts[0]); 1253 my($multi) = build::multiple->new($builder, \@tgts); 1254 for $tgt (@tgts) { 1255 $tgt->bind($multi, @sources); 1256 } 1257 } else { 1258 $tgt = $dir::cwd->lookupfile($tgt); 1259 $env = $env->_resolve($tgt); 1260 $tgt->bind($builder, @sources); 1261 } 1262 } 1263 1264 sub Depends { 1265 my($env) = shift; 1266 my($tgt) = $env->_subst(shift); 1267 my(@deps) = map($dir::cwd->lookup($env->_subst($_)), @_); 1268 if (! ref($tgt)) { 1269 $tgt = [ $tgt ]; 1270 } 1271 my($t); 1272 foreach $t (map($dir::cwd->lookupfile($_), @$tgt)) { 1273 push(@{$t->{dep}}, @deps); 1274 } 1275 } 1276 1277 # Setup a quick scanner for the specified input file, for the 1278 # associated environment. Any use of the input file will cause the 1279 # scanner to be invoked, once only. The scanner sees just one line at 1280 # a time of the file, and is expected to return a list of 1281 # dependencies. 1282 sub QuickScan { 1283 my($env, $code, $file, $path) = @_; 1284 $dir::cwd->lookup($env->_subst($file))->{'srcscan',$env} = 1285 find scan::quickscan($code, $env, $env->_subst($path)); 1286 } 1287 1288 # Generic builder module. Just a few default methods. Every derivable 1289 # file must have a builder object of some sort attached. Usually 1290 # builder objects are shared. 1291 package build; 1292 1293 use vars qw( %builder ); 1294 1295 # Every builder must now have at least an associated environment, 1296 # so we can find its sigarray and calculate the proper signature. 1297 sub find { 1298 my($class, $env) = @_; 1299 $builder{$env} || do { 1300 my $self = { env => $env }; 1301 $builder{$env} = bless $self, $class; 1302 } 1303 } 1304 1305 # Null signature for dynamic includes. 1306 sub includes { () } 1307 1308 # Null signature for build script. 1309 sub scriptsig { () } 1310 1311 # Not compatible with any other builder, by default. 1312 sub compatible { 0 } 1313 1314 1315 # Builder module for the Install command. 1316 package build::install; 1317 1318 use vars qw( @ISA ); 1319 1320 BEGIN { @ISA = qw(build) } 1321 1322 # Caching not supported for Install: generally install is trivial anyway, 1323 # and we don't want to clutter the cache. 1324 sub cachin { undef } 1325 sub cachout { } 1326 1327 # Do the installation. 1328 sub action { 1329 my($self, $tgt) = @_; 1330 my($src) = $tgt->{sources}[0]; 1331 main::showcom("Install ${\$src->rpath} as ${\$tgt->path}") 1332 if ($param::install && $param::quiet < 1); 1333 return unless $param::build; 1334 futil::install($src->rpath, $tgt); 1335 return 1; 1336 } 1337 1338 1339 # Builder module for generic UNIX commands. 1340 package build::command; 1341 1342 use vars qw( @ISA %com ); 1343 1344 BEGIN { @ISA = qw(build) } 1345 1346 sub find { 1347 my($class, $env, $cmd, $package) = @_; 1348 my($act) = action::new($env, $cmd); 1349 $package ||= ''; 1350 $com{$env,$act,$package} || do { 1351 my $self = { env => $env, act => $act, 'package' => $package }; 1352 $com{$env,$act,$package} = bless $self, $class; 1353 } 1354 } 1355 1356 # Default cache in function. 1357 sub cachin { 1358 my($self, $tgt, $sig) = @_; 1359 if (cache::in($tgt, $sig)) { 1360 if ($param::cachecom) { 1361 $self->{act}->show($self->{env}, $tgt); 1362 } else { 1363 printf("Retrieved %s from cache\n", $tgt->path) 1364 if ($param::quiet < 1); 1365 } 1366 return 1; 1367 } 1368 return undef; 1369 } 1370 1371 # Default cache out function. 1372 sub cachout { 1373 my($self, $tgt, $sig) = @_; 1374 cache::out($tgt, $sig); 1375 } 1376 1377 # Build the target using the previously specified commands. 1378 sub action { 1379 my($self, $tgt) = @_; 1380 $self->{act}->execute($self->{env}, $tgt, $self->{'package'}); 1381 } 1382 1383 # Return script signature. 1384 sub scriptsig { 1385 $_[0]->{act}->scriptsig 1386 } 1387 1388 1389 # Create a linked module. 1390 package build::command::link; 1391 1392 use vars qw( @ISA ); 1393 1394 BEGIN { @ISA = qw(build::command) } 1395 1396 # Find an appropriate linker. 1397 sub find { 1398 my($class, $env, $command) = @_; 1399 if (!exists $env->{_LDIRS}) { 1400 my($ldirs) = ''; 1401 my($wd) = $env->{_cwd}; 1402 my($pdirs) = $env->{LIBPATH}; 1403 if (! defined $pdirs) { 1404 $pdirs = [ ]; 1405 } elsif (ref($pdirs) ne 'ARRAY') { 1406 $pdirs = [ split(/$main::PATH_SEPARATOR/o, $pdirs) ]; 1407 } 1408 my($dir, $dpath); 1409 for $dir (map($wd->lookupdir($env->_subst($_)), @$pdirs)) { 1410 $dpath = $dir->path; 1411 # Add the (presumably local) directory to the -L flags 1412 # if we're not using repositories, the directory exists, 1413 # or it's Linked to a source directory (that is, it *will* 1414 # exist by the time the link occurs). 1415 $ldirs .= " ".$env->{LIBDIRPREFIX}.$dpath.$env->{LIBDIRSUFFIX} 1416 if ! @param::rpath || -d $dpath || $dir->is_linked; 1417 next if File::Spec->file_name_is_absolute($dpath); 1418 if (@param::rpath) { 1419 my $d; 1420 if ($dpath eq $dir::CURDIR) { 1421 foreach $d (map($_->path, @param::rpath)) { 1422 $ldirs .= " " . $env->{LIBDIRPREFIX} . 1423 $d . $env->{LIBDIRSUFFIX}; 1424 } 1425 } else { 1426 my($rpath); 1427 foreach $d (map($_->path, @param::rpath)) { 1428 $rpath = File::Spec->catfile($d, $dpath); 1429 $ldirs .= " ". $env->{LIBDIRPREFIX} . 1430 $rpath . $env->{LIBDIRSUFFIX} if -d $rpath; 1431 } 1432 } 1433 } 1434 } 1435 $env->{_LDIRS} = "%($ldirs%)"; 1436 } 1437 1438 # Introduce a new magic _LIBS symbol which allows to use the 1439 # Unix-style -lNAME syntax for Win32 only. -lNAME will be replaced 1440 # with %{PREFLIB}NAME%{SUFLIB}. <schwarze@isa.de> 1998-06-18 1441 1442 if ($main::_WIN32 && !exists $env->{_LIBS}) { 1443 my $libs; 1444 my $name; 1445 for $name (split(' ', $env->_subst($env->{LIBS} || ''))) { 1446 if ($name =~ /^-l(.*)/) { 1447 $name = "$env->{PREFLIB}$1$env->{SUFLIB}"; 1448 } 1449 $libs .= ' ' . $name; 1450 } 1451 $env->{_LIBS} = $libs ? "%($libs%)" : ''; 1452 } 1453 bless find build::command($env, $command); 1454 } 1455 1456 # Called from file::build. Make sure any libraries needed by the 1457 # environment are built, and return the collected signatures 1458 # of the libraries in the path. 1459 sub includes { 1460 return $_[0]->{'bsig'} if exists $_[0]->{'bsig'}; 1461 my($self, $tgt) = @_; 1462 my($env) = $self->{env}; 1463 my($ewd) = $env->{_cwd}; 1464 my $ldirs = $env->{LIBPATH}; 1465 if (! defined $ldirs) { 1466 $ldirs = [ ]; 1467 } elsif (ref($ldirs) ne 'ARRAY') { 1468 $ldirs = [ split(/$main::PATH_SEPARATOR/o, $ldirs) ]; 1469 } 1470 my @lpath = map($ewd->lookupdir($_), @$ldirs); 1471 my(@sigs); 1472 my(@names); 1473 1474 # Pass %LIBS symbol through %-substituition 1475 # <schwarze@isa.de> 1998-06-18 1476 @names = split(' ', $env->_subst($env->{LIBS} || '')); 1477 my $name; 1478 for $name (@names) { 1479 my ($lpath, @allnames); 1480 if ($name =~ /^-l(.*)/) { 1481 # -l style names are looked up on LIBPATH, using all 1482 # possible lib suffixes in the same search order the 1483 # linker uses (according to SUFLIBS). 1484 # Recognize new PREFLIB symbol, which should be 'lib' on 1485 # Unix, and empty on Win32. TODO: What about shared 1486 # library suffixes? <schwarze@isa.de> 1998-05-13 1487 @allnames = map("$env->{PREFLIB}$1$_", 1488 split(/:/, $env->{SUFLIBS})); 1489 $lpath = \@lpath; 1490 } else { 1491 @allnames = ($name); 1492 # On Win32, all library names are looked up in LIBPATH 1493 # <schwarze@isa.de> 1998-05-13 1494 if ($main::_WIN32) { 1495 $lpath = [$dir::top, @lpath]; 1496 } 1497 else { 1498 $lpath = [$dir::top]; 1499 } 1500 } 1501 my $dir; 1502 DIR: for $dir (@$lpath) { 1503 my $n; 1504 for $n (@allnames) { 1505 my($lib) = $dir->lookup_accessible($n); 1506 if ($lib) { 1507 last DIR if $lib->ignore; 1508 if ((build $lib) eq 'errors') { 1509 $tgt->{status} = 'errors'; 1510 return undef; 1511 } 1512 push(@sigs, 'sig'->signature($lib)); 1513 last DIR; 1514 } 1515 } 1516 } 1517 } 1518 $self->{'bsig'} = 'sig'->collect(@sigs); 1519 } 1520 1521 # Always compatible with other such builders, so the user 1522 # can define a single program or module from multiple places. 1523 sub compatible { 1524 my($self, $other) = @_; 1525 ref($other) eq "build::command::link"; 1526 } 1527 1528 # Link a program. 1529 package build::command::linkedmodule; 1530 1531 use vars qw( @ISA ); 1532 1533 BEGIN { @ISA = qw(build::command) } 1534 1535 # Always compatible with other such builders, so the user 1536 # can define a single linked module from multiple places. 1537 sub compatible { 1538 my($self, $other) = @_; 1539 ref($other) eq "build::command::linkedmodule"; 1540 } 1541 1542 # Builder for a C module 1543 package build::command::cc; 1544 1545 use vars qw( @ISA ); 1546 1547 BEGIN { @ISA = qw(build::command) } 1548 1549 sub find { 1550 $_[1]->{_cc} || do { 1551 my($class, $env) = @_; 1552 my($cpppath) = $env->_subst($env->{CPPPATH}); 1553 my($cscanner) = find scan::cpp($env->{_cwd}, $cpppath); 1554 $env->{_IFLAGS} = "%(" . $cscanner->iflags($env) . "%)"; 1555 my($self) = find build::command($env, $env->{CCCOM}); 1556 $self->{scanner} = $cscanner; 1557 bless $env->{_cc} = $self; 1558 } 1559 } 1560 1561 # Invoke the associated C scanner to get signature of included files. 1562 sub includes { 1563 my($self, $tgt) = @_; 1564 $self->{scanner}->includes($tgt, $tgt->{sources}[0]); 1565 } 1566 1567 # Builder for a C++ module 1568 package build::command::cxx; 1569 1570 use vars qw( @ISA ); 1571 1572 BEGIN { @ISA = qw(build::command) } 1573 1574 sub find { 1575 $_[1]->{_cxx} || do { 1576 my($class, $env) = @_; 1577 my($cpppath) = $env->_subst($env->{CPPPATH}); 1578 my($cscanner) = find scan::cpp($env->{_cwd}, $cpppath); 1579 $env->{_IFLAGS} = "%(" . $cscanner->iflags($env) . "%)"; 1580 my($self) = find build::command($env, $env->{CXXCOM}); 1581 $self->{scanner} = $cscanner; 1582 bless $env->{_cxx} = $self; 1583 } 1584 } 1585 1586 # Invoke the associated C scanner to get signature of included files. 1587 sub includes { 1588 my($self, $tgt) = @_; 1589 $self->{scanner}->includes($tgt, $tgt->{sources}[0]); 1590 } 1591 1592 # Builder for a user command (cons::Command). We assume that a user 1593 # command might be built and implement the appropriate dependencies on 1594 # the command itself (actually, just on the first word of the command 1595 # line). 1596 package build::command::user; 1597 1598 use vars qw( @ISA ); 1599 1600 BEGIN { @ISA = qw(build::command) } 1601 1602 sub includes { 1603 my($self, $tgt) = @_; 1604 my($sig) = ''; 1605 1606 # Check for any quick scanners attached to source files. 1607 my $dep; 1608 for $dep (@{$tgt->{dep}}, @{$tgt->{sources}}) { 1609 my($scanner) = $dep->{'srcscan',$self->{env}}; 1610 if ($scanner) { 1611 $sig .= $scanner->includes($tgt, $dep); 1612 } 1613 } 1614 1615 # XXX Optimize this to not use ignored paths. 1616 if (! exists $self->{_comsig}) { 1617 my($env) = $self->{env}; 1618 $self->{_comsig} = ''; 1619 my($com, $dir); 1620 com: 1621 for $com ($self->{act}->commands) { 1622 my($pdirs) = $env->{ENV}->{PATH}; 1623 if (! defined $pdirs) { 1624 $pdirs = [ ]; 1625 } elsif (ref($pdirs) ne 'ARRAY') { 1626 $pdirs = [ split(/$main::PATH_SEPARATOR/o, $pdirs) ]; 1627 } 1628 for $dir (map($dir::top->lookupdir($_), @$pdirs)) { 1629 my($prog) = $dir->lookup_accessible($com); 1630 if ($prog) { # XXX Not checking execute permission. 1631 if ((build $prog) eq 'errors') { 1632 $tgt->{status} = 'errors'; 1633 return $sig; 1634 } 1635 next com if $prog->ignore; 1636 $self->{_comsig} .= 'sig'->signature($prog); 1637 next com; 1638 } 1639 } 1640 } 1641 } 1642 1643 return $self->{_comsig} . $sig 1644 } 1645 1646 1647 # Builder for a library module (archive). 1648 # We assume that a user command might be built and implement the 1649 # appropriate dependencies on the command itself. 1650 package build::command::library; 1651 1652 use vars qw( @ISA ); 1653 1654 BEGIN { @ISA = qw(build::command) } 1655 1656 sub find { 1657 my($class, $env) = @_; 1658 bless find build::command($env, $env->{ARCOM}) 1659 } 1660 1661 # Always compatible with other library builders, so the user 1662 # can define a single library from multiple places. 1663 sub compatible { 1664 my($self, $other) = @_; 1665 ref($other) eq "build::command::library"; 1666 } 1667 1668 # A multi-target builder. 1669 # This allows multiple targets to be associated with a single build 1670 # script, without forcing all the code to be aware of multiple targets. 1671 package build::multiple; 1672 1673 sub new { 1674 my($class, $builder, $tgts) = @_; 1675 bless { 'builder' => $builder, 'env' => $builder->{env}, 'tgts' => $tgts }; 1676 } 1677 1678 sub scriptsig { 1679 my($self, $tgt) = @_; 1680 $self->{builder}->scriptsig($tgt); 1681 } 1682 1683 sub includes { 1684 my($self, $tgt) = @_; 1685 $self->{builder}->includes($tgt); 1686 } 1687 1688 sub compatible { 1689 my($self, $tgt) = @_; 1690 $self->{builder}->compatible($tgt); 1691 } 1692 1693 sub cachin { 1694 my($self, $tgt, $sig) = @_; 1695 $self->{builder}->cachin($tgt, $sig); 1696 } 1697 1698 sub cachout { 1699 my($self, $tgt, $sig) = @_; 1700 $self->{builder}->cachout($tgt, $sig); 1701 } 1702 1703 sub action { 1704 my($self, $invoked_tgt) = @_; 1705 return $self->{built} if exists $self->{built}; 1706 1707 # Make sure all targets in the group are unlinked before building any. 1708 my($tgts) = $self->{tgts}; 1709 my $tgt; 1710 for $tgt (@$tgts) { 1711 futil::mkdir($tgt->{dir}); 1712 unlink($tgt->path) if ! $tgt->precious; 1713 } 1714 1715 # Now do the action to build all the targets. For consistency 1716 # we always call the action on the first target, just so that 1717 # $> is deterministic. 1718 $self->{built} = $self->{builder}->action($tgts->[0]); 1719 1720 # Now "build" all the other targets (except for the one 1721 # we were called with). This guarantees that the signature 1722 # of each target is updated appropriately. We force the 1723 # targets to be built even if they have been previously 1724 # considered and found to be OK; the only effect this 1725 # has is to make sure that signature files are updated 1726 # correctly. 1727 for $tgt (@$tgts) { 1728 if ($tgt ne $invoked_tgt) { 1729 delete $tgt->{status}; 1730 'sig'->invalidate($tgt); 1731 build $tgt; 1732 } 1733 } 1734 1735 # Status of action. 1736 $self->{built}; 1737 } 1738 1739 package action; 1740 1741 sub new { 1742 my($env, $act) = @_; 1743 if (ref($act) eq 'CODE') { 1744 return action::perl->new($act); 1745 } else { 1746 return action::command->new($env, $act); 1747 } 1748 } 1749 1750 package action::command; 1751 1752 use vars qw( @ISA %cmd %_varopts $_varletters ); 1753 1754 BEGIN { 1755 @ISA = $main::_WIN32 ? 'action::command::win32' : 'action::command::unix'; 1756 1757 # Internal hash for processing variable options. 1758 # f: return file part 1759 # d: return directory part 1760 # F: return file part, but strip any suffix 1761 # b: return full path, but strip any suffix (a.k.a. return basename) 1762 # s: return only the suffix (or an empty string, if no suffix is there) 1763 # a: return the absolute path to the file 1764 # S: return the absolute path to a Linked source file 1765 %_varopts = ( 1766 'f' => sub { return $_[0]->{entry}; }, 1767 'd' => sub { return $_[0]->{dir}->path; }, 1768 'F' => sub { my $subst = $_[0]->{entry}; 1769 $subst =~ s/\.[^\.]+$//; 1770 return $subst; }, 1771 'b' => sub { my $subst = $_[0]->path; 1772 $subst =~ s/\.[^\.]+$//; 1773 return $subst; }, 1774 's' => sub { my $subst = $_[0]->{entry}; 1775 $subst =~ m/(\.[^\.]+)$/; 1776 return $1; }, 1777 'a' => sub { my $path = $_[0]->path; 1778 if (! File::Spec->file_name_is_absolute($path)) { 1779 $path = File::Spec->catfile(Cwd::cwd(), $path); 1780 } 1781 return $path; }, 1782 'S' => sub { my $path = $_[0]->srcpath; 1783 if (! File::Spec->file_name_is_absolute($path)) { 1784 my $cwd = File::Spec->canonpath(Cwd::cwd()); 1785 $path = File::Spec->catfile($cwd, $path); 1786 } 1787 return $path; }, 1788 ); 1789 1790 $_varletters = join('', keys %_varopts); 1791 } 1792 1793 # Internal routine for processing variable options. 1794 # Options are specified in hash in the BEGIN block above. 1795 # no option: return path to file (relative to top, 1796 # or absolute if it's outside) 1797 sub _variant { 1798 my($opt, $file) = @_; 1799 $opt = '' if ! defined $opt; 1800 if (defined $_varopts{$opt}) { 1801 return &{$_varopts{$opt}}($file); 1802 } 1803 return $file->path; 1804 } 1805 1806 sub new { 1807 my($class, $env, $cmd) = @_; 1808 $cmd = $env->_subst($cmd); 1809 $cmd{$env,$cmd} || do { 1810 # Remove unwanted bits from signature -- those bracketed by %( ... %) 1811 my $sigs = $cmd; 1812 my $sig = ''; 1813 if (ref($sigs) eq 'ARRAY') { 1814 # This is an array of commands.. 1815 my $f; 1816 foreach $f (@$sigs) { 1817 $sig .= _strip($f); 1818 } 1819 } else { 1820 $sig = _strip($sigs); 1821 } 1822 my $self = { cmd => $cmd, cmdsig => 'sig'->cmdsig($sig) }; 1823 $cmd{$env,$cmd} = bless $self, $class; 1824 } 1825 } 1826 1827 sub _strip { 1828 my $sig = shift; 1829 $sig =~ s/^\@\s*//mg; 1830 while ($sig =~ s/%\(([^%]|%[^\(])*?%\)//g) { } 1831 $sig; 1832 } 1833 1834 sub scriptsig { 1835 $_[0]->{cmdsig}; 1836 } 1837 1838 # Return an array of all the commands (first word on each line). 1839 sub commands { 1840 my($self) = @_; 1841 my(@cmds) = (); 1842 my $com; 1843 my $cmd = $self->{'cmd'}; 1844 my @allcoms; 1845 1846 push @allcoms, ref $cmd ? @{$cmd} : split(/\n/, $cmd); 1847 1848 for $com (@allcoms) { 1849 $com =~ s/^\s*//; 1850 $com =~ s/\s.*//; 1851 next if ! $com; # blank line 1852 push @cmds, $com; 1853 } 1854 @cmds; 1855 } 1856 1857 # For the signature of a basic command, we don't bother 1858 # including the command itself. This is not strictly correct, 1859 # and if we wanted to be rigorous, we might want to insist 1860 # that the command was checked for all the basic commands 1861 # like gcc, etc. For this reason we don't have an includes 1862 # method. 1863 1864 # Call this to get the command line script: an array of 1865 # fully substituted commands. 1866 sub getcoms { 1867 my($self, $env, $tgt) = @_; 1868 my(@coms); 1869 my $com; 1870 my @allcoms = (); 1871 my $cmd = $self->{'cmd'}; 1872 1873 push @allcoms, ref $cmd ? @{$cmd} : split(/\n/, $cmd); 1874 1875 for $com (@allcoms) { 1876 my(@src) = (undef, @{$tgt->{sources}}); 1877 my(@src1) = @src; 1878 1879 next if $com =~ /^\s*$/; 1880 1881 # NOTE: we used to have a more elegant s//.../e solution 1882 # for the items below, but this caused a bus error... 1883 1884 # Remove %( and %) -- those are only used to bracket parts 1885 # of the command that we don't depend on. 1886 $com =~ s/%[()]//g; 1887 1888 # Deal with %n, n=1,9 and variants. 1889 while ($com =~ /%([1-9])(:([$_varletters]?))?/o) { 1890 my($match) = $&; 1891 my($src) = $src1[$1]; 1892 my($subst) = _variant($3, $src1[$1]->rfile); 1893 undef $src[$1]; 1894 $com =~ s/$match/$subst/; 1895 } 1896 1897 # Deal with %0 aka %> and variants. 1898 while ($com =~ /%[0>](:([$_varletters]?))?/o) { 1899 my($match) = $&; 1900 my($subst) = _variant($2, $tgt); 1901 $com =~ s/$match/$subst/; 1902 } 1903 1904 # Deal with %< (all sources except %n's already used) 1905 while ($com =~ /%<(:([$_varletters]?))?/o) { 1906 my($match) = $&; 1907 my @list = (); 1908 foreach (@src) { 1909 push(@list, _variant($2, $_->rfile)) if $_; 1910 } 1911 my($subst) = join(' ', @list); 1912 $com =~ s/$match/$subst/; 1913 } 1914 1915 # Deal with %[ %]. 1916 $com =~ s{%\[(.*?)%\]}{ 1917 my($func, @args) = grep { $_ ne '' } split(/\s+/, $1); 1918 die("$0: \"$func\" is not defined.\n") 1919 unless ($env->{$func}); 1920 &{$env->{$func}}(@args); 1921 }gex; 1922 1923 # Convert left-over %% into %. 1924 $com =~ s/%%/%/g; 1925 1926 # White space cleanup. XXX NO WAY FOR USER TO HAVE QUOTED SPACES 1927 $com = join(' ', split(' ', $com)); 1928 next if $com =~ /^:/ && $com !~ /^:\S/; 1929 push(@coms, $com); 1930 } 1931 @coms 1932 } 1933 1934 # Build the target using the previously specified commands. 1935 sub execute { 1936 my($self, $env, $tgt, $package) = @_; 1937 1938 if ($param::build) { 1939 futil::mkdir($tgt->{dir}); 1940 unlink($tgt->path) if ! $tgt->precious; 1941 } 1942 1943 # Set environment. 1944 map(delete $ENV{$_}, keys %ENV); 1945 %ENV = %{$env->{ENV}}; 1946 1947 # Handle multi-line commands. 1948 my $com; 1949 for $com ($self->getcoms($env, $tgt)) { 1950 if ($com !~ s/^\@\s*//) { 1951 main::showcom($com); 1952 } 1953 next if ! $param::build; 1954 1955 if ($com =~ /^\[perl\]\s*/) { 1956 my $perlcmd = $'; 1957 my $status; 1958 { 1959 # Restore the script package variables that were defined 1960 # in the Conscript file that defined this [perl] build, 1961 # so the code executes with the expected variables. 1962 # Then actually execute (eval) the [perl] command to build 1963 # the target, followed by cleaning up the name space 1964 # by deleting the package variables we just restored. 1965 my($pkgvars) = $tgt->{conscript}->{pkgvars}; 1966 NameSpace::restore($package, $pkgvars) if $pkgvars; 1967 $status = eval "package $package; $perlcmd"; 1968 NameSpace::remove($package, keys %$pkgvars) if $pkgvars; 1969 } 1970 if (!defined($status)) { 1971 warn "$0: *** Error during perl command eval: $@.\n"; 1972 return undef; 1973 } elsif ($status == 0) { 1974 warn "$0: *** Perl command returned $status " 1975 . "(this indicates an error).\n"; 1976 return undef; 1977 } 1978 next; 1979 } 1980 if (! $self->do_command($com, $tgt->path)) { 1981 return undef; 1982 } 1983 } 1984 1985 # success. 1986 return 1; 1987 } 1988 1989 sub show { 1990 my($self, $env, $tgt) = @_; 1991 my $com; 1992 for $com ($self->getcoms($env, $tgt)) { 1993 if ($com !~ /^\@\s*/) { 1994 main::showcom($com); 1995 } 1996 } 1997 } 1998 1999 package action::command::unix; 2000 2001 sub do_command { 2002 my($class, $com, $path) = @_; 2003 my($pid) = fork(); 2004 die("$0: unable to fork child process ($!)\n") if !defined $pid; 2005 if (!$pid) { 2006 # This is the child. We eval the command to suppress -w 2007 # warnings about not reaching the statements afterwards. 2008 eval 'exec($com)'; 2009 $com =~ s/\s.*//; 2010 die qq($0: failed to execute "$com" ($!). ) 2011 . qq(Is this an executable on path "$ENV{PATH}"?\n); 2012 } 2013 for (;;) { 2014 do {} until wait() == $pid; 2015 my ($b0, $b1) = ($? & 0xFF, $? >> 8); 2016 # Don't actually see 0177 on stopped process; is this necessary? 2017 next if $b0 == 0177; # process stopped; we can wait. 2018 if ($b0) { 2019 my($core, $sig) = ($b0 & 0200, $b0 & 0177); 2020 my($coremsg) = $core ? "; core dumped" : ""; 2021 $com =~ s/\s.*//; 2022 my $err = "$0: *** \[$path\] $com terminated by signal " . 2023 "$sig$coremsg\n"; 2024 warn $err; 2025 return undef; 2026 } 2027 if ($b1) { 2028 warn qq($0: *** [$path] Error $b1\n); # trying to be like make. 2029 return undef; 2030 } 2031 last; 2032 } 2033 return 1; 2034 } 2035 2036 package action::command::win32; 2037 2038 sub do_command { 2039 my($class, $com, $path) = @_; 2040 system($com); 2041 if ($?) { 2042 my ($b0, $b1) = ($? & 0xFF, $? >> 8); 2043 my $err = $b1 || $?; 2044 my $warn = qq($0: *** [$path] Error $err); 2045 $warn .= " (executable not found in path?)" if $b1 == 0xFF; 2046 warn "$warn\n"; 2047 return undef; 2048 } 2049 return 1; 2050 } 2051 2052 package action::perl; 2053 2054 # THIS IS AN EXPERIMENTAL PACKAGE. It's entirely possible that the 2055 # interface may change as this gets completed, so use at your own risk. 2056 # 2057 # There are (at least) two issues that need to be solved before blessing 2058 # this as a real, fully-supported feature: 2059 # 2060 # -- We need to calculate a signature value for a Perl code ref, in 2061 # order to rebuild the target if there's a change to the Perl code 2062 # used to generate it. 2063 # 2064 # This is not straightforward. A B::Deparse package exists that 2065 # decompiles a coderef into text. It's reportedly not completely 2066 # reliable for closures; it misses which variables are global, and 2067 # the values of private lexicals. Nevertheless, it'd probably 2068 # be perfect for our purposes, except that it wasn't added until 2069 # some time between Perl 5.00502 and 5.00554, and doesn't seem to 2070 # really work until Perl 5.6.0, so by relying on it, we'd lose 2071 # support for Perl versions back to 5.003*. 2072 # 2073 # -- Ideally, a code ref should be able to use something like 2074 # $env->_subst to fetch values from the construction environment 2075 # to modify its behavior without having to cut-and-paste code. 2076 # (Actually, since we pass the environment to the executed code 2077 # ref, there's no reason you can't do this with the code as it 2078 # stands today.) But this REALLY complicates the signature 2079 # calculation, because now the actual signature would depend not 2080 # just on the code contents, but on the construction variables (or 2081 # maybe just the environment). 2082 # 2083 # A potentially valid workaround would be to use the contents of the 2084 # Conscript file in which the code reference is defined as the code 2085 # ref's signature. This has the drawback of causing a recompilation of 2086 # the target file even in response to unrelated changes in the Conscript 2087 # file, but it would ensure correct builds without having to solve the 2088 # messy issues of generating a signature directly from a code ref. 2089 # 2090 # Nevertheless, this seemed a useful enough skeleton of a feature that 2091 # it made sense to release it in hopes that some practical experience 2092 # will encourage someone to figure out how to solve the signature 2093 # issues. Or maybe we'll discover these aren't big issues in practice 2094 # and end up blessing it as is. 2095 2096 use vars qw( %code ); 2097 2098 sub new { 2099 my($class, $cref) = @_; 2100 $code{$cref} || do { 2101 my $sig = ''; 2102 # Generating a code signature using B::Deparse doesn't really 2103 # work for us until Perl 5.6.0. Here's the code in case 2104 # someone wants to use it. 2105 #use B::Deparse; 2106 #my $deparse = B::Deparse->new(); 2107 #my $body = $deparse->coderef2text($cref); 2108 #$sig = $body; # should be an MD5 sig 2109 my($self) = { cref => $cref, crefsig => $sig }; 2110 $code{$cref} = bless $self, $class; 2111 } 2112 } 2113 2114 sub scriptsig { 2115 $_[0]->{crefsig} 2116 } 2117 2118 sub execute { 2119 my($self, $env, $tgt) = @_; 2120 if ($param::build) { 2121 futil::mkdir($tgt->{dir}); 2122 unlink($tgt->path) if ! $tgt->precious; 2123 my($cref) = $self->{cref}; 2124 &$cref($env, $tgt->path, map($_->rpath, @{$tgt->{sources}})); 2125 } 2126 } 2127 2128 sub commands { 2129 return (); 2130 } 2131 2132 2133 # Generic scanning module. 2134 package scan; 2135 2136 # Returns the signature of files included by the specified files on 2137 # behalf of the associated target. Any errors in handling the included 2138 # files are propagated to the target on whose behalf this processing 2139 # is being done. Signatures are cached for each unique file/scanner 2140 # pair. 2141 sub includes { 2142 my($self, $tgt, @files) = @_; 2143 my(%files, $file); 2144 my($inc) = $self->{includes} || ($self->{includes} = {}); 2145 while ($file = pop @files) { 2146 next if exists $files{$file}; 2147 if ($inc->{$file}) { 2148 push(@files, @{$inc->{$file}}); 2149 $files{$file} = 'sig'->signature($file->rfile); 2150 } else { 2151 if ((build $file) eq 'errors') { 2152 $tgt->{status} = 'errors'; # tgt inherits build status 2153 return (); 2154 } 2155 $files{$file} = 'sig'->signature($file->rfile); 2156 my(@includes) = $self->scan($file); 2157 $inc->{$file} = \@includes; 2158 push(@files, @includes); 2159 } 2160 } 2161 'sig'->collect(sort values %files) 2162 } 2163 2164 2165 # A simple scanner. This is used by the QuickScanfunction, to setup 2166 # one-time target and environment-independent scanning for a source 2167 # file. Only used for commands run by the Command method. 2168 package scan::quickscan; 2169 2170 use vars qw( @ISA %scanner ); 2171 2172 BEGIN { @ISA = qw(scan) } 2173 2174 sub find { 2175 my($class, $code, $env, $pdirs) = @_; 2176 if (! defined $pdirs) { 2177 $pdirs = [ ] ; 2178 } elsif (ref($pdirs) ne 'ARRAY') { 2179 $pdirs = [ split(/$main::PATH_SEPARATOR/o, $pdirs) ]; 2180 } 2181 my(@path) = map { $dir::cwd->lookupdir($_) } @$pdirs; 2182 my($spath) = "@path"; 2183 $scanner{$code,$env,$spath} || do { 2184 my($self) = { code => $code, env => $env, path => \@path }; 2185 $scanner{$code,$env,$spath} = bless $self; 2186 } 2187 } 2188 2189 # Scan the specified file for included file names. 2190 sub scan { 2191 my($self, $file) = @_; 2192 my($code) = $self->{code}; 2193 my(@includes); 2194 # File should have been built by now. If not, we'll ignore it. 2195 return () unless open(SCAN, $file->rpath); 2196 while(<SCAN>) { 2197 push(@includes, grep($_ ne '', &$code)); 2198 } 2199 close(SCAN); 2200 my($wd) = $file->{dir}; 2201 my(@files); 2202 my $name; 2203 for $name (@includes) { 2204 my $dir; 2205 for $dir ($file->{dir}, @{$self->{path}}) { 2206 my($include) = $dir->lookup_accessible($name); 2207 if ($include) { 2208 push(@files, $include) unless $include->ignore; 2209 last; 2210 } 2211 } 2212 } 2213 @files 2214 } 2215 2216 2217 # CPP (C preprocessor) scanning module 2218 package scan::cpp; 2219 2220 use vars qw( @ISA %scanner ); 2221 2222 BEGIN { @ISA = qw(scan) } 2223 2224 # For this constructor, provide the include path argument (colon 2225 # separated). Each path is taken relative to the provided directory. 2226 2227 # Note: a particular scanning object is assumed to always return the 2228 # same result for the same input. This is why the search path is a 2229 # parameter to the constructor for a CPP scanning object. We go to 2230 # some pains to make sure that we return the same scanner object 2231 # for the same path: otherwise we will unecessarily scan files. 2232 sub find { 2233 my($class, $dir, $pdirs) = @_; 2234 if (! defined $pdirs) { 2235 $pdirs = [ ]; 2236 } elsif (ref($pdirs) ne 'ARRAY') { 2237 $pdirs = [ split(/$main::PATH_SEPARATOR/o, $pdirs) ]; 2238 } 2239 my @path = map($dir->lookupdir($_), @$pdirs); 2240 my($spath) = "@path"; 2241 $scanner{$spath} || do { 2242 my($self) = {'path' => \@path}; 2243 $scanner{$spath} = bless $self; 2244 } 2245 } 2246 2247 # Scan the specified file for include lines. 2248 sub scan { 2249 my($self, $file) = @_; 2250 my($angles, $quotes); 2251 2252 if (exists $file->{angles}) { 2253 $angles = $file->{angles}; 2254 $quotes = $file->{quotes}; 2255 } else { 2256 my(@anglenames, @quotenames); 2257 return () unless open(SCAN, $file->rpath); 2258 while (<SCAN>) { 2259 next unless /^\s*#/; 2260 if (/^\s*#\s*include\s*([<"])(.*?)[>"]/) { 2261 if ($1 eq "<") { 2262 push(@anglenames, $2); 2263 } else { 2264 push(@quotenames, $2); 2265 } 2266 } 2267 } 2268 close(SCAN); 2269 $angles = $file->{angles} = \@anglenames; 2270 $quotes = $file->{quotes} = \@quotenames; 2271 } 2272 2273 2274 my(@shortpath) = @{$self->{path}}; # path for <> style includes 2275 my(@longpath) = ($file->{dir}, @shortpath); # path for "" style includes 2276 2277 my(@includes); 2278 2279 my $name; 2280 for $name (@$angles) { 2281 my $dir; 2282 for $dir (@shortpath) { 2283 my($include) = $dir->lookup_accessible($name); 2284 if ($include) { 2285 push(@includes, $include) unless $include->ignore; 2286 last; 2287 } 2288 } 2289 } 2290 2291 for $name (@$quotes) { 2292 my $dir; 2293 for $dir(@longpath) { 2294 my($include) = $dir->lookup_accessible($name); 2295 if ($include) { 2296 push(@includes, $include) unless $include->ignore; 2297 last; 2298 } 2299 } 2300 } 2301 2302 return @includes 2303 } 2304 2305 # Return the include flags that would be used for a C Compile. 2306 sub iflags { 2307 my($self, $env) = @_; 2308 my($iflags) = ''; 2309 my($dir, $dpath); 2310 for $dir (@{$self->{path}}) { 2311 $dpath = $dir->path; 2312 # Add the (presumably local) directory to the -I flags 2313 # if we're not using repositories, the directory exists, 2314 # or it's Linked to a source directory (that is, it *will* 2315 # exist by the time the compilation occurs). 2316 $iflags .= " ".$env->{INCDIRPREFIX}.$dpath.$env->{INCDIRSUFFIX} 2317 if ! @param::rpath || -d $dpath || $dir->is_linked; 2318 next if File::Spec->file_name_is_absolute($dpath); 2319 if (@param::rpath) { 2320 my $d; 2321 if ($dpath eq $dir::CURDIR) { 2322 foreach $d (map($_->path, @param::rpath)) { 2323 $iflags .= " ".$env->{INCDIRPREFIX}.$d.$env->{INCDIRSUFFIX}; 2324 } 2325 } else { 2326 my($rpath); 2327 foreach $d (map($_->path, @param::rpath)) { 2328 $rpath = File::Spec->catfile($d, $dpath); 2329 $iflags .= " ".$env->{INCDIRPREFIX}.$rpath.$env->{INCDIRSUFFIX} 2330 if -d $rpath; 2331 } 2332 } 2333 } 2334 } 2335 $iflags 2336 } 2337 2338 package File::Spec; 2339 2340 use vars qw( $_SEP $_MATCH_SEP $_MATCH_VOL ); 2341 2342 # Cons is migrating to using File::Spec for portable path name 2343 # manipulation. This is the right long-term direction, but there are 2344 # some problems with making the transition: 2345 # 2346 # For multi-volume support, we need to use newer interfaces 2347 # (splitpath, catpath, splitdir) that are only available in 2348 # File::Spec 0.8. 2349 # 2350 # File::Spec 0.8 doesn't work with Perl 5.00[34] due to 2351 # regular expression incompatibilities (use of \z). 2352 # 2353 # Forcing people to use a new version of a module is painful 2354 # because (in the workplace) their administrators aren't 2355 # always going to agree to install it everywhere. 2356 # 2357 # As a middle ground, we provide our own versions of all the File::Spec 2358 # methods we use, supporting both UNIX and Win32. Some of these methods 2359 # are home brew, some are cut-and-pasted from the real File::Spec methods. 2360 # This way, we're not reinventing the whole wheel, at least. 2361 # 2362 # We can (and should) get rid of this class whenever 5.00[34] and 2363 # versions of File::Spec prior to 0.9 (?) have faded sufficiently. 2364 # We also may need to revisit whenever someone first wants to use 2365 # Cons on some platform other than UNIX or Win32. 2366 2367 BEGIN { 2368 if ($main::_WIN32) { 2369 $_SEP = '\\'; 2370 $_MATCH_SEP = "[\Q/$_SEP\E]"; 2371 $_MATCH_VOL = "([a-z]:)?$_MATCH_SEP"; 2372 } else { 2373 $_SEP = '/'; 2374 $_MATCH_SEP = "\Q$_SEP\E"; 2375 $_MATCH_VOL = $_MATCH_SEP; 2376 } 2377 } 2378 2379 sub canonpath { 2380 my ($self, $path) = @_; 2381 if ($main::_WIN32) { 2382 $path =~ s/^([a-z]:)/\u$1/s; 2383 $path =~ s|/|\\|g; 2384 $path =~ s|([^\\])\\+|$1\\|g; # xx////xx -> xx/xx 2385 $path =~ s|(\\\.)+\\|\\|g; # xx/././xx -> xx/xx 2386 $path =~ s|^(\.\\)+||s unless $path eq ".\\"; # ./xx -> xx 2387 $path =~ s|\\$|| 2388 unless $path =~ m#^([A-Z]:)?\\$#s; # xx/ -> xx 2389 } else { 2390 $path =~ s|/+|/|g unless($^O eq 'cygwin'); # xx////xx -> xx/xx 2391 $path =~ s|(/\.)+/|/|g; # xx/././xx -> xx/xx 2392 $path =~ s|^(\./)+||s unless $path eq "./"; # ./xx -> xx 2393 $path =~ s|^/(\.\./)+|/|s; # /../../xx -> xx 2394 $path =~ s|/$|| unless $path eq "/"; # xx/ -> xx 2395 } 2396 return $path; 2397 } 2398 2399 sub catdir { 2400 my $self = shift; 2401 my @args = @_; 2402 foreach (@args) { 2403 # append a slash to each argument unless it has one there 2404 $_ .= $_SEP if $_ eq '' || substr($_,-1) ne $_SEP; 2405 } 2406 return $self->canonpath(join('', @args)); 2407 } 2408 2409 sub catfile { 2410 my $self = shift; 2411 my $file = pop @_; 2412 return $file unless @_; 2413 my $dir = $self->catdir(@_); 2414 $dir .= $_SEP unless substr($dir,-1) eq $_SEP; 2415 $file = '' if ! defined($file); 2416 return $dir.$file; 2417 } 2418 2419 sub catpath { 2420 my $path = $_[1] . $_[0]->catfile(@_[2..$#_]); 2421 $path =~ s/(.)$_MATCH_SEP*$/$1/; 2422 $path; 2423 } 2424 2425 sub curdir { 2426 '.' 2427 } 2428 2429 sub file_name_is_absolute { 2430 my ($self, $file) = @_; 2431 return scalar($file =~ m{^$_MATCH_VOL}is); 2432 } 2433 2434 sub splitdir { 2435 my @dirs = split(/$_MATCH_SEP/, $_[1], -1); 2436 push(@dirs, '') if $dirs[$#dirs]; 2437 @dirs; 2438 } 2439 2440 sub splitpath { 2441 my ($self, $path) = @_; 2442 my $vol = ''; 2443 my $sep = $_SEP; 2444 if ($main::_WIN32) { 2445 if ($path =~ s#^([A-Za-z]:|(?:\\\\|//)[^\\/]+[\\/][^\\/]+)([\\/])#$2#) { 2446 $vol = $1; 2447 $sep = $2; 2448 } 2449 } 2450 my(@path) = split(/$_MATCH_SEP/, $path, -1); 2451 my $file = pop @path; 2452 my $dirs = join($sep, @path, ''); 2453 return ($vol, $dirs, $file); 2454 } 2455 2456 sub updir { 2457 '..' 2458 } 2459 2460 sub case_tolerant { 2461 return $main::_WIN32; 2462 } 2463 2464 # Directory and file handling. Files/dirs are represented by objects. 2465 # Other packages are welcome to add component-specific attributes. 2466 package dir; 2467 2468 use vars qw( $SEPARATOR $MATCH_SEPARATOR $CURDIR $UPDIR 2469 $cwd_vol %root $top $cwd ); 2470 2471 BEGIN { 2472 # A portable way of determing our directory separator. 2473 $SEPARATOR = File::Spec->catdir('', ''); 2474 # A fast-path regular expression to match a directory separator 2475 # anywhere in a path name. 2476 if ($SEPARATOR eq '/') { 2477 $MATCH_SEPARATOR = "\Q$SEPARATOR\E"; 2478 } else { 2479 $MATCH_SEPARATOR = "[\Q/$SEPARATOR\E]"; 2480 } 2481 # Cache these values so we don't have to make a method call 2482 # every time we need them. 2483 $CURDIR = File::Spec->curdir; # '.' on UNIX 2484 $UPDIR = File::Spec->updir; # '..' on UNIX 2485 # 2486 $cwd_vol = ''; 2487 } 2488 2489 # Annotate a node (file or directory) with info about the 2490 # method that created it. 2491 sub creator { 2492 my($self, @frame) = @_; 2493 $self->{'creator'} = \@frame if @frame; 2494 $self->{'creator'}; 2495 } 2496 2497 # Handle a file|dir type exception. We only die if we find we were 2498 # invoked by something in a Conscript/Construct file, because 2499 # dependencies created directly by Cons' analysis shouldn't cause 2500 # an error. 2501 sub _type_exception { 2502 my($e) = @_; 2503 my($line, $sub); 2504 (undef, undef, $line, $sub) = script::caller_info; 2505 if (defined $line) { 2506 my $err = "\"${\$e->path}\" already in use as a " . ref($e) . " before $sub on line $line"; 2507 if ($e->{'creator'}) { 2508 my $script; 2509 (undef, $script, $line, $sub) = @{$e->{'creator'}}; 2510 $err = "\t" . $err . ",\n\t\tdefined by $sub in $script, line $line"; 2511 } 2512 $err .= "\n"; 2513 die $err; 2514 } 2515 } 2516 2517 # This wraps up all the common File::Spec logic that we use for parsing 2518 # directory separators in a path and turning it into individual 2519 # subdirectories that we must create, as well as creation of root 2520 # nodes for any new file system volumes we find. File::Spec doesn't have 2521 # intuitively obvious interfaces, so this is heavily commented. 2522 # 2523 # Note: This is NOT an object or class method; 2524 # it's just a utility subroutine. 2525 sub _parse_path { 2526 my($dir, $path) = @_; 2527 2528 # Convert all slashes to the native directory separator. 2529 # This allows Construct files to always be written with good 2530 # old POSIX path names, regardless of what we're running on. 2531 $path = File::Spec->canonpath($path); 2532 2533 # File::Spec doesn't understand the Cons convention of 2534 # an initial '#' for top-relative files. Strip it. 2535 my($toprel) = $path =~ s/^#//; 2536 2537 # Let File::Spec do the heavy lifting of parsing the path name. 2538 my($vol, $directories, $entry) = File::Spec->splitpath($path); 2539 my @dirs = File::Spec->splitdir($directories); 2540 2541 # If there was a file entry on the end of the path, then the 2542 # last @dirs element is '' and we don't need it. If there 2543 # wasn't a file entry on the end (File::Spec->splitpath() knew 2544 # the last component was a directory), then the last @dirs 2545 # element becomes the entry we want to look up. 2546 my($e) = pop @dirs; 2547 $entry = $e if $entry eq ''; 2548 2549 if (File::Spec->file_name_is_absolute($path)) { 2550 # An absolute path name. If no volume was supplied, 2551 # use the volume of our current directory. 2552 $vol = $cwd_vol if $vol eq ''; 2553 $vol = uc($vol) if File::Spec->case_tolerant; 2554 if (! defined $root{$vol}) { 2555 # This is our first time looking up a path name 2556 # on this volume, so create a root node for it. 2557 # (On UNIX systems, $vol is always '', so '/' 2558 # always maps to the $root{''} node.) 2559 $root{$vol} = {path => $vol.$SEPARATOR, 2560 prefix => $vol.$SEPARATOR, 2561 srcpath => $vol.$SEPARATOR, 2562 'exists' => 1 }; 2563 $root{$vol}->{'srcdir'} = $root{$vol}; 2564 bless $root{$vol}; 2565 } 2566 # We're at the top, so strip the blank entry from the front of 2567 # the @dirs array since the initial '/' it represents will now 2568 # be supplied by the root node we return. 2569 shift @dirs; 2570 $dir = $root{$vol}; 2571 } elsif ($toprel) { 2572 $dir = $dir::top; 2573 } 2574 ($dir, \@dirs, $entry); 2575 } 2576 2577 # Common subroutine for creating directory nodes. 2578 sub _create_dirs { 2579 my ($dir, @dirs) = @_; 2580 my $e; 2581 foreach $e (@dirs) { 2582 my $d = $dir->{member}->{$e}; 2583 if (! defined $d) { 2584 bless $d = { 'entry' => $e, 'dir' => $dir, }, 'dir'; 2585 $d->creator(script::caller_info); 2586 $d->{member}->{$dir::CURDIR} = $d; 2587 $d->{member}->{$dir::UPDIR} = $dir; 2588 $dir->{member}->{$e} = $d; 2589 } elsif (ref $d eq 'entry') { 2590 bless $d, 'dir'; 2591 $d->{member}->{$dir::CURDIR} = $d; 2592 $d->{member}->{$dir::UPDIR} = $dir; 2593 } elsif (ref $d eq 'file') { 2594 # This clause is to supply backwards compatibility, 2595 # with a warning, for anyone that's used FilePath 2596 # to refer to a directory. After people have using 2597 # 1.8 have had time to adjust (sometime in version 2598 # 1.9 or later), we should remove this entire clause. 2599 my($script, $line, $sub); 2600 (undef, $script, $line, $sub) = @{$d->{'creator'}}; 2601 if ($sub eq 'script::FilePath') { 2602 print STDERR "$0: Warning: $sub used to refer to a directory\n" 2603 . "\tat line $line of $script. Use DirPath instead.\n"; 2604 bless $d, 'dir'; 2605 } else { 2606 _type_exception($d); 2607 } 2608 } elsif (ref $d ne 'dir') { 2609 _type_exception($d); 2610 } 2611 $dir = $d; 2612 } 2613 $dir; 2614 } 2615 2616 # Look up an entry in a directory. This method is for when we don't 2617 # care whether a file or directory is returned, so if the entry already 2618 # exists, it will simply be returned. If not, we create it as a 2619 # generic "entry" which can be later turned into a file or directory 2620 # by a more-specific lookup. 2621 # 2622 # The file entry may be specified as relative, absolute (starts with /), 2623 # or top-relative (starts with #). 2624 sub lookup { 2625 my($dir, $entry) = @_; 2626 2627 if ($entry !~ m#$MATCH_SEPARATOR#o) { 2628 # Fast path: simple entry name in a known directory. 2629 if ($entry =~ s/^#//) { 2630 # Top-relative names begin with #. 2631 $dir = $dir::top; 2632 } elsif ($entry =~ s/^!//) { 2633 $dir = $dir::cwd->srcdir; 2634 } 2635 } else { 2636 my $dirsref; 2637 ($dir, $dirsref, $entry) = _parse_path($dir, $entry); 2638 $dir = _create_dirs($dir, @$dirsref) if @$dirsref; 2639 return if ! defined $dir; 2640 return $dir if $entry eq ''; 2641 } 2642 2643 my $e = $dir->{member}->{$entry}; 2644 if (! defined $e) { 2645 bless $e = { 'entry' => $entry, 'dir' => $dir, }, 'entry'; 2646 $e->creator(script::caller_info); 2647 $dir->{member}->{$entry} = $e; 2648 } 2649 2650 $e; 2651 } 2652 2653 # Look up a file entry in a directory. 2654 # 2655 # The file entry may be specified as relative, absolute (starts with /), 2656 # or top-relative (starts with #). 2657 sub lookupfile { 2658 my($dir, $entry) = @_; 2659 2660 if ($entry !~ m#$MATCH_SEPARATOR#o) { 2661 # Fast path: simple entry name in a known directory. 2662 if ($entry =~ s/^#//) { 2663 # Top-relative names begin with #. 2664 $dir = $dir::top; 2665 } elsif ($entry =~ s/^!//) { 2666 $dir = $dir::cwd->srcdir; 2667 } 2668 } else { 2669 my $dirsref; 2670 ($dir, $dirsref, $entry) = _parse_path($dir, $entry); 2671 $dir = _create_dirs($dir, @$dirsref) if @$dirsref; 2672 return undef if $entry eq ''; 2673 } 2674 2675 my $f = $dir->{member}->{$entry}; 2676 if (! defined $f) { 2677 bless $f = { 'entry' => $entry, 'dir' => $dir, }, 'file'; 2678 $f->creator(script::caller_info); 2679 $dir->{member}->{$entry} = $f; 2680 } elsif (ref $f eq 'entry') { 2681 bless $f, 'file'; 2682 } elsif (ref $f ne 'file') { 2683 _type_exception($f); 2684 } 2685 2686 $f; 2687 } 2688 2689 # Look up a (sub-)directory entry in a directory. 2690 # 2691 # The (sub-)directory entry may be specified as relative, absolute 2692 # (starts with /), or top-relative (starts with #). 2693 sub lookupdir { 2694 my($dir, $entry) = @_; 2695 2696 my $dirsref; 2697 if ($entry !~ m#$MATCH_SEPARATOR#o) { 2698 # Fast path: simple entry name in a known directory. 2699 if ($entry =~ s/^#//) { 2700 # Top-relative names begin with #. 2701 $dir = $dir::top; 2702 } elsif ($entry =~ s/^!//) { 2703 $dir = $dir::cwd->srcdir; 2704 } 2705 } else { 2706 ($dir, $dirsref, $entry) = _parse_path($dir, $entry); 2707 } 2708 push(@$dirsref, $entry) if $entry ne ''; 2709 _create_dirs($dir, @$dirsref); 2710 } 2711 2712 # Look up a file entry and return it if it's accessible. 2713 sub lookup_accessible { 2714 my $file = $_[0]->lookupfile($_[1]); 2715 return ($file && $file->accessible) ? $file : undef; 2716 } 2717 2718 # Return the parent directory without doing a lookupdir, 2719 # which would create a parent if it doesn't already exist. 2720 # A return value of undef (! $dir->up) indicates a root directory. 2721 sub up { 2722 $_[0]->{member}->{$dir::UPDIR}; 2723 } 2724 2725 # Return whether this is an entry somewhere underneath the 2726 # specified directory. 2727 sub is_under { 2728 my $dir = $_[0]; 2729 while ($dir) { 2730 return 1 if $_[1] == $dir; 2731 $dir = $dir->up; 2732 } 2733 return undef; 2734 } 2735 2736 # Return the relative path from the calling directory ($_[1]) 2737 # to the object. If the object is not under the directory, then 2738 # we return it as a top-relative or absolute path name. 2739 sub relpath { 2740 my ($dir, $obj) = @_; 2741 my @dirs; 2742 my $o = $obj; 2743 while ($o) { 2744 if ($dir == $o) { 2745 if (@dirs < 2) { 2746 return $dirs[0] || ''; 2747 } else { 2748 return File::Spec->catdir(@dirs); 2749 } 2750 } 2751 unshift(@dirs, $o->{entry}); 2752 $o = $o->up; 2753 } 2754 # The object was not underneath the specified directory. 2755 # Use the node's cached path, which is either top-relative 2756 # (in which case we append '#' to the beginning) or 2757 # absolute. 2758 my $p = $obj->path; 2759 $p = '#' . $p if ! File::Spec->file_name_is_absolute($p); 2760 return $p; 2761 } 2762 2763 # Return the path of the directory (file paths implemented 2764 # separately, below). 2765 sub path { 2766 $_[0]->{path} || 2767 ($_[0]->{path} = $_[0]->{dir}->prefix . $_[0]->{entry}); 2768 } 2769 2770 # Return the pathname as a prefix to be concatenated with an entry. 2771 sub prefix { 2772 return $_[0]->{prefix} if exists $_[0]->{prefix}; 2773 $_[0]->{prefix} = $_[0]->path . $SEPARATOR; 2774 } 2775 2776 # Return the related source path prefix. 2777 sub srcprefix { 2778 return $_[0]->{srcprefix} if exists $_[0]->{srcprefix}; 2779 my($srcdir) = $_[0]->srcdir; 2780 $srcdir->{srcprefix} = $srcdir eq $_[0] ? $srcdir->prefix 2781 : $srcdir->srcprefix; 2782 } 2783 2784 # Return the related source directory. 2785 sub srcdir { 2786 $_[0]->{'srcdir'} || 2787 ($_[0]->{'srcdir'} = $_[0]->{dir}->srcdir->lookupdir($_[0]->{entry})) 2788 } 2789 2790 # Return if the directory is linked to a separate source directory. 2791 sub is_linked { 2792 return $_[0]->{is_linked} if defined $_[0]->{is_linked}; 2793 $_[0]->{is_linked} = $_[0]->path ne $_[0]->srcdir->path; 2794 } 2795 2796 sub link { 2797 my(@paths) = @_; 2798 my($srcdir) = $dir::cwd->lookupdir(pop @paths)->srcdir; 2799 map($dir::cwd->lookupdir($_)->{'srcdir'} = $srcdir, @paths); 2800 2801 # make a reverse lookup for the link. 2802 $srcdir->{links} = [] if ! $srcdir->{links}; 2803 push @{$srcdir->{links}}, @paths; 2804 } 2805 2806 use vars qw( @tail ); # TODO: Why global ???? 2807 2808 sub linked_targets { 2809 my $tgt = shift; 2810 my @targets = (); 2811 my $dir; 2812 if (ref $tgt eq 'dir') { 2813 $dir = $tgt; 2814 } else { 2815 push @tail, $tgt; 2816 $dir = $tgt->{dir}; 2817 } 2818 while ($dir) { 2819 if (defined $dir->{links} && @{$dir->{links}}) { 2820 push @targets, 2821 map(File::Spec->catdir($_, @tail), @{$dir->{links}}); 2822 #print STDERR "Found Link: ${\$dir->path} -> @{\$dir->{links}}\n"; 2823 } 2824 unshift @tail, $dir->{entry}; 2825 $dir = $dir->up; 2826 } 2827 2828 return map($dir::top->lookupdir($_), @targets); 2829 } 2830 2831 sub accessible { 2832 my $path = $_[0]->path; 2833 my $err = "$0: you have attempted to use path \"$path\" both as a file " . 2834 "and as a directory!\n"; 2835 die $err; 2836 } 2837 2838 sub init { 2839 my $path = Cwd::cwd(); 2840 2841 # We know we can get away with passing undef to lookupdir 2842 # as the directory because $dir is an absolute path. 2843 $top = lookupdir(undef, $path); 2844 $top->{'path'} = $top->{srcpath} = $dir::CURDIR; 2845 $top->{'prefix'} = ''; 2846 $top->{'srcdir'} = $top; 2847 2848 $cwd = $top; 2849 2850 ($cwd_vol, undef, undef) = File::Spec->splitpath($path); 2851 $cwd_vol = '' if ! defined $cwd_vol; 2852 $cwd_vol = uc($cwd_vol) if File::Spec->case_tolerant; 2853 } 2854 2855 package file; 2856 2857 use vars qw( @ISA $level ); 2858 2859 BEGIN { @ISA = qw(dir); $level = 0 } 2860 2861 # Return the pathname of the file. 2862 # Define this separately from dir::path because we don't want to 2863 # cache all file pathnames (just directory pathnames). 2864 sub path { 2865 $_[0]->{dir}->prefix . $_[0]->{entry} 2866 } 2867 2868 # Return the related source file path. 2869 sub srcpath { 2870 $_[0]->{dir}->srcprefix . $_[0]->{entry} 2871 } 2872 2873 # Return if the file is (should be) linked to a separate source file. 2874 sub is_linked { 2875 $_[0]->{dir}->is_linked 2876 } 2877 2878 # Repository file search. If the local file exists, that wins. 2879 # Otherwise, return the first existing same-named file under a 2880 # Repository directory. If there isn't anything with the same name 2881 # under a Repository directory, return the local file name anyway 2882 # so that some higher layer can try to construct it. 2883 sub rfile { 2884 return $_[0]->{rfile} if exists $_[0]->{rfile}; 2885 my($self) = @_; 2886 my($rfile) = $self; 2887 if (@param::rpath) { 2888 my($path) = $self->path; 2889 if (! File::Spec->file_name_is_absolute($path) && ! -f $path) { 2890 my($dir); 2891 foreach $dir (@param::rpath) { 2892 my($t) = $dir->prefix . $path; 2893 if (-f $t) { 2894 $rfile = $_[0]->lookupfile($t); 2895 $rfile->{'lfile'} = $self; 2896 last; 2897 } 2898 } 2899 } 2900 } 2901 $self->{rfile} = $rfile; 2902 } 2903 2904 # Returns the local file for a repository file; 2905 # returns self if it's already a local file. 2906 sub lfile { 2907 $_[0]->{'lfile'} || $_[0] 2908 } 2909 2910 # returns the "precious" status of this file. 2911 sub precious { 2912 return $_[0]->{precious}; 2913 } 2914 2915 # "Erase" reference to a Repository file, 2916 # making this a completely local file object 2917 # by pointing it back to itself. 2918 sub no_rfile { 2919 $_[0]->{'rfile'} = $_[0]; 2920 } 2921 2922 # Return a path to the first existing file under a Repository directory, 2923 # implicitly returning the current file's path if there isn't a 2924 # same-named file under a Repository directory. 2925 sub rpath { 2926 $_[0]->{rpath} || 2927 ($_[0]->{rpath} = $_[0]->rfile->path) 2928 } 2929 2930 # Return a path to the first linked srcpath file under a Repositoy 2931 # directory, implicitly returning the current file's srcpath if there 2932 # isn't a same-named file under a Repository directory. 2933 sub rsrcpath { 2934 return $_[0]->{rsrcpath} if exists $_[0]->{rsrcpath}; 2935 my($self) = @_; 2936 my($path) = $self->{rsrcpath} = $self->srcpath; 2937 if (@param::rpath && ! File::Spec->file_name_is_absolute($path) && ! -f $path) { 2938 my($dir); 2939 foreach $dir (@param::rpath) { 2940 my($t) = $dir->prefix . $path; 2941 if (-f $t) { 2942 $self->{rsrcpath} = $t; 2943 last; 2944 } 2945 } 2946 } 2947 $self->{rsrcpath}; 2948 } 2949 2950 # Return if a same-named file source file exists. 2951 # This handles the interaction of Link and Repository logic. 2952 # As a side effect, it will link a source file from its Linked 2953 # directory (preferably local, but maybe in a repository) 2954 # into a build directory from its proper Linked directory. 2955 sub source_exists { 2956 return $_[0]->{source_exists} if defined $_[0]->{source_exists}; 2957 my($self) = @_; 2958 my($path) = $self->path; 2959 my($mtime, $ctime) = (stat($path))[9,10]; 2960 if ($self->is_linked) { 2961 # Linked directory, local logic. 2962 my($srcpath) = $self->srcpath; 2963 my($src_mtime, $src_ctime) = (stat($srcpath))[9,10]; 2964 if ($src_mtime) { 2965 if (! $mtime || $src_mtime != $mtime || $src_ctime != $ctime) { 2966 futil::install($srcpath, $self); 2967 } 2968 return $self->{source_exists} = 1; 2969 } 2970 # Linked directory, repository logic. 2971 if (@param::rpath) { 2972 if ($self != $self->rfile) { 2973 return $self->{source_exists} = 1; 2974 } 2975 my($rsrcpath) = $self->rsrcpath; 2976 if ($path ne $rsrcpath) { 2977 my($rsrc_mtime, $rsrc_ctime) = (stat($rsrcpath))[9,10]; 2978 if ($rsrc_mtime) { 2979 if (! $mtime || $rsrc_mtime != $mtime 2980 || $rsrc_ctime != $ctime) { 2981 futil::install($rsrcpath, $self); 2982 } 2983 return $self->{source_exists} = 1; 2984 } 2985 } 2986 } 2987 # There was no source file in any Linked directory 2988 # under any Repository. If there's one in the local 2989 # build directory, it no longer belongs there. 2990 if ($mtime) { 2991 unlink($path) || die("$0: couldn't unlink $path ($!)\n"); 2992 } 2993 return $self->{source_exists} = ''; 2994 } else { 2995 if ($mtime) { 2996 return $self->{source_exists} = 1; 2997 } 2998 if (@param::rpath && $self != $self->rfile) { 2999 return $self->{source_exists} = 1; 3000 } 3001 return $self->{source_exists} = ''; 3002 } 3003 } 3004 3005 # Return if a same-named derived file exists under a Repository directory. 3006 sub derived_exists { 3007 $_[0]->{derived_exists} || 3008 ($_[0]->{derived_exists} = ($_[0] != $_[0]->rfile)); 3009 } 3010 3011 # Return if this file is somewhere under a Repository directory. 3012 sub is_on_rpath { 3013 defined $_[0]->{'lfile'}; 3014 } 3015 3016 sub local { 3017 my($self, $arg) = @_; 3018 if (defined $arg) { 3019 $self->{'local'} = $arg; 3020 } 3021 $self->{'local'}; 3022 } 3023 3024 # Return the entry name of the specified file with the specified 3025 # suffix appended. Leave it untouched if the suffix is already there. 3026 # Differs from the addsuffix function, below, in that this strips 3027 # the existing suffix (if any) before appending the desired one. 3028 sub base_suf { 3029 my($entry) = $_[0]->{entry}; 3030 if ($entry !~ m/$_[1]$/) { 3031 $entry =~ s/\.[^\.]*$//; 3032 $entry .= $_[1]; 3033 } 3034 $entry; 3035 } 3036 3037 # Return the suffix of the file; everything including and to the 3038 # right of the last dot. 3039 sub suffix { 3040 my @pieces = split(/\./, $_[0]->{entry}); 3041 my $suffix = pop(@pieces); 3042 return ".$suffix"; 3043 } 3044 3045 # Called as a simple function file::addsuffix(name, suffix) 3046 sub addsuffix { 3047 my($name, $suffix) = @_; 3048 3049 if ($suffix && substr($name, -length($suffix)) ne $suffix) { 3050 return $name .= $suffix; 3051 } 3052 $name; 3053 } 3054 3055 # Return true if the file is (or will be) accessible. 3056 # That is, if we can build it, or if it is already present. 3057 sub accessible { 3058 (exists $_[0]->{builder}) || ($_[0]->source_exists); 3059 } 3060 3061 # Return true if the file should be ignored for the purpose 3062 # of computing dependency information (should not be considered 3063 # as a dependency and, further, should not be scanned for 3064 # dependencies). 3065 sub ignore { 3066 return 0 if !$param::ignore; 3067 return $_[0]->{ignore} if exists $_[0]->{ignore}; 3068 $_[0]->{ignore} = $_[0]->path =~ /$param::ignore/o; 3069 } 3070 3071 # Build the file, if necessary. 3072 sub build { 3073 return $_[0]->{status} if $_[0]->{status}; 3074 my($status) = &file::_build; 3075 if ($_[0]->{after_build_func}) { 3076 my($pkgvars) = $_[0]->{conscript}->{pkgvars}; 3077 NameSpace::restore('script', $pkgvars) if $pkgvars; 3078 eval("package script; " . $_[0]->{after_build_func}); 3079 print "Error running AfterBuild for ${\$_[0]->path}: $@\n" if ($@); 3080 NameSpace::remove('script', keys %$pkgvars) if $pkgvars; 3081 } 3082 return $status; 3083 } 3084 3085 sub _build { 3086 my($self) = @_; 3087 print main::DEPFILE $self->path, "\n" if $param::depfile; 3088 print((' ' x $level), "Checking ", $self->path, "\n") if $param::depends; 3089 if (!exists $self->{builder}) { 3090 # We don't know how to build the file. This is OK, if 3091 # the file is present as a source file, under either the 3092 # local tree or a Repository. 3093 if ($self->source_exists) { 3094 return $self->{status} = 'handled'; 3095 } else { 3096 my($name) = $self->path; 3097 print("$0: don't know how to construct \"$name\"\n"); 3098 exit(1) unless $param::kflag; 3099 return $self->{status} = 'errors'; # xxx used to be 'unknown' 3100 } 3101 } 3102 3103 # An associated build object exists, so we know how to build 3104 # the file. We first compute the signature of the file, based 3105 # on its dependendencies, then only rebuild the file if the 3106 # signature has changed. 3107 my($builder) = $self->{builder}; 3108 $level += 2; 3109 3110 my(@deps) = (@{$self->{dep}}, @{$self->{sources}}); 3111 my($rdeps) = \@deps; 3112 3113 if ($param::random) { 3114 # If requested, build in a random order, instead of the 3115 # order that the dependencies were listed. 3116 my(%rdeps); 3117 map { $rdeps{$_,'*' x int(rand 10)} = $_ } @deps; 3118 $rdeps = [values(%rdeps)]; 3119 } 3120 3121 $self->{status} = ''; 3122 3123 my $dep; 3124 for $dep (@$rdeps) { 3125 if ((build $dep) eq 'errors') { 3126 # Propagate dependent errors to target. 3127 # but try to build all dependents regardless of errors. 3128 $self->{status} = 'errors'; 3129 } 3130 } 3131 3132 # If any dependents had errors, then we abort. 3133 if ($self->{status} eq 'errors') { 3134 $level -= 2; 3135 return 'errors'; 3136 } 3137 3138 # Compute the final signature of the file, based on 3139 # the static dependencies (in order), dynamic dependencies, 3140 # output path name, and (non-substituted) build script. 3141 my($sig) = 'sig'->collect(map('sig'->signature($_->rfile), @deps), 3142 $builder->includes($self), 3143 $builder->scriptsig); 3144 3145 # May have gotten errors during computation of dynamic 3146 # dependency signature, above. 3147 $level -= 2; 3148 return 'errors' if $self->{status} eq 'errors'; 3149 3150 if (@param::rpath && $self->derived_exists) { 3151 # There is no local file of this name, but there is one 3152 # under a Repository directory. 3153 3154 if ('sig'->current($self->rfile, $sig)) { 3155 # The Repository copy is current (its signature matches 3156 # our calculated signature). 3157 if ($self->local) { 3158 # ...but they want a local copy, so provide it. 3159 main::showcom("Local copy of ${\$self->path} from " . 3160 "${\$self->rpath}"); 3161 futil::install($self->rpath, $self); 3162 'sig'->bsig($self, $sig); 3163 } 3164 return $self->{status} = 'handled'; 3165 } 3166 3167 # The signatures don't match, implicitly because something 3168 # on which we depend exists locally. Get rid of the reference 3169 # to the Repository file; we'll build this (and anything that 3170 # depends on it) locally. 3171 $self->no_rfile; 3172 } 3173 3174 # Then check for currency. 3175 if (! 'sig'->current($self, $sig)) { 3176 # We have to build/derive the file. 3177 print((' ' x $level), "Rebuilding ", $self->path, ": out of date.\n") 3178 if $param::depends; 3179 # First check to see if the built file is cached. 3180 if ($builder->cachin($self, $sig)) { 3181 'sig'->bsig($self, $sig); 3182 return $self->{status} = 'built'; 3183 } elsif ($builder->action($self)) { 3184 $builder->cachout($self, $sig); 3185 'sig'->bsig($self, $sig); 3186 return $self->{status} = 'built'; 3187 } else { 3188 die("$0: errors constructing ${\$self->path}\n") 3189 unless $param::kflag; 3190 return $self->{status} = 'errors'; 3191 } 3192 } else { 3193 # Push this out to the cache if we've been asked to (-C option). 3194 # Don't normally do this because it slows us down. 3195 # In a fully built system, no accesses to the cache directory 3196 # are required to check any files. This is a win if cache is 3197 # heavily shared. Enabling this option puts the directory in the 3198 # loop. Useful only when you wish to recreate a cache from a build. 3199 if ($param::cachesync) { 3200 $builder->cachout($self, $sig); 3201 'sig'->bsig($self, $sig); 3202 } 3203 return $self->{status} = 'handled'; 3204 } 3205 } 3206 3207 # Bind an action to a file, with the specified sources. No return value. 3208 sub bind { 3209 my($self, $builder, @sources) = @_; 3210 if ($self->{builder} && !$self->{builder}->compatible($builder)) { 3211 # Even if not "compatible", we can still check to see if the 3212 # derivation is identical. It should be identical if the builder is 3213 # the same and the sources are the same. 3214 if ("$self->{builder} @{$self->{sources}}" ne "$builder @sources") { 3215 $main::errors++; 3216 my($_foo1, $script1, $line1, $sub1) = @{$self->creator}; 3217 my($_foo2, $script2, $line2, $sub2) = script::caller_info; 3218 my $err = "\t${\$self->path}\n" . 3219 "\tbuilt (at least) two different ways:\n" . 3220 "\t\t$script1, line $line1: $sub1\n" . 3221 "\t\t$script2, line $line2: $sub2\n"; 3222 die $err; 3223 } 3224 return; 3225 } 3226 if ($param::wflag) { 3227 my($script, $line, $sub); 3228 (undef, $script, $line, $sub) = script::caller_info; 3229 $self->{script} = '' if ! defined $self->{script}; 3230 $self->{script} .= "; " if $self->{script}; 3231 $self->{script} .= qq($sub in "$script", line $line); 3232 } 3233 $self->{builder} = $builder; 3234 push(@{$self->{sources}}, @sources); 3235 @{$self->{dep}} = () if ! defined $self->{dep}; 3236 $self->{conscript} = $priv::self->{script}; 3237 } 3238 3239 sub is_under { 3240 $_[0]->{dir}->is_under($_[1]); 3241 } 3242 3243 sub relpath { 3244 my $dirpath = $_[0]->relpath($_[1]->{dir}); 3245 if (! $dirpath) { 3246 return $_[1]->{entry}; 3247 } else { 3248 File::Spec->catfile($dirpath, $_[1]->{entry}); 3249 } 3250 } 3251 3252 # Return the signature array for this file. 3253 # This probably belongs in its own "sigarray" package, 3254 # which would make it easier to optimize performance. 3255 sub sigarray { 3256 if ($_[0]->{sigaref}) { 3257 return @{$_[0]->{sigaref}}; 3258 } 3259 my $self = shift; 3260 # glob2pat based on The Perl Cookbook, p. 180. 3261 sub glob2pat { 3262 my $globstr = shift; 3263 my %patmap = ( 3264 '*' => '.*', 3265 '?' => '.', 3266 '[' => '[', 3267 ']' => ']', 3268 '/' => "\Q$dir::SEPARATOR", # Cons-specific modification 3269 ); 3270 $globstr =~ s{(.)} { $patmap{$1} || "\Q$1" }ge; 3271 return '^' . $globstr . '$'; 3272 } 3273 my @sigarray; 3274 my $default; 3275 my $builder = $self->lfile->{builder}; 3276 if (! $builder) { 3277 @sigarray = @$param::sourcesig; 3278 $default = [qw(content)]; 3279 } else { 3280 if ($builder->{env} && $builder->{env}->{SIGNATURE}) { 3281 @sigarray = @{$builder->{env}->{SIGNATURE}}; 3282 } else { 3283 my $class = ref $builder; 3284 my $path = $self->path; 3285 warn qq($0: Warning: Builder package $class did not record\n) . 3286 qq(\tthe calling environment for '$path'.\n) . 3287 qq(\tUnable to use any %SIGNATURE construction variable\n) . 3288 qq(\tfor signature configuration.\n); 3289 } 3290 $default = [qw(build)]; 3291 } 3292 my $path = $self->path; 3293 while (@sigarray) { 3294 my($glob, $aref) = splice(@sigarray, 0, 2); 3295 my $re = glob2pat($glob); 3296 if ($path =~ /$re/) { 3297 $aref = [split(/\s+/, $aref)] if ! ref $aref; 3298 $self->{sigaref} = $aref; 3299 return @$aref; 3300 } 3301 } 3302 $self->{sigaref} = $default; 3303 return @{$self->{sigaref}} 3304 } 3305 3306 # Decide if this file's signature should be the content or build signature. 3307 sub sigtype { 3308 if ($_[0]->{sigtype}) { 3309 return $_[0]->{sigtype}; 3310 } 3311 my $self = shift; 3312 my @sigarray = $self->sigarray; 3313 my $sigtype; 3314 if (grep($_ eq "build", @sigarray)) { 3315 $sigtype = 'bsig'; 3316 } elsif (grep($_ =~ /content$/, @sigarray)) { 3317 $sigtype = 'csig'; 3318 } 3319 return $self->{sigtype} = $sigtype; 3320 } 3321 3322 # Return whether this file is configured to use stored 3323 # signature values from the .consign file. 3324 sub stored { 3325 if (! defined $_[0]->{stored}) { 3326 $_[0]->{stored} = grep($_ eq "stored-content", $_[0]->sigarray); 3327 } 3328 return $_[0]->{stored}; 3329 } 3330 3331 # Generic entry (file or directory) handling. 3332 # This is an empty subclass for nodes that haven't 3333 # quite decided whether they're files or dirs. 3334 # Use file methods until someone blesses them one way or the other. 3335 package entry; 3336 3337 use vars qw( @ISA ); 3338 3339 BEGIN { @ISA = qw(file) } 3340 3341 # File utilities 3342 package futil; 3343 3344 # Install one file as another. 3345 # Links them if possible (hard link), otherwise copies. 3346 # Don't ask why, but the source is a path, the tgt is a file obj. 3347 sub install { 3348 my($sp, $tgt) = @_; 3349 my($tp) = $tgt->path; 3350 return 1 if $tp eq $sp; 3351 return 1 if eval { link($sp, $tp) }; 3352 unlink($tp); 3353 if (! futil::mkdir($tgt->{dir})) { 3354 return undef; 3355 } 3356 return 1 if eval { link($sp, $tp) }; 3357 futil::copy($sp, $tp); 3358 } 3359 3360 # Copy one file to another. Arguments are actual file names. 3361 # Returns undef on failure. Preserves mtime and mode. 3362 sub copy { 3363 my ($sp, $tp) = @_; 3364 my ($mode, $length, $atime, $mtime) = (stat($sp))[2,7,8,9]; 3365 3366 # Use Perl standard library module for file copying, which handles 3367 # binary copies. <schwarze@isa.de> 1998-06-18 3368 if (! File::Copy::copy($sp, $tp)) { 3369 warn qq($0: can\'t install "$sp" to "$tp" ($!)\n); #' 3370 return undef; 3371 } 3372 # The file has been created, so try both the chmod and utime, 3373 # first making sure the copy is writable (because permissions 3374 # affect the ability to modify file times on some operating 3375 # systems), and then changing permissions back if necessary. 3376 my $ret = 1; 3377 my $wmode = $mode | 0700; 3378 if (! chmod $wmode, $tp) { 3379 warn qq($0: can\'t set mode $wmode on file "$tp" ($!)\n); #' 3380 $ret = undef; 3381 } 3382 if (! utime $atime, $mtime, $tp) { 3383 warn qq($0: can\'t set modification time for file "$tp" ($!)\n); #' 3384 $ret = undef; 3385 } 3386 if ($mode != $wmode && ! chmod $mode, $tp) { 3387 warn qq($0: can\'t set mode $mode on file "$tp" ($!)\n); #' 3388 $ret = undef; 3389 } 3390 return $ret; 3391 } 3392 3393 # Ensure that the specified directory exists. 3394 # Aborts on failure. 3395 sub mkdir { 3396 return 1 if $_[0]->{'exists'}; 3397 if (! futil::mkdir($_[0]->{dir})) { # Recursively make parent. 3398 return undef; 3399 } 3400 my($path) = $_[0]->path; 3401 if (!-d $path && !mkdir($path, 0777)) { 3402 warn qq($0: can't create directory $path ($!).\n); #' 3403 return undef; 3404 } 3405 $_[0]->{'exists'} = 1; 3406 } 3407 3408 3409 # Signature package. 3410 package sig::hash; 3411 3412 use vars qw( $called ); 3413 3414 sub init { 3415 my($dir) = @_; 3416 my($consign) = $dir->prefix . ".consign"; 3417 my($dhash) = $dir->{consign} = {}; 3418 if (-f $consign) { 3419 open(CONSIGN, $consign) || die("$0: can't open $consign ($!)\n"); 3420 while(<CONSIGN>) { 3421 chop; 3422 my ($file, $sig) = split(/:/,$_); 3423 $dhash->{$file} = $sig; 3424 } 3425 close(CONSIGN); 3426 } 3427 $dhash 3428 } 3429 3430 # Read the hash entry for a particular file. 3431 sub in { 3432 my($dir) = $_[0]->{dir}; 3433 ($dir->{consign} || init($dir))->{$_[0]->{entry}} 3434 } 3435 3436 # Write the hash entry for a particular file. 3437 sub out { 3438 my($file, $sig) = @_; 3439 my($dir) = $file->{dir}; 3440 ($dir->{consign} || init($dir))->{$file->{entry}} = $sig; 3441 $sig::hash::dirty{$dir} = $dir; 3442 } 3443 3444 # Eliminate the hash entry for a particular file. 3445 sub clear { 3446 my($file) = @_; 3447 my($dir) = $file->{dir}; 3448 delete $dir->{consign}->{$file->{entry}} if $dir->{consign}; 3449 $sig::hash::dirty{$dir} = $dir; 3450 } 3451 3452 # Flush hash entries. Called at end or via ^C interrupt. 3453 sub END { 3454 return if $called++; # May be called twice. 3455 close(CONSIGN); # in case this came in via ^C. 3456 my $dir; 3457 for $dir (values %sig::hash::dirty) { 3458 my($consign) = $dir->prefix . ".consign"; 3459 my($constemp) = $consign . ".$$"; 3460 if (! open(CONSIGN, ">$constemp")) { 3461 die("$0: can't create $constemp ($!)\n"); 3462 } 3463 my($entry, $sig); 3464 while (($entry, $sig) = each %{$dir->{consign}}) { 3465 if (! print CONSIGN "$entry:$sig\n") { 3466 die("$0: error writing to $constemp ($!)\n"); 3467 } 3468 } 3469 close(CONSIGN); 3470 if (! rename($constemp, $consign)) { 3471 if (futil::copy($constemp, $consign)) { 3472 unlink($constemp); 3473 } else { 3474 die("$0: couldn't rename or copy $constemp to $consign " . 3475 "($!)\n"); 3476 } 3477 } 3478 } 3479 } 3480 3481 3482 # Derived file caching. 3483 package cache; 3484 3485 # Find a file in the cache. Return non-null if the file is in the cache. 3486 sub in { 3487 return undef unless $param::cache; 3488 my($file, $sig) = @_; 3489 # Add the path to the signature, to make it unique. 3490 $sig = 'sig'->collect($sig, $file->path) unless $param::mixtargets; 3491 my($dir) = substr($sig, 0, 1); 3492 my($cp) = File::Spec->catfile($param::cache, $dir, $sig); 3493 return -f $cp && futil::install($cp, $file); 3494 } 3495 3496 # Try to flush a file to the cache, if not already there. 3497 # If it doesn't make it out, due to an error, then that doesn't 3498 # really matter. 3499 sub out { 3500 return unless $param::cache; 3501 my($file, $sig) = @_; 3502 # Add the path to the signature, to make it unique. 3503 $sig = 'sig'->collect($sig, $file->path) unless $param::mixtargets; 3504 my($dir) = substr($sig, 0, 1); 3505 my($sp) = $file->path; 3506 my($cp) = File::Spec->catfile($param::cache, $dir, $sig); 3507 my($cdir) = File::Spec->catfile($param::cache, $dir); 3508 if (! -d $cdir) { 3509 mkdir($cdir, 0777) || 3510 die("$0: can't create cache directory $cdir ($!).\n"); 3511 } elsif (-f $cp) { 3512 # Already cached: try to use that instead, to save space. 3513 # This can happen if the -cs option is used on a previously 3514 # uncached build, or if two builds occur simultaneously. 3515 my($lp) = ".$sig"; 3516 unlink($lp); 3517 return if ! eval { link($cp, $lp) }; 3518 rename($lp, $sp); 3519 # Unix98 says, "If the old argument and the new argument both 3520 # [refer] to the same existing file, the rename() function 3521 # returns successfully and performs no other action." So, if 3522 # $lp and $sp are links (i.e., $cp and $sp are links), $lp is 3523 # left, and we must unlink it ourselves. If the rename failed 3524 # for any reason, it is also good form to unlink the temporary 3525 # $lp. Otherwise $lp no longer exists and, barring some race, 3526 # the unlink fails silently. 3527 unlink($lp); 3528 return; 3529 } 3530 3531 return if eval { link($sp, $cp) }; 3532 return if ! -f $sp; # if nothing to cache. 3533 if (futil::copy($sp, "$cp.new")) { 3534 rename("$cp.new", $cp); 3535 } 3536 } 3537 3538 3539 # Generic signature handling package. 3540 # This handles the higher-layer distinction between content and build 3541 # signatures, relying on an underlying calculation package like 3542 # "sig::md5"" to provide the signature values themselves. 3543 package sig; 3544 3545 use vars qw( @ISA ); 3546 3547 # Select the underlying package to be used for signature calculation. 3548 # We play a few namespace games here. Specifically, we append 3549 # "sig::" to the beginning of the subclass we're passed. Then, 3550 # if the package ends in "::debug", we actually subclass the 3551 # "sig::debug" package and as a wrapper around the underlying 3552 # (e.g.) "sig::md5" package that's doing the real calculation. 3553 sub select { 3554 my($package, $subclass) = @_; 3555 my $p = $package . "::" . $subclass; 3556 my $sigpkg = $p; 3557 if ($p =~ /(.*)::debug$/) { 3558 $sigpkg = $1; 3559 $p = 'sig::debug'; 3560 } 3561 @ISA = ($p); 3562 $p->init($sigpkg); 3563 }; 3564 3565 # Set or return the build signature of a file. 3566 # This is computed elsewhere and passed in to us. 3567 sub bsig { 3568 my($self, $file, $sig) = @_; 3569 if (defined $sig) { 3570 $file->{'bsig'} = $sig; 3571 $self->set($file); 3572 } elsif (! defined $file->{'bsig'}) { 3573 $file->{'bsig'} = ''; 3574 } 3575 $file->{'bsig'} 3576 } 3577 3578 # Determine the content signature of a file. 3579 # This also sets the .consign entry unless the file is in a 3580 # repository; we don't write into repositories, only read from them. 3581 sub csig { 3582 my($self, $file) = @_; 3583 if (! $file->{'csig'}) { 3584 $file->{'csig'} = $self->srcsig($file->path); 3585 $self->set($file) if ! $file->is_on_rpath; 3586 } 3587 $_[1]->{'csig'} 3588 } 3589 3590 # Determine the current signature of an already-existing or 3591 # non-existant file. Unless a specific signature type (bsig 3592 # or csig) is requested, this consults the file's signature 3593 # array to decide whether to return content or build signature, 3594 # and whether to use a cached value from a .consign file. 3595 sub signature { 3596 my($self, $file, $sigtype) = @_; 3597 $sigtype = $file->sigtype if ! $sigtype; 3598 #open(TTY, ">/dev/tty"); 3599 #print TTY $file->path, ": $sigtype\n"; 3600 #close(TTY); 3601 my($path) = $file->path; 3602 my($time) = (stat($path))[9]; 3603 if ($time) { 3604 if ($file->{$sigtype}) { 3605 return $file->{$sigtype}; 3606 } 3607 if ($file->is_on_rpath || $file->stored) { 3608 if ('sig'->fetch($file) && $file->{$sigtype}) { 3609 if ($file->{'sigtime'} == $time || 3610 ! $param::rep_sig_times_ok 3611 && $file->is_on_rpath) { 3612 return $file->{$sigtype}; 3613 } 3614 } 3615 $file->{$sigtype} = undef; 3616 } 3617 if ($file->is_on_rpath || ! File::Spec->file_name_is_absolute($path)) { 3618 my $sig = ''; 3619 if ($sigtype eq 'bsig') { $sig = $self->bsig($file); } 3620 elsif ($sigtype eq 'csig') { $sig = $self->csig($file); } 3621 return $sig; 3622 } 3623 # This file is not in a repository or under the local directory 3624 # structure. In the canonical case, it's a utility that will be 3625 # executed by a command. Historically, Cons has returned the 3626 # name of the command concatenated with the modification time. 3627 # Note that this is *not* the path ("cc" not "/bin/cc"), so it 3628 # would lose in the unlikely event that a different copy of the 3629 # utility was used that happened to have the same modification 3630 # time (due to living in a different directory on the PATH, for 3631 # example). The obvious "fix" of using the path like so, however: 3632 # return $path . $time; 3633 # is wrong. In a multi-machine build environment, different 3634 # systems may have the same utility in different locations (due 3635 # to different NFS mount points, for example), which would 3636 # cause a lot of unnecessary builds if we used the full path. 3637 # A better solution to strengthen this signature would be to 3638 # also concatenate the size of the file, but that would cause 3639 # unnecessary rebuilds when coming from .consign files that used 3640 # the old scheme. All of which is to merely explain why we're 3641 # leaving this as it has been, but documenting it here in case 3642 # there's reason to change it in the future. 3643 return $file->{entry} . $time; 3644 } 3645 return $file->{$sigtype} = ''; 3646 } 3647 3648 sub bsignature { 3649 my($self, $file) = @_; 3650 my($path) = $file->path; 3651 my($time) = (stat($path))[9]; 3652 if ($time) { 3653 if ($file->{'bsig'}) { 3654 return $file->{'bsig'}; 3655 } 3656 if ('sig'->fetch($file, 'bsig') && $file->{'bsig'}) { 3657 if ($file->{'sigtime'} == $time || 3658 ! $param::rep_sig_times_ok 3659 && $file->is_on_rpath) { 3660 return $file->{'bsig'}; 3661 } 3662 } 3663 if ($file->is_on_rpath || ! File::Spec->file_name_is_absolute($path)) { 3664 return $self->bsig($file); 3665 } 3666 return $path . $time; 3667 } 3668 return $file->{'bsig'} = ''; 3669 } 3670 3671 # Invalidate a file's signature, also clearing its .consign entry. 3672 sub invalidate { 3673 my($self, $file) = @_; 3674 delete $file->{'sigtime'}; 3675 delete $file->{'bsig'}; 3676 delete $file->{'csig'}; 3677 sig::hash::clear($file); 3678 } 3679 3680 # Store the signature for a file. 3681 sub set { 3682 my($self, $file) = @_; 3683 my $sig = (stat($file->path))[9]; 3684 $sig .= " " . ($file->{'bsig'} || '-'); 3685 $sig .= " " . $file->{'csig'} if $file->{'csig'}; 3686 sig::hash::out($file, $sig); 3687 } 3688 3689 # Fetch the signature(s) for a file. 3690 # Returns whether there was a signature to fetch. 3691 sub fetch { 3692 my($self, $file, @kw) = @_; 3693 @kw = ('bsig', 'csig') if ! @kw; 3694 my $sig = sig::hash::in($file) || ''; 3695 my($sigtime, $bsig, $csig) = split(/ /, $sig); 3696 $file->{'sigtime'} = $sigtime; 3697 $file->{'bsig'} = $bsig || '' if grep($_ eq 'bsig', @kw); 3698 $file->{'csig'} = $csig || '' if grep($_ eq 'csig', @kw); 3699 $file->{'bsig'} = '' if $file->{'bsig'} eq '-'; 3700 return $sig ne ''; 3701 } 3702 3703 # MD5-based signature package. 3704 package sig::md5; 3705 3706 use vars qw( $md5 ); 3707 3708 # Initialize MD5 signature calculation by finding an appropriate 3709 # module and creating the proper object. 3710 sub init { 3711 my $self = shift; 3712 my @md5_modules = qw(Digest::MD5 MD5 Digest::Perl::MD5); 3713 # We used to find the right module more simply, using $_ as the 3714 # loop iterator and just doing: 3715 # 3716 # eval "use $_"; 3717 # $module = $_, $last if ! $@; 3718 # 3719 # in the loop. Empirically, though, this doesn't pass back the 3720 # right value in $module on some ActiveState versions. (Maybe 3721 # it's something to do with the eval in a for loop, I dunno.) 3722 # Work around it by using $_ to pass the value out of the loop, 3723 # which seems to work everywhere. 3724 my $module; 3725 for $module (@md5_modules) { 3726 eval "use $module"; 3727 $_ = $module, last if ! $@; 3728 } 3729 $module = $_; 3730 die "Cannot find any MD5 module from: @md5_modules" if $@; 3731 3732 $md5 = new $module; 3733 } 3734 3735 # Is the provided signature equal to the signature of the current 3736 # instantiation of the target (and does the target exist)? 3737 sub current { 3738 my($self, $file, $sig, $sigtype) = @_; 3739 $self->bsignature($file) eq $sig; 3740 } 3741 3742 # Return an aggregate signature for a list of signature values. 3743 sub collect { 3744 my($self, @sigs) = @_; 3745 # The following sequence is faster than calling the hex interface. 3746 $md5->reset(); 3747 $md5->add(join('', $param::salt, @sigs)); 3748 unpack("H*", $md5->digest()); 3749 } 3750 3751 # Directly compute a file signature as the MD5 checksum of the 3752 # bytes in the file. 3753 sub srcsig { 3754 my($self, $path) = @_; 3755 $md5->reset(); 3756 open(FILE, $path) || return ''; 3757 binmode(FILE); 3758 $md5->addfile(\*FILE); 3759 close(FILE); 3760 unpack("H*", $md5->digest()); 3761 } 3762 3763 # Compute the signature of a command string. 3764 # For MD5, this is just the string itself, since MD5 will condense 3765 # the string contents into the ultimate signature. Other signature 3766 # schemes may need to figure this out differently. 3767 sub cmdsig { 3768 my($self, $sig) = @_; 3769 return $sig 3770 } 3771 3772 # Generic debug package for signature calculation. 3773 # Because of the way we're called by sig::select() and then use 3774 # the specified value to set up @ISA, this package is essentially a 3775 # factory that creates packages like sig::md5::debug, etc., on the fly. 3776 package sig::debug; 3777 3778 use vars qw( @ISA $sigpkg $outfh ); 3779 3780 local *FH; 3781 3782 sub init { 3783 my $self = shift; 3784 $sigpkg = shift; 3785 @ISA = ($sigpkg); 3786 $sigpkg->init(); 3787 my $file = $ENV{CONS_SIG_DEBUG}; 3788 if ($file) { 3789 if (! open(FH, ">$file")) { 3790 die "Cannot open $file: $!"; 3791 } 3792 $outfh = \*FH; 3793 } else { 3794 $outfh = \*STDOUT; 3795 } 3796 } 3797 3798 sub current { 3799 my($self, $file, $sig, $sigtype) = @_; 3800 my $fsig = $self->bsignature($file); 3801 my $sub = "${sigpkg}::current"; 3802 my $sep = "\n" . ' ' x (length($sub) + 1 - 3); 3803 print $outfh "$sub(|$fsig|${sep}eq |$sig|)\n"; 3804 return $fsig eq $sig; 3805 } 3806 3807 sub collect { 3808 my($self, @sigs) = @_; 3809 my $sig = $sigpkg->collect(@sigs); 3810 my $sub = "${sigpkg}::collect"; 3811 my $sep = ",\n" . ' ' x (length($sub) + 1); 3812 my $buf = join($sep, @sigs); 3813 $buf = $param::salt . $sep . $buf if $param::salt; 3814 print $outfh "$sub($buf)\n\t=> |$sig|\n"; 3815 return $sig; 3816 } 3817 3818 sub srcsig { 3819 my($self, $path) = @_; 3820 my $sig = $sigpkg->srcsig($path); 3821 print $outfh "${sigpkg}::srcsig($path)\n\t=> |$sig|\n"; 3822 return $sig; 3823 } 3824 3825 __END__; 3826 3827 =head1 NAME 3828 3829 Cons - A Software Construction System 3830 3831 =head1 DESCRIPTION 3832 3833 A guide and reference for version 2.3.1 3834 3835 Copyright (c) 1996-2001 Free Software Foundation, Inc. 3836 3837 This program is free software; you can redistribute it and/or modify 3838 it under the terms of the GNU General Public License as published by 3839 the Free Software Foundation; either version 2 of the License, or 3840 (at your option) any later version. 3841 3842 This program is distributed in the hope that it will be useful, 3843 but WITHOUT ANY WARRANTY; without even the implied warranty of 3844 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 3845 GNU General Public License for more details. 3846 3847 You should have received a copy of the GNU General Public License 3848 along with this program; see the file COPYING. If not, write to 3849 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 3850 Boston, MA 02111-1307, USA. 3851 3852 =head1 Introduction 3853 3854 B<Cons> is a system for constructing, primarily, software, but is quite 3855 different from previous software construction systems. Cons was designed 3856 from the ground up to deal easily with the construction of software spread 3857 over multiple source directories. Cons makes it easy to create build scripts 3858 that are simple, understandable and maintainable. Cons ensures that complex 3859 software is easily and accurately reproducible. 3860 3861 Cons uses a number of techniques to accomplish all of this. Construction 3862 scripts are just Perl scripts, making them both easy to comprehend and very 3863 flexible. Global scoping of variables is replaced with an import/export 3864 mechanism for sharing information between scripts, significantly improving 3865 the readability and maintainability of each script. B<Construction 3866 environments> are introduced: these are Perl objects that capture the 3867 information required for controlling the build process. Multiple 3868 environments are used when different semantics are required for generating 3869 products in the build tree. Cons implements automatic dependency analysis 3870 and uses this to globally sequence the entire build. Variant builds are 3871 easily produced from a single source tree. Intelligent build subsetting is 3872 possible, when working on localized changes. Overrides can be setup to 3873 easily override build instructions without modifying any scripts. MD5 3874 cryptographic B<signatures> are associated with derived files, and are used 3875 to accurately determine whether a given file needs to be rebuilt. 3876 3877 While offering all of the above, and more, Cons remains simple and easy to 3878 use. This will, hopefully, become clear as you read the remainder of this 3879 document. 3880 3881 3882 =head1 Why Cons? Why not Make? 3883 3884 Cons is a B<make> replacement. In the following paragraphs, we look at a few 3885 of the undesirable characteristics of make--and typical build environments 3886 based on make--that motivated the development of Cons. 3887 3888 =head2 Build complexity 3889 3890 Traditional make-based systems of any size tend to become quite complex. The 3891 original make utility and its derivatives have contributed to this tendency 3892 in a number of ways. Make is not good at dealing with systems that are 3893 spread over multiple directories. Various work-arounds are used to overcome 3894 this difficulty; the usual choice is for make to invoke itself recursively 3895 for each sub-directory of a build. This leads to complicated code, in which 3896 it is often unclear how a variable is set, or what effect the setting of a 3897 variable will have on the build as a whole. The make scripting language has 3898 gradually been extended to provide more possibilities, but these have 3899 largely served to clutter an already overextended language. Often, builds 3900 are done in multiple passes in order to provide appropriate products from 3901 one directory to another directory. This represents a further increase in 3902 build complexity. 3903 3904 3905 =head2 Build reproducibility 3906 3907 The bane of all makes has always been the correct handling of 3908 dependencies. Most often, an attempt is made to do a reasonable job of 3909 dependencies within a single directory, but no serious attempt is made to do 3910 the job between directories. Even when dependencies are working correctly, 3911 make's reliance on a simple time stamp comparison to determine whether a 3912 file is out of date with respect to its dependents is not, in general, 3913 adequate for determining when a file should be rederived. If an external 3914 library, for example, is rebuilt and then ``snapped'' into place, the 3915 timestamps on its newly created files may well be earlier than the last 3916 local build, since it was built before it became visible. 3917 3918 3919 =head2 Variant builds 3920 3921 Make provides only limited facilities for handling variant builds. With the 3922 proliferation of hardware platforms and the need for debuggable 3923 vs. optimized code, the ability to easily create these variants is 3924 essential. More importantly, if variants are created, it is important to 3925 either be able to separate the variants or to be able to reproduce the 3926 original or variant at will. With make it is very difficult to separate the 3927 builds into multiple build directories, separate from the source. And if 3928 this technique isn't used, it's also virtually impossible to guarantee at 3929 any given time which variant is present in the tree, without resorting to a 3930 complete rebuild. 3931 3932 3933 =head2 Repositories 3934 3935 Make provides only limited support for building software from code that 3936 exists in a central repository directory structure. The VPATH feature of 3937 GNU make (and some other make implementations) is intended to provide this, 3938 but doesn't work as expected: it changes the path of target file to the 3939 VPATH name too early in its analysis, and therefore searches for all 3940 dependencies in the VPATH directory. To ensure correct development builds, 3941 it is important to be able to create a file in a local build directory and 3942 have any files in a code repository (a VPATH directory, in make terms) that 3943 depend on the local file get rebuilt properly. This isn't possible with 3944 VPATH, without coding a lot of complex repository knowledge directly into 3945 the makefiles. 3946 3947 3948 =head1 Keeping it simple 3949 3950 A few of the difficulties with make have been cited above. In this and 3951 subsequent sections, we shall introduce Cons and show how these issues are 3952 addressed. 3953 3954 =head2 Perl scripts 3955 3956 Cons is Perl-based. That is, Cons scripts--F<Conscript> and F<Construct> 3957 files, the equivalent to F<Makefile> or F<makefile>--are all written in 3958 Perl. This provides an immediate benefit: the language for writing scripts 3959 is a familiar one. Even if you don't happen to be a Perl programmer, it 3960 helps to know that Perl is basically just a simple declarative language, 3961 with a well-defined flow of control, and familiar semantics. It has 3962 variables that behave basically the way you would expect them to, 3963 subroutines, flow of control, and so on. There is no special syntax 3964 introduced for Cons. The use of Perl as a scripting language simplifies 3965 the task of expressing the appropriate solution to the often complex 3966 requirements of a build. 3967 3968 3969 =head2 Hello, World! 3970 3971 To ground the following discussion, here's how you could build the B<Hello, 3972 World!> C application with Cons: 3973 3974 3975 3976 $env = new cons(); 3977 Program $env 'hello', 'hello.c'; 3978 3979 If you install this script in a directory, naming the script F<Construct>, 3980 and create the F<hello.c> source file in the same directory, then you can 3981 type C<cons hello> to build the application: 3982 3983 3984 3985 % cons hello 3986 cc -c hello.c -o hello.o 3987 cc -o hello hello.o 3988 3989 3990 =head2 Construction environments 3991 3992 A key simplification of Cons is the idea of a B<construction environment>. A 3993 construction environment is an B<object> characterized by a set of key/value 3994 pairs and a set of B<methods>. In order to tell Cons how to build something, 3995 you invoke the appropriate method via an appropriate construction 3996 environment. Consider the following example: 3997 3998 3999 4000 $env = new cons( 4001 CC => 'gcc', 4002 LIBS => 'libworld.a' 4003 ); 4004 4005 Program $env 'hello', 'hello.c'; 4006 4007 In this case, rather than using the default construction environment, as is, 4008 we have overridden the value of C<CC> so that the GNU C Compiler equivalent 4009 is used, instead. Since this version of B<Hello, World!> requires a library, 4010 F<libworld.a>, we have specified that any program linked in this environment 4011 should be linked with that library. If the library exists already, well and 4012 good, but if not, then we'll also have to include the statement: 4013 4014 4015 4016 Library $env 'libworld', 'world.c'; 4017 4018 Now if you type C<cons hello>, the library will be built before the program 4019 is linked, and, of course, C<gcc> will be used to compile both modules: 4020 4021 4022 4023 % cons hello 4024 gcc -c hello.c -o hello.o 4025 gcc -c world.c -o world.o 4026 ar r libworld.a world.o 4027 ar: creating libworld.a 4028 ranlib libworld.a 4029 gcc -o hello hello.o libworld.a 4030 4031 4032 =head2 Automatic and complete dependency analysis 4033 4034 With Cons, dependencies are handled automatically. Continuing the previous 4035 example, note that when we modify F<world.c>, F<world.o> is recompiled, 4036 F<libworld.a> recreated, and F<hello> relinked: 4037 4038 4039 4040 % vi world.c 4041 [EDIT] 4042 % cons hello 4043 gcc -c world.c -o world.o 4044 ar r libworld.a world.o 4045 ar: creating libworld.a 4046 ranlib libworld.a 4047 gcc -o hello hello.o libworld.a 4048 4049 This is a relatively simple example: Cons ``knows'' F<world.o> depends upon 4050 F<world.c>, because the dependency is explicitly set up by the C<Library> 4051 method. It also knows that F<libworld.a> depends upon F<world.o> and that 4052 F<hello> depends upon F<libworld.a>, all for similar reasons. 4053 4054 Now it turns out that F<hello.c> also includes the interface definition 4055 file, F<world.h>: 4056 4057 4058 4059 % emacs world.h 4060 [EDIT] 4061 % cons hello 4062 gcc -c hello.c -o hello.o 4063 gcc -o hello hello.o libworld.a 4064 4065 How does Cons know that F<hello.c> includes F<world.h>, and that F<hello.o> 4066 must therefore be recompiled? For now, suffice it to say that when 4067 considering whether or not F<hello.o> is up-to-date, Cons invokes a scanner 4068 for its dependency, F<hello.c>. This scanner enumerates the files included 4069 by F<hello.c> to come up with a list of further dependencies, beyond those 4070 made explicit by the Cons script. This process is recursive: any files 4071 included by included files will also be scanned. 4072 4073 Isn't this expensive? The answer is--it depends. If you do a full build of a 4074 large system, the scanning time is insignificant. If you do a rebuild of a 4075 large system, then Cons will spend a fair amount of time thinking about it 4076 before it decides that nothing has to be done (although not necessarily more 4077 time than make!). The good news is that Cons makes it very easy to 4078 intelligently subset your build, when you are working on localized changes. 4079 4080 4081 =head2 Automatic global build sequencing 4082 4083 Because Cons does full and accurate dependency analysis, and does this 4084 globally, for the entire build, Cons is able to use this information to take 4085 full control of the B<sequencing> of the build. This sequencing is evident 4086 in the above examples, and is equivalent to what you would expect for make, 4087 given a full set of dependencies. With Cons, this extends trivially to 4088 larger, multi-directory builds. As a result, all of the complexity involved 4089 in making sure that a build is organized correctly--including multi-pass 4090 hierarchical builds--is eliminated. We'll discuss this further in the next 4091 sections. 4092 4093 =head1 Building large trees--still just as simple 4094 4095 4096 =head2 A hierarchy of build scripts 4097 4098 A larger build, in Cons, is organized by creating a hierarchy of B<build 4099 scripts>. At the top of the tree is a script called F<Construct>. The rest 4100 of the scripts, by convention, are each called F<Conscript>. These scripts 4101 are connected together, very simply, by the C<Build>, C<Export>, and 4102 C<Import> commands. 4103 4104 4105 =head2 The Build command 4106 4107 The C<Build> command takes a list of F<Conscript> file names, and arranges 4108 for them to be included in the build. For example: 4109 4110 Build qw( 4111 drivers/display/Conscript 4112 drivers/mouse/Conscript 4113 parser/Conscript 4114 utilities/Conscript 4115 ); 4116 4117 This is a simple two-level hierarchy of build scripts: all the subsidiary 4118 F<Conscript> files are mentioned in the top-level F<Construct> file. Notice 4119 that not all directories in the tree necessarily have build scripts 4120 associated with them. 4121 4122 This could also be written as a multi-level script. For example, the 4123 F<Construct> file might contain this command: 4124 4125 Build qw( 4126 parser/Conscript 4127 drivers/Conscript 4128 utilities/Conscript 4129 ); 4130 4131 and the F<Conscript> file in the F<drivers> directory might contain this: 4132 4133 Build qw( 4134 display/Conscript 4135 mouse/Conscript 4136 ); 4137 4138 Experience has shown that the former model is a little easier to understand, 4139 since the whole construction tree is laid out in front of you, at the 4140 top-level. Hybrid schemes are also possible. A separately maintained 4141 component that needs to be incorporated into a build tree, for example, 4142 might hook into the build tree in one place, but define its own construction 4143 hierarchy. 4144 4145 By default, Cons does not change its working directory to the directory 4146 containing a subsidiary F<Conscript> file it is including. This behavior 4147 can be enabled for a build by specifying, in the top-level F<Construct> 4148 file: 4149 4150 Conscript_chdir 1; 4151 4152 When enabled, Cons will change to the subsidiary F<Conscript> file's 4153 containing directory while reading in that file, and then change back 4154 to the top-level directory once the file has been processed. 4155 4156 It is expected that this behavior will become the default in some future 4157 version of Cons. To prepare for this transition, builds that expect 4158 Cons to remain at the top of the build while it reads in a subsidiary 4159 F<Conscript> file should explicitly disable this feature as follows: 4160 4161 Conscript_chdir 0; 4162 4163 4164 =head2 Relative, top-relative, and absolute file names 4165 4166 You may have noticed that the file names specified to the Build command are 4167 relative to the location of the script it is invoked from. This is generally 4168 true for other filename arguments to other commands, too, although we might 4169 as well mention here that if you begin a file name with a hash mark, ``#'', 4170 then that file is interpreted relative to the top-level directory (where the 4171 F<Construct> file resides). And, not surprisingly, if you begin it with ``/'', 4172 then it is considered to be an absolute pathname. This is true even on 4173 systems which use a back slash rather than a forward slash to name absolute 4174 paths. 4175 4176 (There is another file prefix, ``!'', that is interpreted specially by 4177 Cons. See discussion of the C<Link> command, below, for details.) 4178 4179 4180 =head2 Using modules in build scripts 4181 4182 You may pull modules into each F<Conscript> file using the normal Perl 4183 C<use> or C<require> statements: 4184 4185 use English; 4186 require My::Module; 4187 4188 Each C<use> or C<require> only affects the one F<Conscript> file in which 4189 it appears. To use a module in multiple F<Conscript> files, you must 4190 put a C<use> or C<require> statement in each one that needs the module. 4191 4192 4193 =head2 Scope of variables 4194 4195 The top-level F<Construct> file and all F<Conscript> files begin life in 4196 a common, separate Perl package. B<Cons> controls the symbol table for 4197 the package so that, the symbol table for each script is empty, except 4198 for the F<Construct> file, which gets some of the command line arguments. 4199 All of the variables that are set or used, therefore, are set by the 4200 script itself--not by some external script. 4201 4202 Variables can be explicitly B<imported> by a script from its parent 4203 script. To import a variable, it must have been B<exported> by the parent 4204 and initialized (otherwise an error will occur). 4205 4206 4207 =head2 The Export command 4208 4209 The C<Export> command is used as in the following example: 4210 4211 $env = new cons(); 4212 $INCLUDE = "#export/include"; 4213 $LIB = "#export/lib"; 4214 Export qw( env INCLUDE LIB ); 4215 Build qw( util/Conscript ); 4216 4217 The values of the simple variables mentioned in the C<Export> list will be 4218 squirreled away by any subsequent C<Build> commands. The C<Export> command 4219 will only export Perl B<scalar> variables, that is, variables whose name 4220 begins with C<$>. Other variables, objects, etc. can be exported by 4221 reference--but all scripts will refer to the same object, and this object 4222 should be considered to be read-only by the subsidiary scripts and by the 4223 original exporting script. It's acceptable, however, to assign a new value 4224 to the exported scalar variable--that won't change the underlying variable 4225 referenced. This sequence, for example, is OK: 4226 4227 $env = new cons(); 4228 Export qw( env INCLUDE LIB ); 4229 Build qw( util/Conscript ); 4230 $env = new cons(CFLAGS => '-O'); 4231 Build qw( other/Conscript ); 4232 4233 It doesn't matter whether the variable is set before or after the C<Export> 4234 command. The important thing is the value of the variable at the time the 4235 C<Build> command is executed. This is what gets squirreled away. Any 4236 subsequent C<Export> commands, by the way, invalidate the first: you must 4237 mention all the variables you wish to export on each C<Export> command. 4238 4239 4240 =head2 The Import command 4241 4242 Variables exported by the C<Export> command can be imported into subsidiary 4243 scripts by the C<Import> command. The subsidiary script always imports 4244 variables directly from the superior script. Consider this example: 4245 4246 Import qw( env INCLUDE ); 4247 4248 This is only legal if the parent script exported both C<$env> and 4249 C<$INCLUDE>. It also must have given each of these variables values. It is 4250 OK for the subsidiary script to only import a subset of the exported 4251 variables (in this example, C<$LIB>, which was exported by the previous 4252 example, is not imported). 4253 4254 All the imported variables are automatically re-exported, so the sequence: 4255 4256 Import qw ( env INCLUDE ); 4257 Build qw ( beneath-me/Conscript ); 4258 4259 will supply both C<$env> and C<$INCLUDE> to the subsidiary file. If only 4260 C<$env> is to be exported, then the following will suffice: 4261 4262 Import qw ( env INCLUDE ); 4263 Export qw ( env ); 4264 Build qw ( beneath-me/Conscript ); 4265 4266 Needless to say, the variables may be modified locally before invoking 4267 C<Build> on the subsidiary script. 4268 4269 4270 =head2 Build script evaluation order 4271 4272 The only constraint on the ordering of build scripts is that superior 4273 scripts are evaluated before their inferior scripts. The top-level 4274 F<Construct> file, for instance, is evaluated first, followed by any 4275 inferior scripts. This is all you really need to know about the evaluation 4276 order, since order is generally irrelevant. Consider the following C<Build> 4277 command: 4278 4279 Build qw( 4280 drivers/display/Conscript 4281 drivers/mouse/Conscript 4282 parser/Conscript 4283 utilities/Conscript 4284 ); 4285 4286 We've chosen to put the script names in alphabetical order, simply because 4287 that's the most convenient for maintenance purposes. Changing the order will 4288 make no difference to the build. 4289 4290 4291 =head1 A Model for sharing files 4292 4293 4294 =head2 Some simple conventions 4295 4296 In any complex software system, a method for sharing build products needs to 4297 be established. We propose a simple set of conventions which are trivial to 4298 implement with Cons, but very effective. 4299 4300 The basic rule is to require that all build products which need to be shared 4301 between directories are shared via an intermediate directory. We have 4302 typically called this F<export>, and, in a C environment, provided 4303 conventional sub-directories of this directory, such as F<include>, F<lib>, 4304 F<bin>, etc. 4305 4306 These directories are defined by the top-level F<Construct> file. A simple 4307 F<Construct> file for a B<Hello, World!> application, organized using 4308 multiple directories, might look like this: 4309 4310 # Construct file for Hello, World! 4311 4312 # Where to put all our shared products. 4313 $EXPORT = '#export'; 4314 4315 Export qw( CONS INCLUDE LIB BIN ); 4316 4317 # Standard directories for sharing products. 4318 $INCLUDE = "$EXPORT/include"; 4319 $LIB = "$EXPORT/lib"; 4320 $BIN = "$EXPORT/bin"; 4321 4322 # A standard construction environment. 4323 $CONS = new cons ( 4324 CPPPATH => $INCLUDE, # Include path for C Compilations 4325 LIBPATH => $LIB, # Library path for linking programs 4326 LIBS => '-lworld', # List of standard libraries 4327 ); 4328 4329 Build qw( 4330 hello/Conscript 4331 world/Conscript 4332 ); 4333 4334 The F<world> directory's F<Conscript> file looks like this: 4335 4336 # Conscript file for directory world 4337 Import qw( CONS INCLUDE LIB ); 4338 4339 # Install the products of this directory 4340 Install $CONS $LIB, 'libworld.a'; 4341 Install $CONS $INCLUDE, 'world.h'; 4342 4343 # Internal products 4344 Library $CONS 'libworld.a', 'world.c'; 4345 4346 and the F<hello> directory's F<Conscript> file looks like this: 4347 4348 # Conscript file for directory hello 4349 Import qw( CONS BIN ); 4350 4351 # Exported products 4352 Install $CONS $BIN, 'hello'; 4353 4354 # Internal products 4355 Program $CONS 'hello', 'hello.c'; 4356 4357 To construct a B<Hello, World!> program with this directory structure, go to 4358 the top-level directory, and invoke C<cons> with the appropriate 4359 arguments. In the following example, we tell Cons to build the directory 4360 F<export>. To build a directory, Cons recursively builds all known products 4361 within that directory (only if they need rebuilding, of course). If any of 4362 those products depend upon other products in other directories, then those 4363 will be built, too. 4364 4365 % cons export 4366 Install world/world.h as export/include/world.h 4367 cc -Iexport/include -c hello/hello.c -o hello/hello.o 4368 cc -Iexport/include -c world/world.c -o world/world.o 4369 ar r world/libworld.a world/world.o 4370 ar: creating world/libworld.a 4371 ranlib world/libworld.a 4372 Install world/libworld.a as export/lib/libworld.a 4373 cc -o hello/hello hello/hello.o -Lexport/lib -lworld 4374 Install hello/hello as export/bin/hello 4375 4376 4377 =head2 Clean, understandable, location-independent scripts 4378 4379 You'll note that the two F<Conscript> files are very clean and 4380 to-the-point. They simply specify products of the directory and how to build 4381 those products. The build instructions are minimal: they specify which 4382 construction environment to use, the name of the product, and the name of 4383 the inputs. Note also that the scripts are location-independent: if you wish 4384 to reorganize your source tree, you are free to do so: you only have to 4385 change the F<Construct> file (in this example), to specify the new locations 4386 of the F<Conscript> files. The use of an export tree makes this goal easy. 4387 4388 Note, too, how Cons takes care of little details for you. All the F<export> 4389 directories, for example, were made automatically. And the installed files 4390 were really hard-linked into the respective export directories, to save 4391 space and time. This attention to detail saves considerable work, and makes 4392 it even easier to produce simple, maintainable scripts. 4393 4394 4395 =head1 Separating source and build trees 4396 4397 It's often desirable to keep any derived files from the build completely 4398 separate from the source files. This makes it much easier to keep track of 4399 just what is a source file, and also makes it simpler to handle B<variant> 4400 builds, especially if you want the variant builds to co-exist. 4401 4402 4403 =head2 Separating build and source directories using the Link command 4404 4405 Cons provides a simple mechanism that handles all of these requirements. The 4406 C<Link> command is invoked as in this example: 4407 4408 Link 'build' => 'src'; 4409 4410 The specified directories are ``linked'' to the specified source 4411 directory. Let's suppose that you setup a source directory, F<src>, with the 4412 sub-directories F<world> and F<hello> below it, as in the previous 4413 example. You could then substitute for the original build lines the 4414 following: 4415 4416 Build qw( 4417 build/world/Conscript 4418 build/hello/Conscript 4419 ); 4420 4421 Notice that you treat the F<Conscript> file as if it existed in the build 4422 directory. Now if you type the same command as before, you will get the 4423 following results: 4424 4425 % cons export 4426 Install build/world/world.h as export/include/world.h 4427 cc -Iexport/include -c build/hello/hello.c -o build/hello/hello.o 4428 cc -Iexport/include -c build/world/world.c -o build/world/world.o 4429 ar r build/world/libworld.a build/world/world.o 4430 ar: creating build/world/libworld.a 4431 ranlib build/world/libworld.a 4432 Install build/world/libworld.a as export/lib/libworld.a 4433 cc -o build/hello/hello build/hello/hello.o -Lexport/lib -lworld 4434 Install build/hello/hello as export/bin/hello 4435 4436 Again, Cons has taken care of the details for you. In particular, you will 4437 notice that all the builds are done using source files and object files from 4438 the build directory. For example, F<build/world/world.o> is compiled from 4439 F<build/world/world.c>, and F<export/include/world.h> is installed from 4440 F<build/world/world.h>. This is accomplished on most systems by the simple 4441 expedient of ``hard'' linking the required files from each source directory 4442 into the appropriate build directory. 4443 4444 The links are maintained correctly by Cons, no matter what you do to the 4445 source directory. If you modify a source file, your editor may do this ``in 4446 place'' or it may rename it first and create a new file. In the latter case, 4447 any hard link will be lost. Cons will detect this condition the next time 4448 the source file is needed, and will relink it appropriately. 4449 4450 You'll also notice, by the way, that B<no> changes were required to the 4451 underlying F<Conscript> files. And we can go further, as we shall see in the 4452 next section. 4453 4454 =head2 Explicit references to the source directory 4455 4456 When using the C<Link> command on some operating systems or with some 4457 tool chains, it's sometimes useful to have a command actually use 4458 the path name to the source directory, not the build directory. For 4459 example, on systems that must copy, not "hard link," the F<src/> and 4460 F<build/> copies of C<Linked> files, using the F<src/> path of a file 4461 name might make an editor aware that a syntax error must be fixed in the 4462 source directory, not the build directory. 4463 4464 You can tell Cons that you want to use the "source path" for a file by 4465 preceding the file name with a ``!'' (exclamation point). For example, 4466 if we add a ``!'' to the beginning of a source file: 4467 4468 Program $env "foo", "!foo.c"; # Notice initial ! on foo.c 4469 4470 Cons will compile the target as follows: 4471 4472 cc -c src/foo.c -o build/foo.o 4473 cc -o build/foo build/foo.o 4474 4475 Notice that Cons has compiled the program from the the F<src/foo.c> 4476 source file. Without the initial ``!'', Cons would have compiled the 4477 program using the F<build/foo.c> path name. 4478 4479 4480 4481 =head1 Variant builds 4482 4483 4484 =head2 Hello, World! for baNaNa and peAcH OS's 4485 4486 Variant builds require just another simple extension. Let's take as an 4487 example a requirement to allow builds for both the baNaNa and peAcH 4488 operating systems. In this case, we are using a distributed file system, 4489 such as NFS to access the particular system, and only one or the other of 4490 the systems has to be compiled for any given invocation of C<cons>. Here's 4491 one way we could set up the F<Construct> file for our B<Hello, World!> 4492 application: 4493 4494 # Construct file for Hello, World! 4495 4496 die qq(OS must be specified) unless $OS = $ARG{OS}; 4497 die qq(OS must be "peach" or "banana") 4498 if $OS ne "peach" && $OS ne "banana"; 4499 4500 # Where to put all our shared products. 4501 $EXPORT = "#export/$OS"; 4502 4503 Export qw( CONS INCLUDE LIB BIN ); 4504 4505 # Standard directories for sharing products. 4506 $INCLUDE = "$EXPORT/include"; 4507 $LIB = "$EXPORT/lib"; 4508 $BIN = "$EXPORT/bin"; 4509 4510 # A standard construction environment. 4511 $CONS = new cons ( 4512 CPPPATH => $INCLUDE, # Include path for C Compilations 4513 LIBPATH => $LIB, # Library path for linking programs 4514 LIBS => '-lworld', # List of standard libraries 4515 ); 4516 4517 # $BUILD is where we will derive everything. 4518 $BUILD = "#build/$OS"; 4519 4520 # Tell cons where the source files for $BUILD are. 4521 Link $BUILD => 'src'; 4522 4523 Build ( 4524 "$BUILD/hello/Conscript", 4525 "$BUILD/world/Conscript", 4526 ); 4527 4528 Now if we login to a peAcH system, we can build our B<Hello, World!> 4529 application for that platform: 4530 4531 % cons export OS=peach 4532 Install build/peach/world/world.h as export/peach/include/world.h 4533 cc -Iexport/peach/include -c build/peach/hello/hello.c -o build/peach/hello/hello.o 4534 cc -Iexport/peach/include -c build/peach/world/world.c -o build/peach/world/world.o 4535 ar r build/peach/world/libworld.a build/peach/world/world.o 4536 ar: creating build/peach/world/libworld.a 4537 ranlib build/peach/world/libworld.a 4538 Install build/peach/world/libworld.a as export/peach/lib/libworld.a 4539 cc -o build/peach/hello/hello build/peach/hello/hello.o -Lexport/peach/lib -lworld 4540 Install build/peach/hello/hello as export/peach/bin/hello 4541 4542 4543 =head2 Variations on a theme 4544 4545 Other variations of this model are possible. For example, you might decide 4546 that you want to separate out your include files into platform dependent and 4547 platform independent files. In this case, you'd have to define an 4548 alternative to C<$INCLUDE> for platform-dependent files. Most F<Conscript> 4549 files, generating purely platform-independent include files, would not have 4550 to change. 4551 4552 You might also want to be able to compile your whole system with debugging 4553 or profiling, for example, enabled. You could do this with appropriate 4554 command line options, such as C<DEBUG=on>. This would then be translated 4555 into the appropriate platform-specific requirements to enable debugging 4556 (this might include turning off optimization, for example). You could 4557 optionally vary the name space for these different types of systems, but, as 4558 we'll see in the next section, it's not B<essential> to do this, since Cons 4559 is pretty smart about rebuilding things when you change options. 4560 4561 4562 =head1 Signatures 4563 4564 Cons uses file B<signatures> to decide if a derived file is out-of-date 4565 and needs rebuilding. In essence, if the contents of a file change, 4566 or the manner in which the file is built changes, the file's signature 4567 changes as well. This allows Cons to decide with certainty when a file 4568 needs rebuilding, because Cons can detect, quickly and reliably, whether 4569 any of its dependency files have been changed. 4570 4571 4572 =head2 MD5 content and build signatures 4573 4574 Cons uses the B<MD5> (B<Message Digest 5>) algorithm to compute file 4575 signatures. The MD5 algorithm computes a strong cryptographic checksum 4576 for any given input string. Cons can, based on configuration, use two 4577 different MD5 signatures for a given file: 4578 4579 The B<content signature> of a file is an MD5 checksum of the file's 4580 contents. Consequently, when the contents of a file change, its content 4581 signature changes as well. 4582 4583 The B<build signature> of a file is a combined MD5 checksum of: 4584 4585 =over 4 4586 4587 the signatures of all the input files used to build the file 4588 4589 the signatures of all dependency files discovered by source scanners 4590 (for example, C<.h> files) 4591 4592 the signatures of all dependency files specified explicitly via the 4593 C<Depends> method) 4594 4595 the command-line string used to build the file 4596 4597 =back 4598 4599 The build signature is, in effect, a digest of all the dependency 4600 information for the specified file. Consequently, a file's build 4601 signature changes whenever any part of its dependency information 4602 changes: a new file is added, the contents of a file on which it depends 4603 change, there's a change to the command line used to build the file (or 4604 any of its dependency files), etc. 4605 4606 For example, in the previous section, the build signature of the 4607 F<world.o> file will include: 4608 4609 =over 4 4610 4611 the signature of the F<world.c> file 4612 4613 the signatures of any header files that Cons detects are included, 4614 directly or indirectly, by F<world.c> 4615 4616 the text of the actual command line was used to generate F<world.o> 4617 4618 =back 4619 4620 Similarly, the build signature of the F<libworld.a> file will include 4621 all the signatures of its constituents (and hence, transitively, the 4622 signatures of B<their> constituents), as well as the command line that 4623 created the file. 4624 4625 Note that there is no need for a derived file to depend upon any 4626 particular F<Construct> or F<Conscript> file. If changes to these files 4627 affect a file, then this will be automatically reflected in its build 4628 signature, since relevant parts of the command line are included in the 4629 signature. Unrelated F<Construct> or F<Conscript> changes will have no 4630 effect. 4631 4632 4633 =head2 Storing signatures in .consign files 4634 4635 Before Cons exits, it stores the calculated signatures for all of the 4636 files it built or examined in F<.consign> files, one per directory. 4637 Cons uses this stored information on later invocations to decide if 4638 derived files need to be rebuilt. 4639 4640 After the previous example was compiled, the F<.consign> file in the 4641 F<build/peach/world> directory looked like this: 4642 4643 world.h:985533370 - d181712f2fdc07c1f05d97b16bfad904 4644 world.o:985533372 2a0f71e0766927c0532977b0d2158981 4645 world.c:985533370 - c712f77189307907f4189b5a7ab62ff3 4646 libworld.a:985533374 69e568fc5241d7d25be86d581e1fb6aa 4647 4648 After the file name and colon, the first number is a timestamp of the 4649 file's modification time (on UNIX systems, this is typically the number 4650 of seconds since January 1st, 1970). The second value is the build 4651 signature of the file (or ``-'' in the case of files with no build 4652 signature--that is, source files). The third value, if any, is the 4653 content signature of the file. 4654 4655 4656 =head2 Using build signatures to decide when to rebuild files 4657 4658 When Cons is deciding whether to build or rebuild a derived file, it 4659 first computes the file's current build signature. If the file doesn't 4660 exist, it must obviously be built. 4661 4662 If, however, the file already exists, Cons next compares the 4663 modification timestamp of the file against the timestamp value in 4664 the F<.consign> file. If the timestamps match, Cons compares the 4665 newly-computed build signature against the build signature in the 4666 F<.consign> file. If the timestamps do not match or the build 4667 signatures do not match, the derived file is rebuilt. 4668 4669 After the file is built or rebuilt, Cons arranges to store the 4670 newly-computed build signature in the F<.consign> file when it exits. 4671 4672 4673 =head2 Signature example 4674 4675 The use of these signatures is an extremely simple, efficient, and 4676 effective method of improving--dramatically--the reproducibility of a 4677 system. 4678 4679 We'll demonstrate this with a simple example: 4680 4681 # Simple "Hello, World!" Construct file 4682 $CFLAGS = '-g' if $ARG{DEBUG} eq 'on'; 4683 $CONS = new cons(CFLAGS => $CFLAGS); 4684 Program $CONS 'hello', 'hello.c'; 4685 4686 Notice how Cons recompiles at the appropriate times: 4687 4688 % cons hello 4689 cc -c hello.c -o hello.o 4690 cc -o hello hello.o 4691 % cons hello 4692 cons: "hello" is up-to-date. 4693 % cons DEBUG=on hello 4694 cc -g -c hello.c -o hello.o 4695 cc -o hello hello.o 4696 % cons DEBUG=on hello 4697 cons: "hello" is up-to-date. 4698 % cons hello 4699 cc -c hello.c -o hello.o 4700 cc -o hello hello.o 4701 4702 4703 =head2 Source-file signature configuration 4704 4705 Cons provides a C<SourceSignature> method that allows you to configure 4706 how the signature should be calculated for any source file when its 4707 signature is being used to decide if a dependent file is up-to-date. 4708 The arguments to the C<SourceSignature> method consist of one or more 4709 pairs of strings: 4710 4711 SourceSignature 'auto/*.c' => 'content', 4712 '*' => 'stored-content'; 4713 4714 The first string in each pair is a pattern to match against derived file 4715 path names. The pattern is a file-globbing pattern, not a Perl regular 4716 expression; the pattern <*.l> will match all Lex source files. The C<*> 4717 wildcard will match across directory separators; the pattern C<foo/*.c> 4718 would match all C source files in any subdirectory underneath the C<foo> 4719 subdirectory. 4720 4721 The second string in each pair contains one of the following keywords to 4722 specify how signatures should be calculated for source files that match 4723 the pattern. The available keywords are: 4724 4725 =over 4 4726 4727 =item content 4728 4729 Use the content signature of the source file when calculating signatures 4730 of files that depend on it. This guarantees correct calculation of the 4731 file's signature for all builds, by telling Cons to read the contents of 4732 a source file to calculate its content signature each time it is run. 4733 4734 =item stored-content 4735 4736 Use the source file's content signature as stored in the F<.consign> 4737 file, provided the file's timestamp matches the cached timestamp value 4738 in the F<.consign> file. This optimizes performance, with the slight 4739 risk of an incorrect build if a source file's contents have been changed 4740 so quickly after its previous update that the timestamp still matches 4741 the stored timestamp in the F<.consign> file even though the contents 4742 have changed. 4743 4744 =back 4745 4746 The Cons default behavior of always calculating a source file's 4747 signature from the file's contents is equivalent to specifying: 4748 4749 SourceSignature '*' => 'content'; 4750 4751 The C<*> will match all source files. The C<content> keyword 4752 specifies that Cons will read the contents of a source file to calculate 4753 its signature each time it is run. 4754 4755 A useful global performance optimization is: 4756 4757 SourceSignature '*' => 'stored-content'; 4758 4759 This specifies that Cons will use pre-computed content signatures 4760 from F<.consign> files, when available, rather than re-calculating a 4761 signature from the the source file's contents each time Cons is run. In 4762 practice, this is safe for most build situations, and only a problem 4763 when source files are changed automatically (by scripts, for example). 4764 The Cons default, however, errs on the side of guaranteeing a correct 4765 build in all situations. 4766 4767 Cons tries to match source file path names against the patterns in the 4768 order they are specified in the C<SourceSignature> arguments: 4769 4770 SourceSignature '/usr/repository/objects/*' => 'stored-content', 4771 '/usr/repository/*' => 'content', 4772 '*.y' => 'content', 4773 '*' => 'stored-content'; 4774 4775 In this example, all source files under the F</usr/repository/objects> 4776 directory will use F<.consign> file content signatures, source files 4777 anywhere else underneath F</usr/repository> will not use F<.consign> 4778 signature values, all Yacc source files (C<*.y>) anywhere else will not 4779 use F<.consign> signature values, and any other source file will use 4780 F<.consign> signature values. 4781 4782 4783 =head2 Derived-file signature configuration 4784 4785 Cons provides a C<SIGNATURE> construction variable that allows you to 4786 configure how signatures are calculated for any derived file when its 4787 signature is being used to decide if a dependent file is up-to-date. 4788 The value of the C<SIGNATURE> construction variable is a Perl array 4789 reference that holds one or more pairs of strings, like the arguments to 4790 the C<SourceSignature> method. 4791 4792 The first string in each pair is a pattern to match against derived file 4793 path names. The pattern is a file-globbing pattern, not a Perl regular 4794 expression; the pattern `*.obj' will match all (Win32) object files. 4795 The C<*> wildcard will match across directory separators; the pattern 4796 `foo/*.a' would match all (UNIX) library archives in any subdirectory 4797 underneath the foo subdirectory. 4798 4799 The second string in each pair contains one of the following keywords 4800 to specify how signatures should be calculated for derived files that 4801 match the pattern. The available keywords are the same as for the 4802 C<SourceSignature> method, with an additional keyword: 4803 4804 =over 4 4805 4806 =item build 4807 4808 Use the build signature of the derived file when calculating signatures 4809 of files that depend on it. This guarantees correct builds by forcing 4810 Cons to rebuild any and all files that depend on the derived file. 4811 4812 =item content 4813 4814 Use the content signature of the derived file when calculating signatures 4815 of files that depend on it. This guarantees correct calculation of the 4816 file's signature for all builds, by telling Cons to read the contents of 4817 a derived file to calculate its content signature each time it is run. 4818 4819 =item stored-content 4820 4821 Use the derived file's content signature as stored in the F<.consign> 4822 file, provided the file's timestamp matches the cached timestamp value 4823 in the F<.consign> file. This optimizes performance, with the slight 4824 risk of an incorrect build if a derived file's contents have been 4825 changed so quickly after a Cons build that the file's timestamp still 4826 matches the stored timestamp in the F<.consign> file. 4827 4828 =back 4829 4830 The Cons default behavior (as previously described) for using 4831 derived-file signatures is equivalent to: 4832 4833 $env = new cons(SIGNATURE => ['*' => 'build']); 4834 4835 The C<*> will match all derived files. The C<build> keyword specifies 4836 that all derived files' build signatures will be used when calculating 4837 whether a dependent file is up-to-date. 4838 4839 A useful alternative default C<SIGNATURE> configuration for many sites: 4840 4841 $env = new cons(SIGNATURE => ['*' => 'content']); 4842 4843 In this configuration, derived files have their signatures calculated 4844 from the file contents. This adds slightly to Cons' workload, but has 4845 the useful effect of "stopping" further rebuilds if a derived file is 4846 rebuilt to exactly the same file contents as before, which usually 4847 outweighs the additional computation Cons must perform. 4848 4849 For example, changing a comment in a C file and recompiling should 4850 generate the exact same object file (assuming the compiler doesn't 4851 insert a timestamp in the object file's header). In that case, 4852 specifying C<content> or C<stored-content> for the signature calculation 4853 will cause Cons to recognize that the object file did not actually 4854 change as a result of being rebuilt, and libraries or programs that 4855 include the object file will not be rebuilt. When C<build> is 4856 specified, however, Cons will only "know" that the object file was 4857 rebuilt, and proceed to rebuild any additional files that include the 4858 object file. 4859 4860 Note that Cons tries to match derived file path names against the 4861 patterns in the order they are specified in the C<SIGNATURE> array 4862 reference: 4863 4864 $env = new cons(SIGNATURE => ['foo/*.o' => 'build', 4865 '*.o' => 'content', 4866 '*.a' => 'stored-content', 4867 '*' => 'content']); 4868 4869 In this example, all object files underneath the F<foo> subdirectory 4870 will use build signatures, all other object files (including object 4871 files underneath other subdirectories!) will use F<.consign> file 4872 content signatures, libraries will use F<.consign> file build 4873 signatures, and all other derived files will use content signatures. 4874 4875 4876 =head2 Debugging signature calculation 4877 4878 Cons provides a C<-S> option that can be used to specify what internal 4879 Perl package Cons should use to calculate signatures. The default Cons 4880 behavior is equivalent to specifying C<-S md5> on the command line. 4881 4882 The only other package (currently) available is an C<md5::debug> 4883 package that prints out detailed information about the MD5 signature 4884 calculations performed by Cons: 4885 4886 % cons -S md5::debug hello 4887 sig::md5::srcsig(hello.c) 4888 => |52d891204c62fe93ecb95281e1571938| 4889 sig::md5::collect(52d891204c62fe93ecb95281e1571938) 4890 => |fb0660af4002c40461a2f01fbb5ffd03| 4891 sig::md5::collect(52d891204c62fe93ecb95281e1571938, 4892 fb0660af4002c40461a2f01fbb5ffd03, 4893 cc -c %< -o %>) 4894 => |f7128da6c3fe3c377dc22ade70647b39| 4895 sig::md5::current(|| 4896 eq |f7128da6c3fe3c377dc22ade70647b39|) 4897 cc -c hello.c -o hello.o 4898 sig::md5::collect() 4899 => |d41d8cd98f00b204e9800998ecf8427e| 4900 sig::md5::collect(f7128da6c3fe3c377dc22ade70647b39, 4901 d41d8cd98f00b204e9800998ecf8427e, 4902 cc -o %> %< ) 4903 => |a0bdce7fd09e0350e7efbbdb043a00b0| 4904 sig::md5::current(|| 4905 eq |a0bdce7fd09e0350e7efbbdb043a00b0|) 4906 cc -o hello, hello.o 4907 4908 4909 =head1 Code Repositories 4910 4911 Many software development organizations will have one or more central 4912 repository directory trees containing the current source code for one or 4913 more projects, as well as the derived object files, libraries, and 4914 executables. In order to reduce unnecessary recompilation, it is useful to 4915 use files from the repository to build development software--assuming, of 4916 course, that no newer dependency file exists in the local build tree. 4917 4918 4919 =head2 Repository 4920 4921 Cons provides a mechanism to specify a list of code repositories that will 4922 be searched, in-order, for source files and derived files not found in the 4923 local build directory tree. 4924 4925 The following lines in a F<Construct> file will instruct Cons to look first 4926 under the F</usr/experiment/repository> directory and then under the 4927 F</usr/product/repository> directory: 4928 4929 Repository qw ( 4930 /usr/experiment/repository 4931 /usr/product/repository 4932 ); 4933 4934 The repository directories specified may contain source files, derived files 4935 (objects, libraries and executables), or both. If there is no local file 4936 (source or derived) under the directory in which Cons is executed, then the 4937 first copy of a same-named file found under a repository directory will be 4938 used to build any local derived files. 4939 4940 Cons maintains one global list of repositories directories. Cons will 4941 eliminate the current directory, and any non-existent directories, from the 4942 list. 4943 4944 4945 =head2 Finding the Construct file in a Repository 4946 4947 Cons will also search for F<Construct> and F<Conscript> files in the 4948 repository tree or trees. This leads to a chicken-and-egg situation, 4949 though: how do you look in a repository tree for a F<Construct> file if the 4950 F<Construct> file tells you where the repository is? To get around this, 4951 repositories may be specified via C<-R> options on the command line: 4952 4953 % cons -R /usr/experiment/repository -R /usr/product/repository . 4954 4955 Any repository directories specified in the F<Construct> or F<Conscript> 4956 files will be appended to the repository directories specified by 4957 command-line C<-R> options. 4958 4959 =head2 Repository source files 4960 4961 If the source code (include the F<Conscript> file) for the library version 4962 of the I<Hello, World!> C application is in a repository (with no derived 4963 files), Cons will use the repository source files to create the local object 4964 files and executable file: 4965 4966 % cons -R /usr/src_only/repository hello 4967 gcc -c /usr/src_only/repository/hello.c -o hello.o 4968 gcc -c /usr/src_only/repository/world.c -o world.o 4969 ar r libworld.a world.o 4970 ar: creating libworld.a 4971 ranlib libworld.a 4972 gcc -o hello hello.o libworld.a 4973 4974 Creating a local source file will cause Cons to rebuild the appropriate 4975 derived file or files: 4976 4977 % pico world.c 4978 [EDIT] 4979 % cons -R /usr/src_only/repository hello 4980 gcc -c world.c -o world.o 4981 ar r libworld.a world.o 4982 ar: creating libworld.a 4983 ranlib libworld.a 4984 gcc -o hello hello.o libworld.a 4985 4986 And removing the local source file will cause Cons to revert back to 4987 building the derived files from the repository source: 4988 4989 % rm world.c 4990 % cons -R /usr/src_only/repository hello 4991 gcc -c /usr/src_only/repository/world.c -o world.o 4992 ar r libworld.a world.o 4993 ar: creating libworld.a 4994 ranlib libworld.a 4995 gcc -o hello hello.o libworld.a 4996 4997 4998 =head2 Repository derived files 4999 5000 If a repository tree contains derived files (usually object files, 5001 libraries, or executables), Cons will perform its normal signature 5002 calculation to decide whether the repository file is up-to-date or a derived 5003 file must be built locally. This means that, in order to ensure correct 5004 signature calculation, a repository tree must also contain the F<.consign> 5005 files that were created by Cons when generating the derived files. 5006 5007 This would usually be accomplished by building the software in the 5008 repository (or, alternatively, in a build directory, and then copying the 5009 result to the repository): 5010 5011 % cd /usr/all/repository 5012 % cons hello 5013 gcc -c hello.c -o hello.o 5014 gcc -c world.c -o world.o 5015 ar r libworld.a world.o 5016 ar: creating libworld.a 5017 ranlib libworld.a 5018 gcc -o hello hello.o libworld.a 5019 5020 (This is safe even if the F<Construct> file lists the F</usr/all/repository> 5021 directory in a C<Repository> command because Cons will remove the current 5022 directory from the repository list.) 5023 5024 Now if we want to build a copy of the application with our own F<hello.c> 5025 file, we only need to create the one necessary source file, and use the 5026 C<-R> option to have Cons use other files from the repository: 5027 5028 % mkdir $HOME/build1 5029 % cd $HOME/build1 5030 % ed hello.c 5031 [EDIT] 5032 % cons -R /usr/all/repository hello 5033 gcc -c hello.c -o hello.o 5034 gcc -o hello hello.o /usr/all/repository/libworld.a 5035 5036 Notice that Cons has not bothered to recreate a local F<libworld.a> library 5037 (or recompile the F<world.o> module), but instead uses the already-compiled 5038 version from the repository. 5039 5040 Because the MD5 signatures that Cons puts in the F<.consign> file contain 5041 timestamps for the derived files, the signature timestamps must match the 5042 file timestamps for a signature to be considered valid. 5043 5044 Some software systems may alter the timestamps on repository files (by 5045 copying them, e.g.), in which case Cons will, by default, assume the 5046 repository signatures are invalid and rebuild files unnecessarily. This 5047 behavior may be altered by specifying: 5048 5049 Repository_Sig_Times_OK 0; 5050 5051 This tells Cons to ignore timestamps when deciding whether a signature is 5052 valid. (Note that avoiding this sanity check means there must be proper 5053 control over the repository tree to ensure that the derived files cannot be 5054 modified without updating the F<.consign> signature.) 5055 5056 5057 =head2 Local copies of files 5058 5059 If the repository tree contains the complete results of a build, and we try 5060 to build from the repository without any files in our local tree, something 5061 moderately surprising happens: 5062 5063 % mkdir $HOME/build2 5064 % cd $HOME/build2 5065 % cons -R /usr/all/repository hello 5066 cons: "hello" is up-to-date. 5067 5068 Why does Cons say that the F<hello> program is up-to-date when there is no 5069 F<hello> program in the local build directory? Because the repository (not 5070 the local directory) contains the up-to-date F<hello> program, and Cons 5071 correctly determines that nothing needs to be done to rebuild this 5072 up-to-date copy of the file. 5073 5074 There are, however, many times in which it is appropriate to ensure that a 5075 local copy of a file always exists. A packaging or testing script, for 5076 example, may assume that certain generated files exist locally. Instead of 5077 making these subsidiary scripts aware of the repository directory, the 5078 C<Local> command may be added to a F<Construct> or F<Conscript> file to 5079 specify that a certain file or files must appear in the local build 5080 directory: 5081 5082 Local qw( 5083 hello 5084 ); 5085 5086 Then, if we re-run the same command, Cons will make a local copy of the 5087 program from the repository copy (telling you that it is doing so): 5088 5089 % cons -R /usr/all/repository hello 5090 Local copy of hello from /usr/all/repository/hello 5091 cons: "hello" is up-to-date. 5092 5093 Notice that, because the act of making the local copy is not considered a 5094 "build" of the F<hello> file, Cons still reports that it is up-to-date. 5095 5096 Creating local copies is most useful for files that are being installed into 5097 an intermediate directory (for sharing with other directories) via the 5098 C<Install> command. Accompanying the C<Install> command for a file with a 5099 companion C<Local> command is so common that Cons provides a 5100 C<Install_Local> command as a convenient way to do both: 5101 5102 Install_Local $env, '#export', 'hello'; 5103 5104 is exactly equivalent to: 5105 5106 Install $env '#export', 'hello'; 5107 Local '#export/hello'; 5108 5109 Both the C<Local> and C<Install_Local> commands update the local F<.consign> 5110 file with the appropriate file signatures, so that future builds are 5111 performed correctly. 5112 5113 5114 =head2 Repository dependency analysis 5115 5116 Due to its built-in scanning, Cons will search the specified repository 5117 trees for included F<.h> files. Unless the compiler also knows about the 5118 repository trees, though, it will be unable to find F<.h> files that only 5119 exist in a repository. If, for example, the F<hello.c> file includes the 5120 F<hello.h> file in its current directory: 5121 5122 % cons -R /usr/all/repository hello 5123 gcc -c /usr/all/repository/hello.c -o hello.o 5124 /usr/all/repository/hello.c:1: hello.h: No such file or directory 5125 5126 Solving this problem forces some requirements onto the way construction 5127 environments are defined and onto the way the C C<#include> preprocessor 5128 directive is used to include files. 5129 5130 In order to inform the compiler about the repository trees, Cons will add 5131 appropriate C<-I> flags to the compilation commands. This means that the 5132 C<CPPPATH> variable in the construction environment must explicitly specify 5133 all subdirectories which are to be searched for included files, including the 5134 current directory. Consequently, we can fix the above example by changing 5135 the environment creation in the F<Construct> file as follows: 5136 5137 $env = new cons( 5138 CC => 'gcc', 5139 CPPPATH => '.', 5140 LIBS => 'libworld.a', 5141 ); 5142 5143 Due to the definition of the C<CPPPATH> variable, this yields, when we 5144 re-execute the command: 5145 5146 % cons -R /usr/all/repository hello 5147 gcc -c -I. -I/usr/all/repository /usr/all/repository/hello.c -o hello.o 5148 gcc -o hello hello.o /usr/all/repository/libworld.a 5149 5150 The order of the C<-I> flags replicates, for the C preprocessor, the same 5151 repository-directory search path that Cons uses for its own dependency 5152 analysis. If there are multiple repositories and multiple C<CPPPATH> 5153 directories, Cons will append the repository directories to the beginning of 5154 each C<CPPPATH> directory, rapidly multiplying the number of C<-I> flags. 5155 As an extreme example, a F<Construct> file containing: 5156 5157 Repository qw( 5158 /u1 5159 /u2 5160 ); 5161 5162 $env = new cons( 5163 CPPPATH => 'a:b:c', 5164 ); 5165 5166 Would yield a compilation command of: 5167 5168 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 5169 5170 In order to shorten the command lines as much as possible, Cons will 5171 remove C<-I> flags for any directories, locally or in the repositories, 5172 which do not actually exist. (Note that the C<-I> flags are not included 5173 in the MD5 signature calculation for the target file, so the target will 5174 not be recompiled if the compilation command changes due to a directory 5175 coming into existence.) 5176 5177 Because Cons relies on the compiler's C<-I> flags to communicate the 5178 order in which repository directories must be searched, Cons' handling 5179 of repository directories is fundamentally incompatible with using 5180 double-quotes on the C<#include> directives in any C source code that 5181 you plan to modify: 5182 5183 #include "file.h" /* DON'T USE DOUBLE-QUOTES LIKE THIS */ 5184 5185 This is because most C preprocessors, when faced with such a directive, will 5186 always first search the directory containing the source file. This 5187 undermines the elaborate C<-I> options that Cons constructs to make the 5188 preprocessor conform to its preferred search path. 5189 5190 Consequently, when using repository trees in Cons, B<always> use 5191 angle-brackets for included files in any C source (.c or .h) files that 5192 you plan to modify locally: 5193 5194 #include <file.h> /* USE ANGLE-BRACKETS INSTEAD */ 5195 5196 Code that will not change can still safely use double quotes on #include 5197 lines. 5198 5199 5200 =head2 Repository_List 5201 5202 Cons provides a C<Repository_List> command to return a list of all 5203 repository directories in their current search order. This can be used for 5204 debugging, or to do more complex Perl stuff: 5205 5206 @list = Repository_List; 5207 print join(' ', @list), "\n"; 5208 5209 5210 =head2 Repository interaction with other Cons features 5211 5212 Cons' handling of repository trees interacts correctly with other Cons 5213 features--which is to say, it generally does what you would expect. 5214 5215 Most notably, repository trees interact correctly, and rather powerfully, 5216 with the 'Link' command. A repository tree may contain one or more 5217 subdirectories for version builds established via C<Link> to a source 5218 subdirectory. Cons will search for derived files in the appropriate build 5219 subdirectories under the repository tree. 5220 5221 5222 =head1 Default targets 5223 5224 Until now, we've demonstrated invoking Cons with an explicit target 5225 to build: 5226 5227 % cons hello 5228 5229 Normally, Cons does not build anything unless a target is specified, 5230 but specifying '.' (the current directory) will build everything: 5231 5232 % cons # does not build anything 5233 5234 % cons . # builds everything under the top-level directory 5235 5236 Adding the C<Default> method to any F<Construct> or F<Conscript> file will add 5237 the specified targets to a list of default targets. Cons will build 5238 these defaults if there are no targets specified on the command line. 5239 So adding the following line to the top-level F<Construct> file will mimic 5240 Make's typical behavior of building everything by default: 5241 5242 Default '.'; 5243 5244 The following would add the F<hello> and F<goodbye> commands (in the 5245 same directory as the F<Construct> or F<Conscript> file) to the default list: 5246 5247 Default qw( 5248 hello 5249 goodbye 5250 ); 5251 5252 The C<Default> method may be used more than once to add targets to the 5253 default list. 5254 5255 =head1 Selective builds 5256 5257 Cons provides two methods for reducing the size of given build. The first is 5258 by specifying targets on the command line, and the second is a method for 5259 pruning the build tree. We'll consider target specification first. 5260 5261 5262 =head2 Selective targeting 5263 5264 Like make, Cons allows the specification of ``targets'' on the command 5265 line. Cons targets may be either files or directories. When a directory is 5266 specified, this is simply a short-hand notation for every derivable 5267 product--that Cons knows about--in the specified directory and below. For 5268 example: 5269 5270 % cons build/hello/hello.o 5271 5272 means build F<hello.o> and everything that F<hello.o> might need. This is 5273 from a previous version of the B<Hello, World!> program in which F<hello.o> 5274 depended upon F<export/include/world.h>. If that file is not up-to-date 5275 (because someone modified F<src/world/world.h)>, then it will be rebuilt, 5276 even though it is in a directory remote from F<build/hello>. 5277 5278 In this example: 5279 5280 % cons build 5281 5282 Everything in the F<build> directory is built, if necessary. Again, this may 5283 cause more files to be built. In particular, both F<export/include/world.h> 5284 and F<export/lib/libworld.a> are required by the F<build/hello> directory, 5285 and so they will be built if they are out-of-date. 5286 5287 If we do, instead: 5288 5289 % cons export 5290 5291 then only the files that should be installed in the export directory will be 5292 rebuilt, if necessary, and then installed there. Note that C<cons build> 5293 might build files that C<cons export> doesn't build, and vice-versa. 5294 5295 5296 =head2 No ``special'' targets 5297 5298 With Cons, make-style ``special'' targets are not required. The simplest 5299 analog with Cons is to use special F<export> directories, instead. Let's 5300 suppose, for example, that you have a whole series of unit tests that are 5301 associated with your code. The tests live in the source directory near the 5302 code. Normally, however, you don't want to build these tests. One solution 5303 is to provide all the build instructions for creating the tests, and then to 5304 install the tests into a separate part of the tree. If we install the tests 5305 in a top-level directory called F<tests>, then: 5306 5307 % cons tests 5308 5309 will build all the tests. 5310 5311 % cons export 5312 5313 will build the production version of the system (but not the tests), and: 5314 5315 % cons build 5316 5317 should probably be avoided (since it will compile tests unnecessarily). 5318 5319 If you want to build just a single test, then you could explicitly name the 5320 test (in either the F<tests> directory or the F<build> directory). You could 5321 also aggregate the tests into a convenient hierarchy within the tests 5322 directory. This hierarchy need not necessarily match the source hierarchy, 5323 in much the same manner that the include hierarchy probably doesn't match 5324 the source hierarchy (the include hierarchy is unlikely to be more than two 5325 levels deep, for C programs). 5326 5327 If you want to build absolutely everything in the tree (subject to whatever 5328 options you select), you can use: 5329 5330 % cons . 5331 5332 This is not particularly efficient, since it will redundantly walk all the 5333 trees, including the source tree. The source tree, of course, may have 5334 buildable objects in it--nothing stops you from doing this, even if you 5335 normally build in a separate build tree. 5336 5337 5338 =head1 Build Pruning 5339 5340 In conjunction with target selection, B<build pruning> can be used to reduce 5341 the scope of the build. In the previous peAcH and baNaNa example, we have 5342 already seen how script-driven build pruning can be used to make only half 5343 of the potential build available for any given invocation of C<cons>. Cons 5344 also provides, as a convenience, a command line convention that allows you 5345 to specify which F<Conscript> files actually get ``built''--that is, 5346 incorporated into the build tree. For example: 5347 5348 % cons build +world 5349 5350 The C<+> argument introduces a Perl regular expression. This must, of 5351 course, be quoted at the shell level if there are any shell meta-characters 5352 within the expression. The expression is matched against each F<Conscript> 5353 file which has been mentioned in a C<Build> statement, and only those 5354 scripts with matching names are actually incorporated into the build 5355 tree. Multiple such arguments are allowed, in which case a match against any 5356 of them is sufficient to cause a script to be included. 5357 5358 In the example, above, the F<hello> program will not be built, since Cons 5359 will have no knowledge of the script F<hello/Conscript>. The F<libworld.a> 5360 archive will be built, however, if need be. 5361 5362 There are a couple of uses for build pruning via the command line. Perhaps 5363 the most useful is the ability to make local changes, and then, with 5364 sufficient knowledge of the consequences of those changes, restrict the size 5365 of the build tree in order to speed up the rebuild time. A second use for 5366 build pruning is to actively prevent the recompilation of certain files that 5367 you know will recompile due to, for example, a modified header file. You may 5368 know that either the changes to the header file are immaterial, or that the 5369 changes may be safely ignored for most of the tree, for testing 5370 purposes.With Cons, the view is that it is pragmatic to admit this type of 5371 behavior, with the understanding that on the next full build everything that 5372 needs to be rebuilt will be. There is no equivalent to a ``make touch'' 5373 command, to mark files as permanently up-to-date. So any risk that is 5374 incurred by build pruning is mitigated. For release quality work, obviously, 5375 we recommend that you do not use build pruning (it's perfectly OK to use 5376 during integration, however, for checking compilation, etc. Just be sure to 5377 do an unconstrained build before committing the integration). 5378 5379 5380 =head1 Temporary overrides 5381 5382 Cons provides a very simple mechanism for overriding aspects of a build. The 5383 essence is that you write an override file containing one or more 5384 C<Override> commands, and you specify this on the command line, when you run 5385 C<cons>: 5386 5387 % cons -o over export 5388 5389 will build the F<export> directory, with all derived files subject to the 5390 overrides present in the F<over> file. If you leave out the C<-o> option, 5391 then everything necessary to remove all overrides will be rebuilt. 5392 5393 5394 =head2 Overriding environment variables 5395 5396 The override file can contain two types of overrides. The first is incoming 5397 environment variables. These are normally accessible by the F<Construct> 5398 file from the C<%ENV> hash variable. These can trivially be overridden in 5399 the override file by setting the appropriate elements of C<%ENV> (these 5400 could also be overridden in the user's environment, of course). 5401 5402 5403 =head2 The Override command 5404 5405 The second type of override is accomplished with the C<Override> command, 5406 which looks like this: 5407 5408 Override <regexp>, <var1> => <value1>, <var2> => <value2>, ...; 5409 5410 The regular expression I<regexp> is matched against every derived file that 5411 is a candidate for the build. If the derived file matches, then the 5412 variable/value pairs are used to override the values in the construction 5413 environment associated with the derived file. 5414 5415 Let's suppose that we have a construction environment like this: 5416 5417 $CONS = new cons( 5418 COPT => '', 5419 CDBG => '-g', 5420 CFLAGS => '%COPT %CDBG', 5421 ); 5422 5423 Then if we have an override file F<over> containing this command: 5424 5425 Override '\.o$', COPT => '-O', CDBG => ''; 5426 5427 then any C<cons> invocation with C<-o over> that creates F<.o> files via 5428 this environment will cause them to be compiled with C<-O >and no C<-g>. The 5429 override could, of course, be restricted to a single directory by the 5430 appropriate selection of a regular expression. 5431 5432 Here's the original version of the Hello, World! program, built with this 5433 environment. Note that Cons rebuilds the appropriate pieces when the 5434 override is applied or removed: 5435 5436 % cons hello 5437 cc -g -c hello.c -o hello.o 5438 cc -o hello hello.o 5439 % cons -o over hello 5440 cc -O -c hello.c -o hello.o 5441 cc -o hello hello.o 5442 % cons -o over hello 5443 cons: "hello" is up-to-date. 5444 % cons hello 5445 cc -g -c hello.c -o hello.o 5446 cc -o hello hello.o 5447 5448 It's important that the C<Override> command only be used for temporary, 5449 on-the-fly overrides necessary for development because the overrides are not 5450 platform independent and because they rely too much on intimate knowledge of 5451 the workings of the scripts. For temporary use, however, they are exactly 5452 what you want. 5453 5454 Note that it is still useful to provide, say, the ability to create a fully 5455 optimized version of a system for production use--from the F<Construct> and 5456 F<Conscript> files. This way you can tailor the optimized system to the 5457 platform. Where optimizer trade-offs need to be made (particular files may 5458 not be compiled with full optimization, for example), then these can be 5459 recorded for posterity (and reproducibility) directly in the scripts. 5460 5461 5462 =head1 More on construction environments 5463 5464 As previously mentioned, a B<construction environment> is an object that 5465 has a set of keyword/value pairs and a set of methods, and which is used 5466 to tell Cons how target files should be built. This section describes 5467 how Cons uses and expands construction environment values to control its 5468 build behavior. 5469 5470 =head2 Construction variable expansion 5471 5472 Construction variables from a construction environment are expanded 5473 by preceding the keyword with a C<%> (percent sign): 5474 5475 Construction variables: 5476 XYZZY => 'abracadabra', 5477 5478 The string: "The magic word is: %XYZZY!" 5479 expands to: "The magic word is: abracadabra!" 5480 5481 A construction variable name may be surrounded by C<{> and C<}> (curly 5482 braces), which are stripped as part of the expansion. This can 5483 sometimes be necessary to separate a variable expansion from trailing 5484 alphanumeric characters: 5485 5486 Construction variables: 5487 OPT => 'value1', 5488 OPTION => 'value2', 5489 5490 The string: "%OPT %{OPT}ION %OPTION %{OPTION}" 5491 expands to: "value1 value1ION value2 value2" 5492 5493 Construction variable expansion is recursive--that is, a string 5494 containing C<%->expansions after substitution will be re-expanded until 5495 no further substitutions can be made: 5496 5497 Construction variables: 5498 STRING => 'The result is: %FOO', 5499 FOO => '%BAR', 5500 BAR => 'final value', 5501 5502 The string: "The string says: %STRING" 5503 expands to: "The string says: The result is: final value" 5504 5505 If a construction variable is not defined in an environment, then the 5506 null string is substituted: 5507 5508 Construction variables: 5509 FOO => 'value1', 5510 BAR => 'value2', 5511 5512 The string: "%FOO <%NO_VARIABLE> %BAR" 5513 expands to: "value1 <> value2" 5514 5515 A doubled C<%%> will be replaced by a single C<%>: 5516 5517 The string: "Here is a percent sign: %%" 5518 expands to: "Here is a percent sign: %" 5519 5520 =head2 Default construction variables 5521 5522 When you specify no arguments when creating a new construction 5523 environment: 5524 5525 $env = new cons(); 5526 5527 Cons creates a reference to a new, default construction 5528 environment. This contains a number of construction variables and some 5529 methods. At the present writing, the default construction variables on a 5530 UNIX system are: 5531 5532 CC => 'cc', 5533 CFLAGS => '', 5534 CCCOM => '%CC %CFLAGS %_IFLAGS -c %< -o %>', 5535 CXX => '%CC', 5536 CXXFLAGS => '%CFLAGS', 5537 CXXCOM => '%CXX %CXXFLAGS %_IFLAGS -c %< -o %>', 5538 INCDIRPREFIX => '-I', 5539 INCDIRSUFFIX => '', 5540 LINK => '%CXX', 5541 LINKCOM => '%LINK %LDFLAGS -o %> %< %_LDIRS %LIBS', 5542 LINKMODULECOM => '%LD -r -o %> %<', 5543 LIBDIRPREFIX => '-L', 5544 LIBDIRSUFFIX => '', 5545 AR => 'ar', 5546 ARFLAGS => 'r', 5547 ARCOM => ['%AR %ARFLAGS %> %<', '%RANLIB %>'], 5548 RANLIB => 'ranlib', 5549 AS => 'as', 5550 ASFLAGS => '', 5551 ASCOM => '%AS %ASFLAGS %< -o %>', 5552 LD => 'ld', 5553 LDFLAGS => '', 5554 PREFLIB => 'lib', 5555 SUFLIB => '.a', 5556 SUFLIBS => '.so:.a', 5557 SUFOBJ => '.o', 5558 SIGNATURE => [ '*' => 'build' ], 5559 ENV => { 'PATH' => '/bin:/usr/bin' }, 5560 5561 5562 And on a Win32 system (Windows NT), the default construction variables 5563 are (unless the default rule style is set using the B<DefaultRules> 5564 method): 5565 5566 CC => 'cl', 5567 CFLAGS => '/nologo', 5568 CCCOM => '%CC %CFLAGS %_IFLAGS /c %< /Fo%>', 5569 CXXCOM => '%CXX %CXXFLAGS %_IFLAGS /c %< /Fo%>', 5570 INCDIRPREFIX => '/I', 5571 INCDIRSUFFIX => '', 5572 LINK => 'link', 5573 LINKCOM => '%LINK %LDFLAGS /out:%> %< %_LDIRS %LIBS', 5574 LINKMODULECOM => '%LD /r /o %> %<', 5575 LIBDIRPREFIX => '/LIBPATH:', 5576 LIBDIRSUFFIX => '', 5577 AR => 'lib', 5578 ARFLAGS => '/nologo ', 5579 ARCOM => "%AR %ARFLAGS /out:%> %<", 5580 RANLIB => '', 5581 LD => 'link', 5582 LDFLAGS => '/nologo ', 5583 PREFLIB => '', 5584 SUFEXE => '.exe', 5585 SUFLIB => '.lib', 5586 SUFLIBS => '.dll:.lib', 5587 SUFOBJ => '.obj', 5588 SIGNATURE => [ '*' => 'build' ], 5589 5590 These variables are used by the various methods associated with the 5591 environment. In particular, any method that ultimately invokes an external 5592 command will substitute these variables into the final command, as 5593 appropriate. For example, the C<Objects> method takes a number of source 5594 files and arranges to derive, if necessary, the corresponding object 5595 files: 5596 5597 Objects $env 'foo.c', 'bar.c'; 5598 5599 This will arrange to produce, if necessary, F<foo.o> and F<bar.o>. The 5600 command invoked is simply C<%CCCOM>, which expands, through substitution, 5601 to the appropriate external command required to build each object. The 5602 substitution rules will be discussed in detail in the next section. 5603 5604 The construction variables are also used for other purposes. For example, 5605 C<CPPPATH> is used to specify a colon-separated path of include 5606 directories. These are intended to be passed to the C preprocessor and are 5607 also used by the C-file scanning machinery to determine the dependencies 5608 involved in a C Compilation. 5609 5610 Variables beginning with underscore are created by various methods, 5611 and should normally be considered ``internal'' variables. For example, 5612 when a method is called which calls for the creation of an object from 5613 a C source, the variable C<_IFLAGS> is created: this corresponds to the 5614 C<-I> switches required by the C compiler to represent the directories 5615 specified by C<CPPPATH>. 5616 5617 Note that, for any particular environment, the value of a variable is set 5618 once, and then never reset (to change a variable, you must create a new 5619 environment. Methods are provided for copying existing environments for this 5620 purpose). Some internal variables, such as C<_IFLAGS> are created on demand, 5621 but once set, they remain fixed for the life of the environment. 5622 5623 The C<CFLAGS>, C<LDFLAGS>, and C<ARFLAGS> variables all supply a place 5624 for passing options to the compiler, loader, and archiver, respectively. 5625 5626 The C<INCDIRPREFIX> and C<INCDIRSUFFIX> variables specify option 5627 strings to be appended to the beginning and end, respectively, of each 5628 include directory so that the compiler knows where to find F<.h> files. 5629 Similarly, the C<LIBDIRPREFIX> and C<LIBDIRSUFFIX> variables specify the 5630 option string to be appended to the beginning of and end, respectively, 5631 of each directory that the linker should search for libraries. 5632 5633 Another variable, C<ENV>, is used to determine the system environment during 5634 the execution of an external command. By default, the only environment 5635 variable that is set is C<PATH>, which is the execution path for a UNIX 5636 command. For the utmost reproducibility, you should really arrange to set 5637 your own execution path, in your top-level F<Construct> file (or perhaps by 5638 importing an appropriate construction package with the Perl C<use> 5639 command). The default variables are intended to get you off the ground. 5640 5641 =head2 Expanding variables in construction commands 5642 5643 Within a construction command, construction variables will be expanded 5644 according to the rules described above. In addition to normal variable 5645 expansion from the construction environment, construction commands also 5646 expand the following pseudo-variables to insert the specific input and 5647 output files in the command line that will be executed: 5648 5649 =over 10 5650 5651 =item %> 5652 5653 The target file name. In a multi-target command, this expands to the 5654 first target mentioned.) 5655 5656 =item %0 5657 5658 Same as C<%E<gt>>. 5659 5660 =item %1, %2, ..., %9 5661 5662 These refer to the first through ninth input file, respectively. 5663 5664 =item %E<lt> 5665 5666 The full set of input file names. If any of these have been used 5667 anywhere else in the current command line (via C<%1>, C<%2>, etc.), then 5668 those will be deleted from the list provided by C<%E<lt>>. Consider the 5669 following command found in a F<Conscript> file in the F<test> directory: 5670 5671 Command $env 'tgt', qw(foo bar baz), qq( 5672 echo %< -i %1 > %> 5673 echo %< -i %2 >> %> 5674 echo %< -i %3 >> %> 5675 ); 5676 5677 If F<tgt> needed to be updated, then this would result in the execution of 5678 the following commands, assuming that no remapping has been established for 5679 the F<test> directory: 5680 5681 echo test/bar test/baz -i test/foo > test/tgt 5682 echo test/foo test/baz -i test/bar >> test/tgt 5683 echo test/foo test/bar -i test/baz >> test/tgt 5684 5685 =back 5686 5687 Any of the above pseudo-variables may be followed immediately by one of 5688 the following suffixes to select a portion of the expanded path name: 5689 5690 :a the absolute path to the file name 5691 :b the directory plus the file name stripped of any suffix 5692 :d the directory 5693 :f the file name 5694 :s the file name suffix 5695 :F the file name stripped of any suffix 5696 :S the absolute path path to a Linked source file 5697 5698 Continuing with the above example, C<%E<lt>:f> would expand to C<foo bar baz>, 5699 and C<%E<gt>:d> would expand to C<test>. 5700 5701 There are additional C<%> elements which affect the command line(s): 5702 5703 =over 10 5704 5705 =item %[ %] 5706 5707 It is possible to programmatically rewrite part of the command by 5708 enclosing part of it between C<%[> and C<%]>. This will call the 5709 construction variable named as the first word enclosed in the brackets 5710 as a Perl code reference; the results of this call will be used to 5711 replace the contents of the brackets in the command line. For example, 5712 given an existing input file named F<tgt.in>: 5713 5714 @keywords = qw(foo bar baz); 5715 $env = new cons(X_COMMA => sub { join(",", @_) }); 5716 Command $env 'tgt', 'tgt.in', qq( 5717 echo '# Keywords: %[X_COMMA @keywords %]' > %> 5718 cat %< >> %> 5719 ); 5720 5721 This will execute: 5722 5723 echo '# Keywords: foo,bar,baz' > tgt 5724 cat tgt.in >> tgt 5725 5726 =item %( %) 5727 5728 Cons includes the text of the command line in the MD5 signature for a 5729 build, so that targets get rebuilt if you change the command line (to 5730 add or remove an option, for example). Command-line text in between 5731 C<%(> and C<%)>, however, will be ignored for MD5 signature calculation. 5732 5733 Internally, Cons uses C<%(> and C<%)> around include and library 5734 directory options (C<-I> and C<-L> on UNIX systems, C</I> and 5735 C</LIBPATH> on Windows NT) to avoid rebuilds just because the directory 5736 list changes. Rebuilds occur only if the changed directory list causes 5737 any included I<files> to change, and a changed include file is detected 5738 by the MD5 signature calculation on the actual file contents. 5739 5740 =back 5741 5742 =head2 Expanding construction variables in file names 5743 5744 Cons expands construction variables in the source and target file names 5745 passed to the various construction methods according to the expansion 5746 rules described above: 5747 5748 $env = new cons( 5749 DESTDIR => 'programs', 5750 SRCDIR => 'src', 5751 ); 5752 Program $env '%DESTDIR/hello', '%SRCDIR/hello.c'; 5753 5754 This allows for flexible configuration, through the construction 5755 environment, of directory names, suffixes, etc. 5756 5757 5758 =head1 Build actions 5759 5760 Cons supports several types of B<build actions> that can be performed 5761 to construct one or more target files. Usually, a build action is 5762 a construction command--that is, a command-line string that invokes 5763 an external command. Cons can also execute Perl code embedded in a 5764 command-line string, and even supports an experimental ability to build 5765 a target file by executing a Perl code reference directly. 5766 5767 A build action is usually specified as the value of a construction 5768 variable: 5769 5770 $env = new cons( 5771 CCCOM => '%CC %CFLAGS %_IFLAGS -c %< -o %>', 5772 LINKCOM => '[perl] &link_executable("%>", "%<")', 5773 ARCOM => sub { my($env, $target, @sources) = @_; 5774 # code to create an archive 5775 } 5776 ); 5777 5778 A build action may be associated directly with one or more target files 5779 via the C<Command> method; see below. 5780 5781 =head2 Construction commands 5782 5783 A construction command goes through expansion of construction variables 5784 and C<%-> pseudo-variables, as described above, to create the actual 5785 command line that Cons will execute to generate the target file or 5786 files. 5787 5788 After substitution occurs, strings of white space are converted into 5789 single blanks, and leading and trailing white space is eliminated. It 5790 is therefore currently not possible to introduce variable length white 5791 space in strings passed into a command. 5792 5793 If a multi-line command string is provided, the commands are executed 5794 sequentially. If any of the commands fails, then none of the rest are 5795 executed, and the target is not marked as updated, i.e. a new signature is 5796 not stored for the target. 5797 5798 Normally, if all the commands succeed, and return a zero status (or whatever 5799 platform-specific indication of success is required), then a new signature 5800 is stored for the target. If a command erroneously reports success even 5801 after a failure, then Cons will assume that the target file created by that 5802 command is accurate and up-to-date. 5803 5804 The first word of each command string, after expansion, is assumed to be an 5805 executable command looked up on the C<PATH> environment variable (which is, 5806 in turn, specified by the C<ENV> construction variable). If this command is 5807 found on the path, then the target will depend upon it: the command will 5808 therefore be automatically built, as necessary. It's possible to write 5809 multi-part commands to some shells, separated by semi-colons. Only the first 5810 command word will be depended upon, however, so if you write your command 5811 strings this way, you must either explicitly set up a dependency (with the 5812 C<Depends> method), or be sure that the command you are using is a system 5813 command which is expected to be available. If it isn't available, you will, 5814 of course, get an error. 5815 5816 Cons normally prints a command before executing it. This behavior is 5817 suppressed if the first character of the command is C<@>. Note that 5818 you may need to separate the C<@> from the command name or escape it to 5819 prevent C<@cmd> from looking like an array to Perl quote operators that 5820 perform interpolation: 5821 5822 # The first command line is incorrect, 5823 # because "@cp" looks like an array 5824 # to the Perl qq// function. 5825 # Use the second form instead. 5826 Command $env 'foo', 'foo.in', qq( 5827 @cp %< tempfile 5828 @ cp tempfile %> 5829 ); 5830 5831 If there are shell meta characters anywhere in the expanded command line, 5832 such as C<E<lt>>, C<E<gt>>, quotes, or semi-colon, then the command 5833 will actually be executed by invoking a shell. This means that a command 5834 such as: 5835 5836 cd foo 5837 5838 alone will typically fail, since there is no command C<cd> on the path. But 5839 the command string: 5840 5841 cd $<:d; tar cf $>:f $<:f 5842 5843 when expanded will still contain the shell meta character semi-colon, and a 5844 shell will be invoked to interpret the command. Since C<cd> is interpreted 5845 by this sub-shell, the command will execute as expected. 5846 5847 =head2 Perl expressions 5848 5849 If any command (even one within a multi-line command) begins with 5850 C<[perl]>, the remainder of that command line will be evaluated by the 5851 running Perl instead of being forked by the shell. If an error occurs 5852 in parsing the Perl code, or if the Perl expression returns 0 or undef, 5853 the command will be considered to have failed. For example, here is a 5854 simple command which creates a file C<foo> directly from Perl: 5855 5856 $env = new cons(); 5857 Command $env 'foo', 5858 qq([perl] open(FOO,'>foo');print FOO "hi\\n"; close(FOO); 1); 5859 5860 Note that when the command is executed, you are in the same package as 5861 when the F<Construct> or F<Conscript> file was read, so you can call 5862 Perl functions you've defined in the same F<Construct> or F<Conscript> 5863 file in which the C<Command> appears: 5864 5865 $env = new cons(); 5866 sub create_file { 5867 my $file = shift; 5868 open(FILE, ">$file"); 5869 print FILE "hi\n"; 5870 close(FILE); 5871 return 1; 5872 } 5873 Command $env 'foo', "[perl] &create_file('%>')"; 5874 5875 The Perl string will be used to generate the signature for the derived 5876 file, so if you change the string, the file will be rebuilt. The contents 5877 of any subroutines you call, however, are not part of the signature, 5878 so if you modify a called subroutine such as C<create_file> above, 5879 the target will I<not> be rebuilt. Caveat user. 5880 5881 =head2 Perl code references [EXPERIMENTAL] 5882 5883 Cons supports the ability to create a derived file by directly executing 5884 a Perl code reference. This feature is considered EXPERIMENTAL and 5885 subject to change in the future. 5886 5887 A code reference may either be a named subroutine referenced by the 5888 usual C<\&> syntax: 5889 5890 sub build_output { 5891 my($env, $target, @sources) = @_; 5892 print "build_output building $target\n"; 5893 open(OUT, ">$target"); 5894 foreach $src (@sources) { 5895 if (! open(IN, "<$src")) { 5896 print STDERR "cannot open '$src': $!\n"; 5897 return undef; 5898 } 5899 print OUT, <IN>; 5900 } 5901 close(OUT); 5902 return 1; 5903 } 5904 Command $env 'output', \&build_output; 5905 5906 or the code reference may be an anonymous subroutine: 5907 5908 Command $env 'output', sub { 5909 my($env, $target, @sources) = @_; 5910 print "building $target\n"; 5911 open(FILE, ">$target"); 5912 print FILE "hello\n"; 5913 close(FILE); 5914 return 1; 5915 }; 5916 5917 To build the target file, the referenced subroutine is passed, in order: 5918 the construction environment used to generate the target; the path 5919 name of the target itself; and the path names of all the source files 5920 necessary to build the target file. 5921 5922 The code reference is expected to generate the target file, of course, 5923 but may manipulate the source and target files in any way it chooses. 5924 The code reference must return a false value (C<undef> or C<0>) if 5925 the build of the file failed. Any true value indicates a successful 5926 build of the target. 5927 5928 Building target files using code references is considered EXPERIMENTAL 5929 due to the following current limitations: 5930 5931 =over 4 5932 5933 Cons does I<not> print anything to indicate the code reference is being 5934 called to build the file. The only way to give the user any indication 5935 is to have the code reference explicitly print some sort of "building" 5936 message, as in the above examples. 5937 5938 Cons does not generate any signatures for code references, so if the 5939 code in the reference changes, the target will I<not> be rebuilt. 5940 5941 Cons has no public method to allow a code reference to extract 5942 construction variables. This would be good to allow generalization of 5943 code references based on the current construction environment, but would 5944 also complicate the problem of generating meaningful signatures for code 5945 references. 5946 5947 =back 5948 5949 Support for building targets via code references has been released in 5950 this version to encourage experimentation and the seeking of possible 5951 solutions to the above limitations. 5952 5953 5954 =head1 Default construction methods 5955 5956 The list of default construction methods includes the following: 5957 5958 5959 =head2 The C<new> constructor 5960 5961 The C<new> method is a Perl object constructor. That is, it is not invoked 5962 via a reference to an existing construction environment B<reference>, but, 5963 rather statically, using the name of the Perl B<package> where the 5964 constructor is defined. The method is invoked like this: 5965 5966 $env = new cons(<overrides>); 5967 5968 The environment you get back is blessed into the package C<cons>, which 5969 means that it will have associated with it the default methods described 5970 below. Individual construction variables can be overridden by providing 5971 name/value pairs in an override list. Note that to override any command 5972 environment variable (i.e. anything under C<ENV>), you will have to override 5973 all of them. You can get around this difficulty by using the C<copy> method 5974 on an existing construction environment. 5975 5976 5977 =head2 The C<clone> method 5978 5979 The C<clone> method creates a clone of an existing construction environment, 5980 and can be called as in the following example: 5981 5982 $env2 = $env1->clone(<overrides>); 5983 5984 You can provide overrides in the usual manner to create a different 5985 environment from the original. If you just want a new name for the same 5986 environment (which may be helpful when exporting environments to existing 5987 components), you can just use simple assignment. 5988 5989 5990 =head2 The C<copy> method 5991 5992 The C<copy> method extracts the externally defined construction variables 5993 from an environment and returns them as a list of name/value 5994 pairs. Overrides can also be provided, in which case, the overridden values 5995 will be returned, as appropriate. The returned list can be assigned to a 5996 hash, as shown in the prototype, below, but it can also be manipulated in 5997 other ways: 5998 5999 %env = $env1->copy(<overrides>); 6000 6001 The value of C<ENV>, which is itself a hash, is also copied to a new hash, 6002 so this may be changed without fear of affecting the original 6003 environment. So, for example, if you really want to override just the 6004 C<PATH> variable in the default environment, you could do the following: 6005 6006 %cons = new cons()->copy(); 6007 $cons{ENV}{PATH} = "<your path here>"; 6008 $cons = new cons(%cons); 6009 6010 This will leave anything else that might be in the default execution 6011 environment undisturbed. 6012 6013 6014 =head2 The C<Install> method 6015 6016 The C<Install> method arranges for the specified files to be installed in 6017 the specified directory. The installation is optimized: the file is not 6018 copied if it can be linked. If this is not the desired behavior, you will 6019 need to use a different method to install the file. It is called as follows: 6020 6021 Install $env <directory>, <names>; 6022 6023 Note that, while the files to be installed may be arbitrarily named, 6024 only the last component of each name is used for the installed target 6025 name. So, for example, if you arrange to install F<foo/bar> in F<baz>, 6026 this will create a F<bar> file in the F<baz> directory (not F<foo/bar>). 6027 6028 6029 =head2 The C<InstallAs> method 6030 6031 The C<InstallAs> method arranges for the specified source file(s) to be 6032 installed as the specified target file(s). Multiple files should be 6033 specified as a file list. The installation is optimized: the file is not 6034 copied if it can be linked. If this is not the desired behavior, you will 6035 need to use a different method to install the file. It is called as follows: 6036 6037 C<InstallAs> works in two ways: 6038 6039 Single file install: 6040 6041 InstallAs $env TgtFile, SrcFile; 6042 6043 Multiple file install: 6044 6045 InstallAs $env ['tgt1', 'tgt2'], ['src1', 'src2']; 6046 6047 Or, even as: 6048 6049 @srcs = qw(src1 src2 src3); 6050 @tgts = qw(tgt1 tgt2 tgt3); 6051 InstallAs $env [@tgts], [@srcs]; 6052 6053 Both the target and the sources lists should be of the same length. 6054 6055 =head2 The C<Precious> method 6056 6057 The C<Precious> method asks cons not to delete the specified file or 6058 list of files before building them again. It is invoked as: 6059 6060 Precious <files>; 6061 6062 This is especially useful for allowing incremental updates to libraries 6063 or debug information files which are updated rather than rebuilt anew each 6064 time. Cons will still delete the files when the C<-r> flag is specified. 6065 6066 =head2 The C<AfterBuild> method 6067 6068 The C<AfterBuild> method evaluates the specified perl string after 6069 building the given file or files (or finding that they are up to date). 6070 The eval will happen once per specified file. C<AfterBuild> is called 6071 as follows: 6072 6073 AfterBuild $env 'foo.o', qq(print "foo.o is up to date!\n"); 6074 6075 The perl string is evaluated in the C<script> package, and has access 6076 to all variables and subroutines defined in the F<Conscript> file in 6077 which the C<AfterBuild> method is called. 6078 6079 =head2 The C<Command> method 6080 6081 The C<Command> method is a catchall method which can be used to arrange for 6082 any build action to be executed to update the target. For this command, a 6083 target file and list of inputs is provided. In addition, a build action 6084 is specified as the last argument. The build action is typically a 6085 command line or lines, but may also contain Perl code to be executed; 6086 see the section above on build actions for details. 6087 6088 The C<Command> method is called as follows: 6089 6090 Command $env <target>, <inputs>, <build action>; 6091 6092 The target is made dependent upon the list of input files specified, and the 6093 inputs must be built successfully or Cons will not attempt to build the 6094 target. 6095 6096 To specify a command with multiple targets, you can specify a reference to a 6097 list of targets. In Perl, a list reference can be created by enclosing a 6098 list in square brackets. Hence the following command: 6099 6100 Command $env ['foo.h', 'foo.c'], 'foo.template', q( 6101 gen %1 6102 ); 6103 6104 could be used in a case where the command C<gen> creates two files, both 6105 F<foo.h> and F<foo.c>. 6106 6107 6108 =head2 The C<Objects> method 6109 6110 The C<Objects> method arranges to create the object files that correspond to 6111 the specified source files. It is invoked as shown below: 6112 6113 @files = Objects $env <source or object files>; 6114 6115 Under Unix, source files ending in F<.s> and F<.c> are currently 6116 supported, and will be compiled into a name of the same file ending 6117 in F<.o>. By default, all files are created by invoking the external 6118 command which results from expanding the C<CCCOM> construction variable, 6119 with C<%E<lt>> and C<%E<gt>> set to the source and object files, 6120 respectively. (See the section above on construction variable expansion 6121 for details). The variable C<CPPPATH> is also used when scanning source 6122 files for dependencies. This is a colon separated list of pathnames, and 6123 is also used to create the construction variable C<_IFLAGS,> which will 6124 contain the appropriate list of -C<I> options for the compilation. Any 6125 relative pathnames in C<CPPPATH> is interpreted relative to the 6126 directory in which the associated construction environment was created 6127 (absolute and top-relative names may also be used). This variable is 6128 used by C<CCCOM>. The behavior of this command can be modified by 6129 changing any of the variables which are interpolated into C<CCCOM>, such 6130 as C<CC>, C<CFLAGS>, and, indirectly, C<CPPPATH>. It's also possible 6131 to replace the value of C<CCCOM>, itself. As a convenience, this file 6132 returns the list of object filenames. 6133 6134 6135 =head2 The C<Program> method 6136 6137 The C<Program> method arranges to link the specified program with the 6138 specified object files. It is invoked in the following manner: 6139 6140 Program $env <program name>, <source or object files>; 6141 6142 The program name will have the value of the C<SUFEXE> construction 6143 variable appended (by default, C<.exe> on Win32 systems, nothing on Unix 6144 systems) if the suffix is not already present. 6145 6146 Source files may be specified in place of objects files--the C<Objects> 6147 method will be invoked to arrange the conversion of all the files into 6148 object files, and hence all the observations about the C<Objects> method, 6149 above, apply to this method also. 6150 6151 The actual linking of the program will be handled by an external command 6152 which results from expanding the C<LINKCOM> construction variable, with 6153 C<%E<lt>> set to the object files to be linked (in the order presented), 6154 and C<%E<gt>> set to the target. (See the section above on construction 6155 variable expansion for details.) The user may set additional variables 6156 in the construction environment, including C<LINK>, to define which 6157 program to use for linking, C<LIBPATH>, a colon-separated list of 6158 library search paths, for use with library specifications of the form 6159 I<-llib>, and C<LIBS>, specifying the list of libraries to link against 6160 (in either I<-llib> form or just as pathnames. Relative pathnames in 6161 both C<LIBPATH> and C<LIBS> are interpreted relative to the directory 6162 in which the associated construction environment is created (absolute 6163 and top-relative names may also be used). Cons automatically sets up 6164 dependencies on any libraries mentioned in C<LIBS>: those libraries will 6165 be built before the command is linked. 6166 6167 6168 =head2 The C<Library> method 6169 6170 The C<Library> method arranges to create the specified library from the 6171 specified object files. It is invoked as follows: 6172 6173 Library $env <library name>, <source or object files>; 6174 6175 The library name will have the value of the C<SUFLIB> construction 6176 variable appended (by default, C<.lib> on Win32 systems, C<.a> on Unix 6177 systems) if the suffix is not already present. 6178 6179 Source files may be specified in place of objects files--the C<Objects> 6180 method will be invoked to arrange the conversion of all the files into 6181 object files, and hence all the observations about the C<Objects> method, 6182 above, apply to this method also. 6183 6184 The actual creation of the library will be handled by an external 6185 command which results from expanding the C<ARCOM> construction variable, 6186 with C<%E<lt>> set to the library members (in the order presented), 6187 and C<%E<gt>> to the library to be created. (See the section above 6188 on construction variable expansion for details.) The user may set 6189 variables in the construction environment which will affect the 6190 operation of the command. These include C<AR>, the archive program 6191 to use, C<ARFLAGS>, which can be used to modify the flags given to 6192 the program specified by C<AR>, and C<RANLIB>, the name of a archive 6193 index generation program, if needed (if the particular need does not 6194 require the latter functionality, then C<ARCOM> must be redefined to not 6195 reference C<RANLIB>). 6196 6197 The C<Library> method allows the same library to be specified in multiple 6198 method invocations. All of the contributing objects from all the invocations 6199 (which may be from different directories) are combined and generated by a 6200 single archive command. Note, however, that if you prune a build so that 6201 only part of a library is specified, then only that part of the library will 6202 be generated (the rest will disappear!). 6203 6204 6205 =head2 The C<Module> method 6206 6207 The C<Module> method is a combination of the C<Program> and C<Command> 6208 methods. Rather than generating an executable program directly, this command 6209 allows you to specify your own command to actually generate a module. The 6210 method is invoked as follows: 6211 6212 Module $env <module name>, <source or object files>, <construction command>; 6213 6214 This command is useful in instances where you wish to create, for example, 6215 dynamically loaded modules, or statically linked code libraries. 6216 6217 6218 =head2 The C<Depends> method 6219 6220 The C<Depends> method allows you to specify additional dependencies for a 6221 target. It is invoked as follows: 6222 6223 Depends $env <target>, <dependencies>; 6224 6225 This may be occasionally useful, especially in cases where no scanner exists 6226 (or is writable) for particular types of files. Normally, dependencies are 6227 calculated automatically from a combination of the explicit dependencies set 6228 up by the method invocation or by scanning source files. 6229 6230 A set of identical dependencies for multiple targets may be specified 6231 using a reference to a list of targets. In Perl, a list reference can 6232 be created by enclosing a list in square brackets. Hence the following 6233 command: 6234 6235 Depends $env ['foo', 'bar'], 'input_file_1', 'input_file_2'; 6236 6237 specifies that both the F<foo> and F<bar> files depend on the listed 6238 input files. 6239 6240 6241 =head2 The C<RuleSet> method 6242 6243 The C<RuleSet> method returns the construction variables for building 6244 various components with one of the rule sets supported by Cons. The 6245 currently supported rule sets are: 6246 6247 =over 4 6248 6249 =item msvc 6250 6251 Rules for the Microsoft Visual C++ compiler suite. 6252 6253 =item unix 6254 6255 Generic rules for most UNIX-like compiler suites. 6256 6257 =back 6258 6259 On systems with more than one available compiler suite, this allows you 6260 to easily create side-by-side environments for building software with 6261 multiple tools: 6262 6263 $msvcenv = new cons(RuleSet("msvc")); 6264 $cygnusenv = new cons(RuleSet("unix")); 6265 6266 In the future, this could also be extended to other platforms that 6267 have different default rule sets. 6268 6269 6270 =head2 The C<DefaultRules> method 6271 6272 The C<DefaultRules> method sets the default construction variables that 6273 will be returned by the C<new> method to the specified arguments: 6274 6275 DefaultRules(CC => 'gcc', 6276 CFLAGS => '', 6277 CCCOM => '%CC %CFLAGS %_IFLAGS -c %< -o %>'); 6278 $env = new cons(); 6279 # $env now contains *only* the CC, CFLAGS, 6280 # and CCCOM construction variables 6281 6282 Combined with the C<RuleSet> method, this also provides an easy way 6283 to set explicitly the default build environment to use some supported 6284 toolset other than the Cons defaults: 6285 6286 # use a UNIX-like tool suite (like cygwin) on Win32 6287 DefaultRules(RuleSet('unix')); 6288 $env = new cons(); 6289 6290 Note that the C<DefaultRules> method completely replaces the default 6291 construction environment with the specified arguments, it does not 6292 simply override the existing defaults. To override one or more 6293 variables in a supported C<RuleSet>, append the variables and values: 6294 6295 DefaultRules(RuleSet('unix'), CFLAGS => '-O3'); 6296 $env1 = new cons(); 6297 $env2 = new cons(); 6298 # both $env1 and $env2 have 'unix' defaults 6299 # with CFLAGS set to '-O3' 6300 6301 6302 =head2 The C<Ignore> method 6303 6304 The C<Ignore> method allows you to ignore explicitly dependencies that 6305 Cons infers on its own. It is invoked as follows: 6306 6307 Ignore <patterns>; 6308 6309 This can be used to avoid recompilations due to changes in system header 6310 files or utilities that are known to not affect the generated targets. 6311 6312 If, for example, a program is built in an NFS-mounted directory on 6313 multiple systems that have different copies of F<stdio.h>, the differences 6314 will affect the signatures of all derived targets built from source files 6315 that C<#include E<lt>stdio.hE<gt>>. This will cause all those targets to 6316 be rebuilt when changing systems. If this is not desirable behavior, then 6317 the following line will remove the dependencies on the F<stdio.h> file: 6318 6319 Ignore '^/usr/include/stdio\.h$'; 6320 6321 Note that the arguments to the C<Ignore> method are regular expressions, 6322 so special characters must be escaped and you may wish to anchor the 6323 beginning or end of the expression with C<^> or C<$> characters. 6324 6325 6326 =head2 The C<Salt> method 6327 6328 The C<Salt> method adds a constant value to the signature calculation 6329 for every derived file. It is invoked as follows: 6330 6331 Salt $string; 6332 6333 Changing the Salt value will force a complete rebuild of every derived 6334 file. This can be used to force rebuilds in certain desired 6335 circumstances. For example, 6336 6337 Salt `uname -s`; 6338 6339 Would force a complete rebuild of every derived file whenever the 6340 operating system on which the build is performed (as reported by C<uname 6341 -s>) changes. 6342 6343 6344 =head2 The C<UseCache> method 6345 6346 The C<UseCache> method instructs Cons to maintain a cache of derived 6347 files, to be shared among separate build trees of the same project. 6348 6349 UseCache("cache/<buildname>") || warn("cache directory not found"); 6350 6351 6352 =head2 The C<SourcePath> method 6353 6354 The C<SourcePath> mathod returns the real source path name of a file, 6355 as opposed to the path name within a build directory. It is invoked 6356 as follows: 6357 6358 $path = SourcePath <buildpath>; 6359 6360 6361 =head2 The C<ConsPath> method 6362 6363 The C<ConsPath> method returns true if the supplied path is a derivable 6364 file, and returns undef (false) otherwise. 6365 It is invoked as follows: 6366 6367 $result = ConsPath <path>; 6368 6369 6370 =head2 The C<SplitPath> method 6371 6372 The C<SplitPath> method looks up multiple path names in a string separated 6373 by the default path separator for the operating system (':' on UNIX 6374 systems, ';' on Windows NT), and returns the fully-qualified names. 6375 It is invoked as follows: 6376 6377 @paths = SplitPath <pathlist>; 6378 6379 The C<SplitPath> method will convert names prefixed '#' to the 6380 appropriate top-level build name (without the '#') and will convert 6381 relative names to top-level names. 6382 6383 6384 =head2 The C<DirPath> method 6385 6386 The C<DirPath> method returns the build path name(s) of a directory or 6387 list of directories. It is invoked as follows: 6388 6389 $cwd = DirPath <paths>; 6390 6391 The most common use for the C<DirPath> method is: 6392 6393 $cwd = DirPath '.'; 6394 6395 to fetch the path to the current directory of a subsidiary F<Conscript> 6396 file. 6397 6398 6399 =head2 The C<FilePath> method 6400 6401 The C<FilePath> method returns the build path name(s) of a file or 6402 list of files. It is invoked as follows: 6403 6404 $file = FilePath <path>; 6405 6406 6407 =head2 The C<Help> method 6408 6409 The C<Help> method specifies help text that will be displayed when the 6410 user invokes C<cons -h>. This can be used to provide documentation 6411 of specific targets, values, build options, etc. for the build tree. 6412 It is invoked as follows: 6413 6414 Help <helptext>; 6415 6416 The C<Help> method may only be called once, and should typically be 6417 specified in the top-level F<Construct> file. 6418 6419 6420 =head1 Extending Cons 6421 6422 6423 =head2 Overriding construction variables 6424 6425 There are several ways of extending Cons, which vary in degree of 6426 difficulty. The simplest method is to define your own construction 6427 environment, based on the default environment, but modified to reflect your 6428 particular needs. This will often suffice for C-based applications. You can 6429 use the C<new> constructor, and the C<clone> and C<copy> methods to create 6430 hybrid environments. These changes can be entirely transparent to the 6431 underlying F<Conscript> files. 6432 6433 6434 =head2 Adding new methods 6435 6436 For slightly more demanding changes, you may wish to add new methods to the 6437 C<cons> package. Here's an example of a very simple extension, 6438 C<InstallScript>, which installs a tcl script in a requested location, but 6439 edits the script first to reflect a platform-dependent path that needs to be 6440 installed in the script: 6441 6442 # cons::InstallScript - Create a platform dependent version of a shell 6443 # script by replacing string ``#!your-path-here'' with platform specific 6444 # path $BIN_DIR. 6445 6446 sub cons::InstallScript { 6447 my ($env, $dst, $src) = @_; 6448 Command $env $dst, $src, qq( 6449 sed s+your-path-here+$BIN_DIR+ %< > %> 6450 chmod oug+x %> 6451 ); 6452 } 6453 6454 Notice that this method is defined directly in the C<cons> package (by 6455 prefixing the name with C<cons::>). A change made in this manner will be 6456 globally visible to all environments, and could be called as in the 6457 following example: 6458 6459 InstallScript $env "$BIN/foo", "foo.tcl"; 6460 6461 For a small improvement in generality, the C<BINDIR> variable could be 6462 passed in as an argument or taken from the construction environment--as 6463 C<%BINDIR>. 6464 6465 6466 =head2 Overriding methods 6467 6468 Instead of adding the method to the C<cons> name space, you could define a 6469 new package which inherits existing methods from the C<cons> package and 6470 overrides or adds others. This can be done using Perl's inheritance 6471 mechanisms. 6472 6473 The following example defines a new package C<cons::switch> which 6474 overrides the standard C<Library> method. The overridden method builds 6475 linked library modules, rather than library archives. A new 6476 constructor is provided. Environments created with this constructor 6477 will have the new library method; others won't. 6478 6479 package cons::switch; 6480 BEGIN {@ISA = 'cons'} 6481 6482 sub new { 6483 shift; 6484 bless new cons(@_); 6485 } 6486 6487 sub Library { 6488 my($env) = shift; 6489 my($lib) = shift; 6490 my(@objs) = Objects $env @_; 6491 Command $env $lib, @objs, q( 6492 %LD -r %LDFLAGS %< -o %> 6493 ); 6494 } 6495 6496 This functionality could be invoked as in the following example: 6497 6498 $env = new cons::switch(@overrides); 6499 ... 6500 Library $env 'lib.o', 'foo.c', 'bar.c'; 6501 6502 6503 =head1 Invoking Cons 6504 6505 The C<cons> command is usually invoked from the root of the build tree. A 6506 F<Construct> file must exist in that directory. If the C<-f> argument is 6507 used, then an alternate F<Construct> file may be used (and, possibly, an 6508 alternate root, since C<cons> will cd to F<Construct> file's containing 6509 directory). 6510 6511 If C<cons> is invoked from a child of the root of the build tree with 6512 the C<-t> argument, it will walk up the directory hierarchy looking for a 6513 F<Construct> file. (An alternate name may still be specified with C<-f>.) 6514 The targets supplied on the command line will be modified to be relative 6515 to the discovered F<Construct> file. For example, from a directory 6516 containing a top-level F<Construct> file, the following invocation: 6517 6518 % cd libfoo/subdir 6519 % cons -t target 6520 6521 is exactly equivalent to: 6522 6523 % cons libfoo/subdir/target 6524 6525 If there are any C<Default> targets specified in the directory hierarchy's 6526 F<Construct> or F<Conscript> files, only the default targets at or below 6527 the directory from which C<cons -t> was invoked will be built. 6528 6529 The command is invoked as follows: 6530 6531 cons <arguments> -- <construct-args> 6532 6533 where I<arguments> can be any of the following, in any order: 6534 6535 =over 10 6536 6537 =item I<target> 6538 6539 Build the specified target. If I<target> is a directory, then recursively 6540 build everything within that directory. 6541 6542 =item I<+pattern> 6543 6544 Limit the F<Conscript> files considered to just those that match I<pattern>, 6545 which is a Perl regular expression. Multiple C<+> arguments are accepted. 6546 6547 =item I<name>=<val> 6548 6549 Sets I<name> to value I<val> in the C<ARG> hash passed to the top-level 6550 F<Construct> file. 6551 6552 =item C<-cc> 6553 6554 Show command that would have been executed, when retrieving from cache. No 6555 indication that the file has been retrieved is given; this is useful for 6556 generating build logs that can be compared with real build logs. 6557 6558 =item C<-cd> 6559 6560 Disable all caching. Do not retrieve from cache nor flush to cache. 6561 6562 =item C<-cr> 6563 6564 Build dependencies in random order. This is useful when building multiple 6565 similar trees with caching enabled. 6566 6567 =item C<-cs> 6568 6569 Synchronize existing build targets that are found to be up-to-date with 6570 cache. This is useful if caching has been disabled with -cc or just recently 6571 enabled with UseCache. 6572 6573 =item C<-d> 6574 6575 Enable dependency debugging. 6576 6577 =item C<-f> <file> 6578 6579 Use the specified file instead of F<Construct> (but first change to 6580 containing directory of I<file>). 6581 6582 =item C<-h> 6583 6584 Show a help message local to the current build if one such is defined, and 6585 exit. 6586 6587 =item C<-k> 6588 6589 Keep going as far as possible after errors. 6590 6591 =item C<-o> <file> 6592 6593 Read override file I<file>. 6594 6595 =item C<-p> 6596 6597 Show construction products in specified trees. No build is attempted. 6598 6599 =item C<-pa> 6600 6601 Show construction products and associated actions. No build is attempted. 6602 6603 =item C<-pw> 6604 6605 Show products and where they are defined. No build is attempted. 6606 6607 =item C<-q> 6608 6609 Make the build quiet. Multiple C<-q> options may be specified. 6610 6611 A single C<-q> options suppress messages about Installing and Removing 6612 targets. 6613 6614 Two C<-q> options suppress build command lines and target up-to-date 6615 messages. 6616 6617 =item C<-r> 6618 6619 Remove construction products associated with <targets>. No build is 6620 attempted. 6621 6622 =item C<-R> <repos> 6623 6624 Search for files in I<repos>. Multiple B<-R> I<repos> directories are 6625 searched in the order specified. 6626 6627 =item C<-S> <pkg> 6628 6629 Use the sig::<pkg> package to calculate. Supported <pkg> values 6630 include "md5" for MD5 signature calculation and "md5::debug" for debug 6631 information about MD5 signature calculation. 6632 6633 If the specified package ends in <::debug>, signature debug information 6634 will be printed to the file name specified in the C<CONS_SIG_DEBUG> 6635 environment variable, or to standard output if the environment variable 6636 is not set. 6637 6638 =item C<-t> 6639 6640 Traverse up the directory hierarchy looking for a F<Construct> file, 6641 if none exists in the current directory. Targets will be modified to 6642 be relative to the F<Construct> file. 6643 6644 Internally, C<cons> will change its working directory to the directory 6645 which contains the top-level F<Construct> file and report: 6646 6647 cons: Entering directory `top-level-directory' 6648 6649 This message indicates to an invoking editor (such as emacs) or build 6650 environment that Cons will now report all file names relative to the 6651 top-level directory. This message can not be suppressed with the C<-q> 6652 option. 6653 6654 =item C<-v> 6655 6656 Show C<cons> version and continue processing. 6657 6658 =item C<-V> 6659 6660 Show C<cons> version and exit. 6661 6662 =item C<-wf> <file> 6663 6664 Write all filenames considered into I<file>. 6665 6666 =item C<-x> 6667 6668 Show a help message similar to this one, and exit. 6669 6670 =back 6671 6672 And I<construct-args> can be any arguments that you wish to process in the 6673 F<Construct> file. Note that there should be a B<--> separating the arguments 6674 to cons and the arguments that you wish to process in the F<Construct> file. 6675 6676 Processing of I<construct-args> can be done by any standard package like 6677 B<Getopt> or its variants, or any user defined package. B<cons> will pass in 6678 the I<construct-args> as B<@ARGV> and will not attempt to interpret anything 6679 after the B<-->. 6680 6681 % cons -R /usr/local/repository -d os=solaris +driver -- -c test -f DEBUG 6682 6683 would pass the following to cons 6684 6685 -R /usr/local/repository -d os=solaris +driver 6686 6687 and the following, to the top level F<Construct> file as B<@ARGV> 6688 6689 -c test -f DEBUG 6690 6691 Note that C<cons -r .> is equivalent to a full recursive C<make clean>, 6692 but requires no support in the F<Construct> file or any F<Conscript> 6693 files. This is most useful if you are compiling files into source 6694 directories (if you separate the F<build> and F<export> directories, 6695 then you can just remove the directories). 6696 6697 The options C<-p>, C<-pa>, and C<-pw> are extremely useful for use as an aid 6698 in reading scripts or debugging them. If you want to know what script 6699 installs F<export/include/foo.h>, for example, just type: 6700 6701 % cons -pw export/include/foo.h 6702 6703 6704 =head1 Using and writing dependency scanners 6705 6706 QuickScan allows simple target-independent scanners to be set up for 6707 source files. Only one QuickScan scanner may be associated with any given 6708 source file and environment, although the same scanner may (and should) 6709 be used for multiple files of a given type. 6710 6711 A QuickScan scanner is only ever invoked once for a given source file, 6712 and it is only invoked if the file is used by some target in the tree 6713 (i.e., there is a dependency on the source file). 6714 6715 QuickScan is invoked as follows: 6716 6717 QuickScan CONSENV CODEREF, FILENAME [, PATH] 6718 6719 The subroutine referenced by CODEREF is expected to return a list of 6720 filenames included directly by FILE. These filenames will, in turn, be 6721 scanned. The optional PATH argument supplies a lookup path for finding 6722 FILENAME and/or files returned by the user-supplied subroutine. The PATH 6723 may be a reference to an array of lookup-directory names, or a string of 6724 names separated by the system's separator character (':' on UNIX systems, 6725 ';' on Windows NT). 6726 6727 The subroutine is called once for each line in the file, with $_ set to the 6728 current line. If the subroutine needs to look at additional lines, or, for 6729 that matter, the entire file, then it may read them itself, from the 6730 filehandle SCAN. It may also terminate the loop, if it knows that no further 6731 include information is available, by closing the filehandle. 6732 6733 Whether or not a lookup path is provided, QuickScan first tries to lookup 6734 the file relative to the current directory (for the top-level file 6735 supplied directly to QuickScan), or from the directory containing the 6736 file which referenced the file. This is not very general, but seems good 6737 enough--especially if you have the luxury of writing your own utilities 6738 and can control the use of the search path in a standard way. 6739 6740 Here's a real example, taken from a F<Construct> file here: 6741 6742 sub cons::SMFgen { 6743 my($env, @tables) = @_; 6744 foreach $t (@tables) { 6745 $env->QuickScan(sub { /\b\S*?\.smf\b/g }, "$t.smf", 6746 $env->{SMF_INCLUDE_PATH}); 6747 $env->Command(["$t.smdb.cc","$t.smdb.h","$t.snmp.cc", 6748 "$t.ami.cc", "$t.http.cc"], "$t.smf", 6749 q(smfgen %( %SMF_INCLUDE_OPT %) %<)); 6750 } 6751 } 6752 6753 The subroutine above finds all names of the form <name>.smf in the 6754 file. It will return the names even if they're found within comments, 6755 but that's OK (the mechanism is forgiving of extra files; they're just 6756 ignored on the assumption that the missing file will be noticed when 6757 the program, in this example, smfgen, is actually invoked). 6758 6759 [NOTE that the form C<$env-E<gt>QuickScan ...> and C<$env-E<gt>Command 6760 ...> should not be necessary, but, for some reason, is required 6761 for this particular invocation. This appears to be a bug in Perl or 6762 a misunderstanding on my part; this invocation style does not always 6763 appear to be necessary.] 6764 6765 Here is another way to build the same scanner. This one uses an 6766 explicit code reference, and also (unnecessarily, in this case) reads 6767 the whole file itself: 6768 6769 sub myscan { 6770 my(@includes); 6771 do { 6772 push(@includes, /\b\S*?\.smf\b/g); 6773 } while <SCAN>; 6774 @includes 6775 } 6776 6777 Note that the order of the loop is reversed, with the loop test at the 6778 end. This is because the first line is already read for you. This scanner 6779 can be attached to a source file by: 6780 6781 QuickScan $env \&myscan, "$_.smf"; 6782 6783 This final example, which scans a different type of input file, takes 6784 over the file scanning rather than being called for each input line: 6785 6786 $env->QuickScan( 6787 sub { my(@includes) = (); 6788 do { 6789 push(@includes, $3) 6790 if /^(#include|import)\s+(\")(.+)(\")/ && $3 6791 } while <SCAN>; 6792 @includes 6793 }, 6794 "$idlFileName", 6795 "$env->{CPPPATH};$BUILD/ActiveContext/ACSCLientInterfaces" 6796 ); 6797 6798 =head1 SUPPORT AND SUGGESTIONS 6799 6800 Cons is maintained by the user community. To subscribe, send mail to 6801 B<cons-discuss-request@gnu.org> with body B<subscribe>. 6802 6803 Please report any suggestions through the B<cons-discuss@gnu.org> mailing 6804 list. 6805 6806 =head1 BUGS 6807 6808 Sure to be some. Please report any bugs through the B<bug-cons@gnu.org> 6809 mailing list. 6810 6811 =head1 INFORMATION ABOUT CONS 6812 6813 Information about CONS can be obtained from the official cons web site 6814 B<http://www.dsmit.com/cons/> or its mirrors listed there. 6815 6816 The cons maintainers can be contacted by email at 6817 B<cons-maintainers@gnu.org> 6818 6819 =head1 AUTHORS 6820 6821 Originally by Bob Sidebotham. Then significantly enriched by the members 6822 of the Cons community B<cons-discuss@gnu.org>. 6823 6824 The Cons community would like to thank Ulrich Pfeifer for the original pod 6825 documentation derived from the F<cons.html> file. Cons documentation is now 6826 a part of the program itself. 6827 6828 =cut