#!/usr/bin/perl -w ################################################################################ # # regenerate -- regenerate baseline and todo files # ################################################################################ # # Version 3.x, Copyright (C) 2004-2013, Marcus Holland-Moritz. # Version 2.x, Copyright (C) 2001, Paul Marquess. # Version 1.x, Copyright (C) 1999, Kenneth Albanowski. # # This program is free software; you can redistribute it and/or # modify it under the same terms as Perl itself. # ################################################################################ use strict; use File::Path; use File::Copy; use Getopt::Long; use Pod::Usage; require './devel/devtools.pl'; require './parts/ppptools.pl'; our %opt = ( check => 1, debug => 0, verbose => 0, yes => 0, ); GetOptions(\%opt, qw( check! verbose yes install=s blead=s blead-version=s debug=i debug-start=s skip-devels)) or die pod2usage(); identify(); unless (-e 'parts/embed.fnc' and -e 'parts/apidoc.fnc') { print "\nOooops, $0 must be run from the Devel::PPPort root directory.\n"; quit_now(); } if (! $opt{'yes'}) { ask_or_quit("Are you SURE you have:\n1) updated parts/embed.fnc to" . "latest blead?\n2) run devel/mkapidoc.pl to update" . " parts/apidoc.fnc?\n3) run devel/mkppport_fnc.pl to" . "update parts/ppport.fnc?\n"); } my $files_glob_pattern = '[12345789]*'; my %files = map { ($_ => [glob "parts/$_/$files_glob_pattern"]) } qw( base todo ); my(@notwr, @wr); for my $f (map @$_, values %files) { push @{-w $f ? \@wr : \@notwr}, $f; } if (@notwr) { if (@wr) { print "\nThe following files are not writable:\n\n"; print " $_\n" for @notwr; print "\nAre you sure you have checked out these files?\n"; } else { print "\nAll baseline / todo file are not writable.\n"; ask_or_quit("Do you want to try to check out these files?"); unless (runtool("wco", "-l", "-t", "locked by $0", @notwr)) { print "\nSomething went wrong while checking out the files.\n"; quit_now(); } } } # Check that there is only one entry in the whole system for each item my @embeds = parse_embed(qw(parts/embed.fnc parts/apidoc.fnc parts/ppport.fnc)); my %seen; for my $entry (@embeds) { my $Mflag = defined $entry->{flags}{M}; $seen{"$entry->{name}/$entry->{cond}/$Mflag"}++; } my %bads = grep { $seen{$_} > 1 } keys %seen; if (keys %bads) { print "The following items have multiple entries in the parts/*.fnc files.\n", " Regenerate apidoc.fnc, then ppport.fnc and try again. If this\n", " doesn't work, choose the best version for each symbol and delete\n", " the others: ", join "\n", keys %bads, "\n"; quit_now(); } if (-e 'ppport.h') { my $blead = $opt{blead}; $blead = get_and_sort_perls(\%opt)->[0]->{path} unless $blead; # Get list of things we provide my %provided = map { /^(\w+)/ ? ( $1 => 1 ) : () } `$blead ppport.h --list-provided`; # Get the list of macros that are hard to test. my @unorthodox = map { exists $_->{flags}{u} ? $_->{name} : () } @embeds; # Keep on that list only the things we provide @unorthodox = grep { exists $provided{$_} } @unorthodox; # And get the list of known hard things. my $hard_ref = &known_but_hard_to_test_for; # If we provide something, it better be on the known things list my @bad = grep { ! exists $hard_ref->{$_} } @unorthodox; undef @bad; if (@bad) { print "The following items need to be manually added to the list in", " parts/ppptools.pl: known_but_hard_to_test_for(): ", join ", ", @bad, "\n"; quit_now(); } } # If starting in the middle, don't zap what we've already done if (! $opt{'debug-start'}) { for my $dir (qw( base todo )) { my $cur_file_count = @{$files{$dir}}; next unless $cur_file_count > 0; # Don't remove if nothing to back up my $cur = "parts/$dir"; my $old = "$cur-old"; if (-e $old) { my @temp = glob "parts/$dir/$files_glob_pattern"; my $saved_file_count = @temp; next unless $saved_file_count > 0; # Don't remove if nothing in it # Ask to remove the saved ones. If there are already many saved # files, ask even if the parameter says the answer is always yes. # (The criteria here for "many" could be profitably revised) if ($saved_file_count > $cur_file_count || ! $opt{'yes'}) { my $message = "";; $message .= "There are $saved_file_count already saved files," . " and $cur_file_count new ones\n" if $cur_file_count > 0; $message .= "Do you want me to remove the old $old directory?"; ask_or_quit($message); } rmtree($old); } mkdir $old; print "\nBacking up $cur in $old.\n"; for my $src (@{$files{$dir}}) { my $dst = $src; $dst =~ s/\Q$cur/$old/ or die "Ooops!"; move($src, $dst) or die "Moving $src to $dst failed: $!\n"; } } } my @perlargs; push @perlargs, "--debug=$opt{debug}" if $opt{debug}; push @perlargs, "--install=$opt{install}" if $opt{install}; push @perlargs, "--blead=$opt{blead}" if $opt{blead}; push @perlargs, "--debug-start=$opt{'debug-start'}" if $opt{'debug-start'}; push @perlargs, "--skip-devels" if $opt{'skip-devels'}; my $T0 = time; my @args = ddverbose(); push @args, '--nocheck' unless $opt{check}; push @args, "--blead-version=$opt{'blead-version'}" if $opt{'blead-version'}; push @args, @perlargs; # Look for all the NEED_foo macros my @NEED; for my $file (all_files_in_dir('parts/inc')) { my $spec = parse_partspec($file); next unless $spec->{'xsinit'}; while ($spec->{'xsinit'} =~ / ^ ( \# \s* define \s+ NEED_ \w+ ) \s /xmg) { push @NEED, "$1"; } } # Make the list available to parts/apicheck.pl $ENV{'DPPP_NEED'} = join "\n", sort @NEED; # Find out what symbols were in what releases print "\nBuilding baseline files...\n\n"; unless (runperl('devel/mktodo', '--base', @args)) { print "\nSomething went wrong while building the baseline files.\n"; quit_now(); } # Then find out what ppport.h buys us by repeating the process above, but # using ppport.h print "\nBuilding todo files...\n\n"; unless (runperl('devel/mktodo', @args)) { print "\nSomething went wrong while building the todo files.\n"; quit_now(); } print "\nAdding remaining info...\n\n"; unless (runperl('Makefile.PL') and runtool('make') and runperl('devel/scanprov', '--mode=write', @perlargs)) { print "\nSomething went wrong while adding the baseline info.\n"; quit_now(); } my($wall, $usr, $sys, $cusr, $csys) = (time - $T0, times); my $cpu = sprintf "%.2f", $usr + $sys + $cusr + $csys; $usr = sprintf "%.2f", $usr + $cusr; $sys = sprintf "%.2f", $sys + $csys; print < and L. =cut