#! /usr/bin/env perl use Getopt::Long qw(:config bundling no_ignore_case); use POSIX; use strict; use warnings; my $help = 0; GetOptions ("h|help" => \$help); usage () if $help; die "$0: exactly one or two nonoption arguments are required\n" if @ARGV != 1 && @ARGV != 2; my $builder = `hostname`; chomp $builder; # Select build number. my $buildnumber = POSIX::strftime("%Y%m%d%H%M%S", localtime); print "\tBUILDNUMBER=$buildnumber\n"; # Create build directory. my $builddir = "builds/$buildnumber"; print "Create $builddir\n"; mkdir "builds" or die "builds: mkdir: $!\n" if ! -d "builds"; mkdir $builddir or die "$builddir: mkdir: $!\n"; $resultsdir = "$builddir/results"; mkdir $resultsdir or die "$resultsdir: mkdir: $!\n"; $logfile = "$resultsdir/LOG"; open (LOG, '>', $logfile) or die "creating $logfile failed: $!\n"; $varsfile = "$resultsdir/VARS"; open (VARS, '>', $varsfile) or die "creating $varsfile failed: $!\n"; my $tarball; if (@ARGV == 2) { my ($repo, $branch) = @ARGV; # Fetch branch print "Fetch $repo, branch $branch\n"; run ("git fetch $repo +$branch:buildtmp/$$/pspp"); # Get revision number. my $revision = `git rev-parse buildtmp/$$/pspp`; chomp $revision; print "\tREVISION=$revision\n"; my $abbrev_revision = substr ($revision, 0, 6); # Extract source. print "Extract branch into $builddir/pspp$buildnumber\n"; run ("git archive --format=tar --prefix=pspp$buildnumber/ buildtmp/$$/pspp | (cd $builddir && tar xf -)"); # Extract version number. print "Extract version number\n"; my $trace = `cd $builddir/pspp$buildnumber && autoconf -t AC_INIT`; chomp $trace; my ($file, $line, $macro, $package, $version, @rest) = split (':', $trace); print "\tVERSION=$version\n"; # Append -g012345 to AC_INIT version number. my $fullname = "$builddir/pspp$buildnumber/$file"; open (OLDFILE, '<', $fullname) or die "opening $fullname failed: $!\n"; open (NEWFILE, '>', "$fullname.new") or die "creating $fullname.new failed: $!\n"; while () { if ($. != $line) { print NEWFILE $_; } else { print NEWFILE "AC_INIT([$package], [$version-g$abbrev_revision]"; print NEWFILE ", [$_]" foreach @rest; print NEWFILE ")\n"; } } close (NEWFILE); close (OLDFILE); rename ("$fullname.new", $fullname) or die "rename $fullname.new to $fullname failed: $!\n"; # Add note to beginning of NEWS (otherwise "make dist" fails). $fullname = "$builddir/pspp$buildnumber/NEWS"; open (OLDFILE, '<', $fullname) or die "opening $fullname failed: $!\n"; open (NEWFILE, '>', "$fullname.new") or die "creating $fullname.new failed: $!\n"; my $found_changes = 0; while () { if (!$found_changes && /^Changes/) { $found_changes = 1; print NEWFILE <) { ($gnulib_commit) = /^\s+commit ([0-9a-fA-F]{8,})/ and last; } die "$fullname does not specify a Git commit number\n" if !defined ($gnulib_commit); print "\tGNULIB_REVISION=$gnulib_commit\n"; # If we don't already have that Gnulib commit, update Gnulib. `git rev-parse $gnulib_commit`; if ($? != 0) { run ("git fetch gnulib"); } # Extract gnulib source. run ("git archive --format=tar --prefix=gnulib/ $gnulib_commit | (cd $builddir && tar xf -)"); # Bootstrap. run ("cd $builddir/pspp$buildnumber && make -f Smake"); # Configure. run ("cd $builddir/pspp$buildnumber && mkdir _build && cd _build && ../configure"); # Distribute. run ("cd $builddir/pspp$buildnumber/_build && make dist"); $tarball = "$builddir/pspp$buildnumber/_build/pspp-$version-g$abbrev_revision.tar.gz"; } else { $tarball = $ARGV[0]; } print "Determining $tarball target directory\n"; my $sample_filename = `zcat $tarball | tar tf - | head -1`; my ($tarball_dir) = $sample_filename =~ m%^(?:[./])*([^/]+)/%; print "\tTARBALL_DIR=$tarball_dir\n"; print "Extracting $tarball into $builddir/$tarball_dir\n"; run ("zcat $tarball | (cd $builddir && tar xf -)"); print "Extracting tar version\n"; my ($version) = `cd $builddir/$tarball_dir && ./configure --version | head -1` =~ /configure (\S+)$/; print "\tVERSION=$version\n"; my ($binary_version) = "$version-$builder-build$buildnumber"; print "\tBINARY_VERSION=$version\n"; print "Configuring\n"; run ("chmod -R a-w $builddir/$tarball_dir"); run ("chmod u+w $builddir/$tarball_dir"); run ("mkdir $builddir/$tarball_dir/_build"); run ("chmod a-w $builddir/$tarball_dir"); run ("cd $builddir/$tarball_dir/_build && ../configure --enable-relocatable --prefix=''"); print "Build\n"; run ("cd $builddir/$tarball_dir/_build && make"); print "Install\n"; run ("cd $builddir/$tarball_dir/_build && make install DESTDIR=\$PWD/pspp-$binary_version"); print "Make binary distribution\n"; run ("cd $builddir/$tarball_dir/_build && tar cfz pspp-$binary_version.tar.gz pspp-$binary_version"); print "Check\n"; run ("cd $builddir/$tarball_dir/_build && make check"); print "Uninstall\n"; run ("cd $builddir/$tarball_dir/_build && make uninstall DESTDIR=\$PWD/pspp-$binary_version"); print "Check uninstall\n"; run ("cd $builddir/$tarball_dir/_build && make distuninstallcheck distuninstallcheck_dir=\$PWD/pspp-$binary_version"); # distcleancheck print "Success\n"; sub usage { print <> 8; } exit 1; } # Clone source # Add build number # Tag build # Clone gnulib at correct commit number # Run gnulib-tool. # Run configure # Make dist # Unpack dist # Run configure # Check # Install # Make binary dist # Build mingw32 installer # Other distcheck stuff? # Distribute manual in various formats