#!/usr/bin/perl -w eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}' if 0; # not running under some shell use strict; # # Use libraries use Getopt::Long; use File::Basename; use File::Copy; use Archive::Tar; use RPM::Specfile; use vars qw/$VERSION/; $VERSION = $RPM::Specfile::VERSION; # # Setup some defaults my %defaults; $defaults{'perlver'} = '1:5.6.1'; if ( $] >= 5.008 ) { $defaults{'perlver'} = '2:5.8.0'; } $defaults{'outdir'} = './'; $defaults{'tmpdir'} = '/tmp'; $defaults{'email'} = ( getpwuid($<) )[0] . '@unconfigured-email'; $defaults{'release'} = '9'; $defaults{'installdirs'} = ""; # # Parse command line options my %options; GetOptions( \%options, "outdir=s", "tmpdir=s", "email=s", "name|n=s", "create", "test|t", "epoch|e=n", "version|v=s", "release|r=s", "perlver=s", "patch=s", "noarch", "arch|a=s", "noperlreqs", "usage", "buildall|b", "installdirs=s", "descfile=s", "help", "requires=s@", "buildrequires=s@", "sign" ) or die_usage(); my $fullname = shift; if ( defined( $options{'usage'} ) ) { usage(); exit(0); } # # Make sure filename was provided die_usage() unless $fullname; # # If we were given a description file, make sure it exists if ( $options{'descfile'} ) { if ( !-e $options{'descfile'} ) { print STDERR "Description file given does not exist!\n"; print STDERR "File: ${options{'descfile'}}\n"; exit(1); } if ( !-r $options{'descfile'} ) { print STDERR "Description file given is not readable!\n"; print STDERR "File: ${options{'descfile'}}\n"; exit(1); } } ## end if ( $options{'descfile'... # # Overide defaults if necessary, otherwise keep them. my $tarball = basename($fullname); my $create = $options{create} || ''; my $email = $options{email} || $defaults{'email'}; my $requires = $options{requires} || []; my $buildrequires = $options{buildrequires} || []; my $outdir = $options{outdir} || $defaults{'outdir'}; my $tmpdir = $options{tmpdir} || $defaults{'tmpdir'}; my $noarch = $options{noarch} || ''; my $plat_perl_reqs = $options{'noperlreqs'} ? 0 : 1; my $release = $options{'release'} || $defaults{'release'}; my $build_switch = 's'; # # Set build arch - this is needed to find out where # the binary rpm was placed, and copy it back to the # current working directory. my $build_arch; if ( $options{'arch'} ) { $build_arch = $options{'arch'}; } elsif ( $options{'noarch'} ) { $build_arch = 'noarch'; } else { $build_arch = get_default_build_arch(); if ( $build_arch eq '' ) { print STDERR "Could not get default build arch!\n"; exit(1); } } ## end else [ if ( $options{'arch'} ) $build_switch = 'a' if ( defined( $options{'buildall'} ) ); $tarball =~ /^(.+)\-([^-]+)\.tar\.gz$/; my $name = $options{name} || $1; my $ver = $options{version} || $2; die "Module name/version not parsable from $tarball" unless $name and $ver; $name =~ s/::/-/g; copy( $fullname, $tmpdir ) or die "copy $fullname: $!"; if ( not exists $options{noarch} ) { my @files = Archive::Tar->list_archive("$tmpdir/$tarball"); if (@files) { $noarch = 1; $noarch = 0 if grep { /\.(xs|c|cc|C)$/ } @files; } } ## end if ( not exists $options... my $patchfile = ''; if ( $options{patch} ) { copy( $options{patch}, $tmpdir ) or die "copy $options{patch}: $!"; $patchfile = $options{patch}; } my $spec = new RPM::Specfile; # perlver. turning perl versions into happy rpm epochs. also used to # determine INSTALLDIRS strategy my $perlver = $defaults{'perlver'}; if ( $options{perlver} ) { if ( $options{perlver} eq '5.6.1' ) { $perlver = "1:5.6.1"; } elsif ( $options{perlver} eq '5.8.0' ) { $perlver = "2:5.8.0"; } } ## end if ( $options{perlver}) # some basic spec fields $spec->name("perl-$name"); $spec->version($ver); $spec->release($release); $spec->epoch( $options{epoch} ); $spec->summary("$name Perl module"); $spec->group("Development/Libraries"); $spec->license("distributable"); $spec->push_buildrequire("perl >= $perlver"); $spec->add_changelog_entry( $email, 'specfile auto-generated by cpanflute' ); for my $req ( @{ $options{'requires'} } ) { $spec->push_require($req); } for my $req ( @{ $options{'buildrequires'} } ) { $spec->push_buildrequire($req); } # Setup spec description. Defaults to summary, unless # description file provided: if ( $options{'descfile'} ) { $spec->description( read_desc_file( $options{'descfile'} ) ); } else { $spec->description( $spec->summary ); } # # Setup build architecture. $spec->buildarch( $options{'arch'} ) if ( defined( $options{'arch'} ) ); $spec->buildarch('noarch') if $noarch; # # Use perl requirements by default (onward and upward...). if ($plat_perl_reqs) { $spec->push_require( q|%(perl -MConfig -le 'if (defined $Config{useithreads}) { print "perl(:WITH_ITHREADS)" } else { print "perl(:WITHOUT_ITHREADS)" }')| ); $spec->push_require( q|%(perl -MConfig -le 'if (defined $Config{usethreads}) { print "perl(:WITH_THREADS)" } else { print "perl(:WITHOUT_THREADS)" }')| ); $spec->push_require( q|%(perl -MConfig -le 'if (defined $Config{uselargefiles}) { print "perl(:WITH_LARGEFILES)" } else { print "perl(:WITHOUT_LARGEFILES)" }')| ); $spec->push_require(q|perl = %(perl -le 'printf "%vd\n", $^V')|); } ## end if ($plat_perl_reqs) $spec->push_source($tarball); $spec->push_patch( basename($patchfile) ) if $patchfile; # make a URL that can actually possibly take you to the right place my $url_name = $name; $url_name =~ s/-/::/g; $url_name =~ s/([^a-zA-Z0-9])/sprintf "%%%x", ord $1/ge; $spec->url("http://search.cpan.org/search?mode=module&query=$url_name"); # now we get into the multiline tags. stolen mostly verbatim from # cpanflute1 my $patch = ''; if ($patchfile) { $patch = "%patch0 -p1\n"; } $spec->prep("%setup -q -n $name-%{version} $create\n$patch"); $spec->file_param("-f $name-%{version}-filelist"); $spec->push_file("%defattr(-,root,root)"); my $test_clause = ''; $test_clause = "make test" if $options{test}; my $installdirs = ""; if ( $options{'installdirs'} ) { # perl 5.8 explicitly supports the INSTALLDIRS option. in previous # perls, it was a vendor added option. Red Hat and Debian provide # this for their perl 5.6.1, but the syntax for 5.8.0 is different, # at least in the Red Hat case $installdirs = "INSTALLDIRS=$options{'installdirs'}"; } ## end if ( $options{'installdirs'... my $makefile_pl = qq{CFLAGS="\$RPM_OPT_FLAGS" perl Makefile.PL}; my $make_install = qq{make PREFIX=\$RPM_BUILD_ROOT/usr $installdirs install}; if ( $perlver =~ /5.8.0/ ) { $makefile_pl = qq{CFLAGS="\$RPM_OPT_FLAGS" perl Makefile.PL PREFIX=\$RPM_BUILD_ROOT/usr $installdirs}; $make_install = qq{make install}; } $spec->build(<clean('[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT'); my $inst = q{ [ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT eval `perl '-V:installarchlib'` mkdir -p $RPM_BUILD_ROOT/$installarchlib $make_install [ -x /usr/lib/rpm/brp-compress ] && /usr/lib/rpm/brp-compress find $RPM_BUILD_ROOT/usr -type f -print | \ sed "s@^$RPM_BUILD_ROOT@@g" | \ grep -v perllocal.pod | \ grep -v "\.packlist" > $name-%{version}-filelist if [ "$(cat $name-%{version}-filelist)X" = "X" ] ; then echo "ERROR: EMPTY FILE LIST" exit 1 fi }; $inst =~ s/\$name/$name/g; $inst =~ s/\$make_install/$make_install/g; $inst = qq{%define _unpackaged_files_terminate_build 0} . "\n" . $inst; $spec->install($inst); # write the spec file. create some macros. $spec->write_specfile("$tmpdir/perl-$name.spec"); print "Signing with \<$email\>; see usage if this is not right...\n"; print "Making $tmpdir/macros...\n"; open FH, ">$tmpdir/macros" or die "Can't create $tmpdir/macros: $!"; print FH qq{ %_topdir $tmpdir %_builddir %{_topdir} %_rpmdir $outdir %_sourcedir %{_topdir} %_specdir %{_topdir} %_srcrpmdir $outdir %_build_name_fmt %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm }; close FH; open FH, ">$tmpdir/rpmrc" or die "Can't create $tmpdir/rpmrc: $!"; my $macrofiles = qx(rpm --showrc | grep ^macrofiles | cut -f2- -d:); chomp $macrofiles; print FH qq{ include: /usr/lib/rpm/rpmrc macrofiles: $macrofiles:$tmpdir/macros }; close FH; # Build the build command my @cmd; push @cmd, 'rpmbuild'; push @cmd, '--rcfile', "$tmpdir/rpmrc"; push @cmd, "-b${build_switch}"; push @cmd, '--rmsource'; push @cmd, '--rmspec'; push @cmd, '--clean', "$tmpdir/perl-$name.spec"; push @cmd, "--sign" if $options{sign}; # perform the build, die on error my $retval = system(@cmd); $retval = $? >> 8; if ( $retval != 0 ) { die "RPM building failed!\n"; } # clean up macros file unlink "$tmpdir/rpmrc", "$tmpdir/macros"; # if we did a build all, lets move the rpms into our current # directory my $bin_rpm = "./perl-${name}-${ver}-${release}.${build_arch}.rpm"; exit(0); ############### # Subroutines # ############### sub die_usage { usage(); exit(1); } sub usage { print <; close FILE; return $ret; } ## end sub read_desc_file