makerel revision 1.10
1#!/usr/bin/perl -w 2 3# A tool to build a perl release tarball 4# Very basic but functional - if you're on a unix system. 5# 6# If you're on Win32 then it should still work, but various Unix command-line 7# tools will need to be available somewhere. An obvious choice is to install 8# Cygwin and ensure its 'bin' folder is on the PATH in the shell where you run 9# this script. The Cygwin 'bin' folder needs to precede the Windows 'system32' 10# folder so that Cygwin's 'find' command is found in preference to the Windows 11# 'find' command. Your Cygwin installation will need to contain at least the 12# 'cpio' command, in addition to the commands installed by default, and it will 13# also be useful to have 'curl' and 'diffstat' installed too for later stages 14# of the release process (namely, Porting\corelist.pl and generating the commit 15# statistics for the perlXYZdelta.pod file respectively). Finally, ensure that 16# the 'awk' and 'shasum' commands are copies of gawk.exe and sha1sum.exe 17# respectively, rather than the links to them that only work in a Cygwin bash 18# shell which they are by default. 19# 20# No matter how automated this gets, you'll always need to read 21# and re-read pumpkin.pod and release_managers_guide.pod to 22# check for things to be done at various stages of the process. 23# 24# Tim Bunce, June 1997 25 26use ExtUtils::Manifest qw(fullcheck); 27$ExtUtils::Manifest::Quiet = 1; 28use Getopt::Std; 29 30$|=1; 31 32sub usage { die <<EOF; } 33usage: $0 [ -r rootdir ] [-s suffix ] [ -b ] [ -n ] 34 -r rootdir directory under which to create the build dir and tarball 35 defaults to '..' 36 -s suffix suffix to append to to the perl-x.y.z dir and tarball name 37 defaults to the concatenation of the local_patches entry 38 in patchlevel.h (or blank, if none) 39 -b make a .bz2 file in addtion to a .gz file 40 -n do not make any tarballs, just the directory 41EOF 42 43my %opts; 44getopts('bnr:s:', \%opts) or usage; 45@ARGV && usage; 46 47$relroot = defined $opts{r} ? $opts{r} : ".."; 48 49die "Must be in root of the perl source tree.\n" 50 unless -f "./MANIFEST" and -f "patchlevel.h"; 51 52open PATCHLEVEL,"<patchlevel.h" or die; 53my @patchlevel_h = <PATCHLEVEL>; 54close PATCHLEVEL; 55my $patchlevel_h = join "", grep { /^#\s*define/ } @patchlevel_h; 56print $patchlevel_h; 57$revision = $1 if $patchlevel_h =~ /PERL_REVISION\s+(\d+)/; 58$patchlevel = $1 if $patchlevel_h =~ /PERL_VERSION\s+(\d+)/; 59$subversion = $1 if $patchlevel_h =~ /PERL_SUBVERSION\s+(\d+)/; 60die "Unable to parse patchlevel.h" unless $subversion >= 0; 61$vers = sprintf("%d.%d.%d", $revision, $patchlevel, $subversion); 62 63# fetch list of local patches 64my (@local_patches, @lpatch_tags, $lpatch_tags); 65@local_patches = grep { !/^\s*,?NULL/ && ! /,"uncommitted-changes"/ } 66 grep { /^static.*local_patches/../^};/ } 67 @patchlevel_h; 68@lpatch_tags = map { /^\s*,"(\w+)/ } @local_patches; 69$lpatch_tags = join "-", @lpatch_tags; 70 71$perl = "perl-$vers"; 72$reldir = "$perl"; 73 74$lpatch_tags = $opts{s} if defined $opts{s}; 75$reldir .= "-$lpatch_tags" if $lpatch_tags; 76 77print "\nMaking a release for $perl in $relroot/$reldir\n\n"; 78 79print "Cross-checking the MANIFEST...\n"; 80($missfile, $missentry) = fullcheck(); 81@$missentry 82 = grep {$_ !~ m!^\.git/! and $_ !~ m!(?:/|^)\.gitignore!} @$missentry; 83if (@$missfile ) { 84 warn "Can't make a release with MANIFEST files missing:\n"; 85 warn "\t".$_."\n" for (@$missfile); 86} 87if (@$missentry ) { 88 warn "Can't make a release with files not listed in MANIFEST\n"; 89 warn "\t".$_."\n" for (@$missentry); 90 91} 92if ("@$missentry" =~ m/\.orig\b/) { 93 # Handy listing of find command and .orig files from patching work. 94 # I tend to run 'xargs rm' and copy and paste the file list. 95 my $cmd = "find . -name '*.orig' -print"; 96 print "$cmd\n"; 97 system($cmd); 98} 99die "Aborted.\n" if @$missentry or @$missfile; 100print "\n"; 101 102# VMS no longer has hardcoded version numbers descrip.mms 103 104print "Creating $relroot/$reldir release directory...\n"; 105die "$relroot/$reldir release directory already exists\n" if -e "$relroot/$reldir"; 106die "$relroot/$reldir.tar.gz release file already exists\n" if -e "$relroot/$reldir.tar.gz"; 107mkdir("$relroot/$reldir", 0755) or die "mkdir $relroot/$reldir: $!\n"; 108print "\n"; 109 110 111print "Copying files to release directory...\n"; 112# ExtUtils::Manifest maniread does not preserve the order 113$cmd = "awk '{print \$1}' MANIFEST | cpio -pdm $relroot/$reldir"; 114system($cmd) == 0 115 or die "$cmd failed"; 116print "\n"; 117 118chdir "$relroot/$reldir" or die $!; 119 120 121print "Setting file permissions...\n"; 122system("find . -type f -print | xargs chmod 0444"); 123system("find . -type d -print | xargs chmod 0755"); 124my @exe = map { my ($f) = split; glob($f) } 125 grep { $_ !~ /\A#/ && $_ !~ /\A\s*\z/ } 126 map { split "\n" } 127 do { local (@ARGV, $/) = 'Porting/exec-bit.txt'; <> }; 128 129system("chmod +x @exe") == 0 130 or die "system: $!"; 131 132my @writables = qw( 133 NetWare/config_H.wc 134 NetWare/Makefile 135 feature.h 136 lib/feature.pm 137 keywords.h 138 keywords.c 139 opcode.h 140 opnames.h 141 pp_proto.h 142 proto.h 143 embed.h 144 embedvar.h 145 overload.c 146 overload.h 147 mg_vtable.h 148 perlapi.h 149 perlapi.c 150 cpan/Devel-PPPort/module2.c 151 cpan/Devel-PPPort/module3.c 152 reentr.c 153 reentr.h 154 regcharclass.h 155 regnodes.h 156 warnings.h 157 lib/warnings.pm 158 win32/Makefile 159 win32/Makefile.ce 160 win32/makefile.mk 161 win32/config_H.ce 162 win32/config_H.gc 163 win32/config_H.gc64 164 win32/config_H.gc64nox 165 win32/config_H.vc 166 win32/config_H.vc64 167 utils/Makefile 168 uconfig.h 169); 170system("chmod u+w @writables") == 0 171 or die "system: $!"; 172 173chdir ".." or die $!; 174 175exit if $opts{n}; 176 177my $src = (-e $perl) ? $perl : 'perl'; # 'perl' in maint branch 178 179print "Checking if you have 7z...\n"; 180my $output_7z = `7z 2>&1`; 181my $have_7z = defined $output_7z && $output_7z =~ /7-Zip/; 182 183print "Checking if you have advdef...\n"; 184my $output_advdef = `advdef --version 2>&1`; 185my $have_advdef = defined $output_advdef && $output_advdef =~ /advancecomp/; 186 187if ($have_7z) { 188 print "Creating and compressing the tar.gz file with 7z...\n"; 189 $cmd = "tar cf - $reldir | 7z a -tgzip -mx9 -bd -si $reldir.tar.gz"; 190 system($cmd) == 0 or die "$cmd failed"; 191} else { 192 print "Creating and compressing the tar.gz file...\n"; 193 $cmd = "tar cf - $reldir | gzip --best > $reldir.tar.gz"; 194 system($cmd) == 0 or die "$cmd failed"; 195 if ($have_advdef) { 196 print "Recompressing the tar.gz file with advdef...\n"; 197 $cmd = "advdef -z -4 $reldir.tar.gz"; 198 system($cmd) == 0 or die "$cmd failed"; 199 } 200} 201 202if ($opts{b}) { 203 if ($have_7z) { 204 print "Creating and compressing the tar.bz2 file with 7z...\n"; 205 $cmd = "tar cf - $reldir | 7z a -tbzip2 -mx9 -bd -si $reldir.tar.bz2"; 206 system($cmd) == 0 or die "$cmd failed"; 207 } else { 208 print "Creating and compressing the tar.bz2 file...\n"; 209 $cmd = "tar cf - $reldir | bzip2 > $reldir.tar.bz2"; 210 system($cmd) == 0 or die "$cmd failed"; 211 } 212} 213 214print "\n"; 215 216system("ls -ld $perl*"); 217print "\n"; 218 219my $null = $^O eq 'MSWin32' ? 'NUL' : '/dev/null'; 220for my $sha (qw(sha1 shasum sha1sum)) { 221 if (`which $sha 2>$null`) { 222 system("$sha $perl*.tar.*"); 223 last; 224 } 225} 226