eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' & eval 'exec perl -S $0 $argv:q' if 0; # $Id: create_ace_build 80826 2008-03-04 14:51:23Z wotte $ # # Creates an ACE build tree in directory "build/" below the current # directory, which must be an ACE "top level" directory (such as # $ACE_ROOT). The build tree directory structure mirrors that of the ACE # top level directory structure, except that instead of containing any plain # files, it contains only symlinks to the files in the ACE top level structure. # # This program has a similar purpose to "clone", but in addition to # only creating symlinks (clone creates hard links, by default), this # script: # 1) uses relative rather than absolute symlinks, # 2) tries not to put junk files into the build tree, # 3) only creates a new tree in a build/ directory below the current, # top level ACE directory (it's a feature :-), but it does enforce # consistency). # # This program can be re-run on a build tree at any time in order to # update it. It will add symlinks for newly added files, and remove # any that are no longer valid. # # If the starts with "build/", that part will be removed # from it. # # The first three lines above let this script run without specifying the # full path to perl, as long as it is in the user's PATH. # Taken from perlrun man page. use File::Find (); use File::Basename; use FileHandle; print "You should consider using clone_build_tree.pl found with MPC\n"; $usage = "usage: $0 -? | [-a] [-d ] [-v] \n"; $directory_mode = 0777; #### Will be modified by umask, also. $verbose = 0; $source='.'; $absolute= 0; $perl_version = $] + 0; if ($perl_version >= 5) { #### Use an eval so that this script will compile with perl4. eval <<'PERL5_CWD' require Cwd; sub cwd { Cwd::getcwd (); } PERL5_CWD } else { sub cwd { local ($pwd); chop ($pwd = `pwd`); $pwd; } } my($starting_dir) = cwd (); my(@nlinks) = (); my($build_re) = undef; sub cab_link { my($real) = shift; my($fake) = shift; my($uif) = ($^O eq 'MSWin32' ? 'link' : 'symlink'); print "$uif $real $fake\n" if $verbose; my($status) = 0; if ($^O eq 'MSWin32') { my($fixed) = $fake; $fixed =~ s/$build_re//; push(@nlinks, $fixed); chdir(dirname($fake)); $status = link ($real, basename($fake)); chdir($starting_dir); } else { $status = symlink ($real, $fake); } if (!$status) { warn "$0: $uif to $fake failed\n"; } } #### #### Process command line args. #### while ($#ARGV >= 0 && $ARGV[0] =~ /^-/) { if ($ARGV[0] eq '-v') { $verbose = 1; } elsif ($ARGV[0] eq '-d') { if ($ARGV[1] =~ /^\d+$/) { $directory_mode = eval ($ARGV[1]); shift; } else { warn "$0: must provide argument for -d option\n"; die $usage; } } elsif ($ARGV[0] eq '-a') { $source = &cwd (); $absolute = 1; } elsif ($ARGV[0] eq '-?') { print "$usage"; exit; } else { warn "$0: unknown option $ARGV[0]\n"; die $usage; } shift; } die $usage unless $#ARGV == 0; $build = $ARGV[0]; $build =~ s%^build[/\\]%%; #### remove leading "build/", if any $build = "build/$build"; ## Set up the build regular expression use under MSWin32 if ($^O eq 'MSWin32') { ## Get the original build name $build_re = $build; ## Remove any trailing slashes $build_re =~ s/[\\\/]+$//; ## Add a single trailing slash $build_re .= '/'; ## Escape any special characters $build_re =~ s/([\\\$\[\]\(\)\.])/\\$1/g; } #### #### Check that we're in an ACE "top level" directory. #### (-d 'ace' && -d 'include') || die "$0: must be in an ACE top level (ACE_ROOT) directory!\n"; #### #### Create build directories, if needed. #### -d 'build' || mkdir ('build', $directory_mode); -d "$build" || mkdir ("$build", $directory_mode); #### #### Get all ACE plain file and directory names. #### @files = (); sub wanted { my ($dev,$ino,$mode,$nlink,$uid,$gid); /^CVS\z/s && ($File::Find::prune = 1) || /^build\z/s && ($File::Find::prune = 1) || /^\..*obj\z/s && ($File::Find::prune = 1) || /^Templates\.DB\z/s && ($File::Find::prune = 1) || /^Debug\z/s && ($File::Find::prune = 1) || /^Release\z/s && ($File::Find::prune = 1) || /^Static_Debug\z/s && ($File::Find::prune = 1) || /^Static_Release\z/s && ($File::Find::prune = 1) || ( ($nlink || (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_))) && ! -l $_ && ! /^core\z/s && ! /^.*\.state\z/s && ! /^.*\.so\z/s && ! /^.*\.[oa]\z/s && ! /^.*\.dll\z/s && ! /^.*\.lib\z/s && ! /^.*\.obj\z/s && ! /^.*~\z/s && ! /^\.\z/s && ! /^\.#.*\z/s && ! /^.*\.log\z/s ) && push(@files, $File::Find::name); } File::Find::find({wanted => \&wanted}, '.'); #### #### Create directories and symlinks to files. #### foreach $file (@files) { $file =~ s%^./%%g; #### excise leading ./ directory component if (-d $file) { unless (-d "$build/$file") { print "mkdir $build/$file, $directory_mode\n" if $verbose; mkdir ("$build/$file", $directory_mode); } } else { unless (-e "$build/$file") { if (!$absolute) { $up = '../..'; while ($file =~ m%/%g) { $up .= '/..'; } cab_link("$up/$file", "$build/$file"); } else { $path = $source . '/' . $file; cab_link("$path", "$build/$file"); } } } } #### #### Find all the symlinks in the build directory, and remove ones #### that are no longer actually linked to a file. #### if ($^O eq 'MSWin32') { my($lfh) = new FileHandle(); my($txt) = "$build/create_ace_build.links"; if (open($lfh, "$txt")) { while(<$lfh>) { my($line) = $_; $line =~ s/\s+$//; if (-e $line) { push(@nlinks, $line); } else { print "Removing $build/$line \n" if $verbose; unlink("$build/$line") || warn "$0: unlink of $build/$line failed\n"; } } close($lfh); } ## Rewrite the link file. unlink($txt); if (open($lfh, ">$txt")) { foreach my $file (@nlinks) { print $lfh "$file\n"; } close($lfh); } } else { @lfiles = (); sub lcheck { ## There's no way to know if we have hard linked back to a now ## non-existent file. So, just do the normal -l on the file ## which will cause no files to be pushed on Windows. if (-l $_) { push(@lfiles, $File::Find::name); } } File::Find::find({wanted => \&lcheck}, $build); foreach (@lfiles) { local @s = stat $_; if ($#s == -1) { print "Removing $_ \n" if $verbose; unlink $_ || warn "$0: unlink of $_ failed\n"; } } } #### #### Done: print message. #### print "\nCompleted creation of $build/.\n"; my($msg) = ''; if (! -e "$build/ace/config.h") { $msg .= "$build/ace/config.h"; } if ($^O ne 'MSWin32' && ! -e "$build/include/makeinclude/platform_macros.GNU") { if ($msg ne '') { $msg .= " and\n"; } $msg .= "$build/include/makeinclude/platform_macros.GNU"; } if ($msg ne '') { print "Be sure to setup $msg.\n"; } #### EOF