michael@360: #!@l_prefix@/bin/perl -w michael@360: ## michael@360: ## perl-openpkg -- OpenPKG Perl Module Build Utility michael@360: ## Copyright (c) 2000-2007 OpenPKG Foundation e.V. michael@360: ## Copyright (c) 2000-2007 Ralf S. Engelschall michael@360: ## michael@360: ## Permission to use, copy, modify, and distribute this software for michael@360: ## any purpose with or without fee is hereby granted, provided that michael@360: ## the above copyright notice and this permission notice appear in all michael@360: ## copies. michael@360: ## michael@360: ## THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED michael@360: ## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF michael@360: ## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. michael@360: ## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR michael@360: ## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, michael@360: ## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT michael@360: ## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF michael@360: ## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND michael@360: ## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, michael@360: ## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT michael@360: ## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF michael@360: ## SUCH DAMAGE. michael@360: ## michael@360: michael@360: require 5; michael@360: use strict; michael@360: use Getopt::Long; michael@360: use IO qw(Handle Seekable File Pipe Socket Dir); michael@360: michael@360: # program information michael@360: my $ME = { michael@360: prog_path => $0, michael@360: prog_name => "perl-openpkg", michael@360: prog_vers => "2.0.1", michael@360: prog_date => "03-Dec-2004" michael@360: }; michael@360: michael@360: # program configuration michael@360: my $CF = { michael@360: path_prefix => '@l_prefix@', michael@360: path_libdir => "", michael@360: path_tmpdir => ($ENV{"TMPDIR"} || "/tmp"), michael@360: path_wrkdir => "", michael@360: path_buildroot => ($ENV{"RPM_BUILD_ROOT"} || ""), michael@360: path_buildwork => ($ENV{"RPM_BUILD_DIR"} || ""), michael@360: pkg_name => ($ENV{"RPM_PACKAGE_NAME"} || ""), michael@360: perl_schema => "vendor", michael@360: perl_args => [], michael@360: perl_stdin => "/dev/null", michael@360: files_file => "-", michael@360: files_unquoted => 0, michael@360: prog_rpm => '%path_prefix%/libexec/openpkg/rpm', michael@360: prog_perl => '%path_prefix%/bin/perl', michael@360: mode_quiet => 0, michael@360: mode_verbose => 0, michael@360: run_version => 0, michael@360: run_help => 0, michael@360: }; michael@360: michael@360: # cleanup support michael@360: my @cleanup = (); michael@360: sub cleanup_remember { michael@360: my ($cmd) = @_; michael@360: push(@cleanup, $cmd); michael@360: } michael@360: sub cleanup_perform { michael@360: foreach my $cmd (reverse @cleanup) { michael@360: &runcmd($cmd); michael@360: } michael@360: } michael@360: michael@360: # exception handling support michael@360: $SIG{__DIE__} = sub { michael@360: my ($err) = @_; michael@360: $err =~ s|\s+at\s+.*||s if (not $CF->{mode_verbose}); michael@360: print STDERR "$ME->{prog_name}:ERROR: $err ". ($! ? "($!)" : "") . "\n"; michael@360: &cleanup_perform() if (not $CF->{mode_verbose}); michael@360: exit(1); michael@360: }; michael@360: michael@360: # verbose message printing michael@360: sub verbose { michael@360: my ($msg) = @_; michael@360: print STDERR "++ $msg\n" if (not $CF->{mode_quiet}); michael@360: } michael@360: michael@360: # expand into a full filesystem path michael@360: sub fullpath { michael@360: my ($prog) = @_; michael@360: my $fullprog = ''; michael@360: foreach my $path (split(/:/, $ENV{PATH})) { michael@360: if (-x "$path/$prog") { michael@360: $fullprog = "$path/$prog"; michael@360: last; michael@360: } michael@360: } michael@360: return $fullprog; michael@360: } michael@360: michael@360: # execution of external commands michael@360: sub runcmd { michael@360: my ($cmd) = @_; michael@360: print STDERR "\$ $cmd\n" if ($CF->{mode_verbose}); michael@360: $cmd = "($cmd) >/dev/null 2>&1" if ($CF->{mode_quiet}); michael@360: return (system($cmd) == 0); michael@360: } michael@360: michael@360: # create a directory (plus its missing parent dirs) michael@360: sub mkdirp { michael@360: my ($dir) = @_; michael@360: my $pdir = $dir; michael@360: $pdir =~ s|/[^/]*$||s; michael@360: if (not -d $pdir) { michael@360: &mkdirp($pdir, 0755); michael@360: } michael@360: if (not -d $dir) { michael@360: &runcmd("umask 022 && mkdir $dir"); michael@360: } michael@360: } michael@360: michael@360: # command line parsing michael@360: Getopt::Long::Configure("bundling"); michael@360: my $result = GetOptions( michael@360: 'p|prefix=s' => \$CF->{path_prefix}, michael@360: 'l|libdir=s' => \$CF->{path_libdir}, michael@360: 't|tmpdir=s' => \$CF->{path_tmpdir}, michael@360: 'd|wrkdir=s' => \$CF->{path_wrkdir}, michael@360: 'r|buildroot=s' => \$CF->{path_buildroot}, michael@360: 'w|buildwork=s' => \$CF->{path_buildwork}, michael@360: 'R|rpm=s' => \$CF->{prog_rpm}, michael@360: 'P|perl=s' => \$CF->{prog_perl}, michael@360: 's|schema=s' => \$CF->{perl_schema}, michael@360: 'A|args=s' => \@{$CF->{perl_args}}, michael@360: 'I|stdin=s' => \$CF->{perl_stdin}, michael@360: 'F|files=s' => \$CF->{files_file}, michael@360: 'U|unquoted' => \$CF->{files_unquoted}, michael@360: 'n|pkgname=s' => \$CF->{pkg_name}, michael@360: 'q|quiet' => \$CF->{mode_quiet}, michael@360: 'v|verbose' => \$CF->{mode_verbose}, michael@360: 'V|version' => \$CF->{run_version}, michael@360: 'h|help' => \$CF->{run_help} michael@360: ) || die "option parsing failed"; michael@360: if ($CF->{run_help}) { michael@360: print "Usage: $ME->{prog_name} [options]\n" . michael@360: "Available options:\n" . michael@360: "\n" . michael@360: " -p, --prefix filesystem path to OpenPKG instance\n" . michael@360: " -l, --libdir filesystem path to Perl lib directory\n" . michael@360: " -t, --tmpdir filesystem path to temporary directory\n" . michael@360: " -d, --wrkdir filesystem path to working directory\n" . michael@360: " -r, --buildroot filesystem path to RPM build root directory\n" . michael@360: " -w, --buildwork filesystem path to RPM build work directory\n" . michael@360: " -R, --rpm filesystem path to RPM program\n" . michael@360: " -P, --perl filesystem path to Perl program\n" . michael@360: "\n" . michael@360: " -s, --schema Perl INSTALLDIRS schema\n" . michael@360: " -A, --args Perl Build.PL/Makefile.PL passed through arguments\n" . michael@360: " -I, --stdin filesystem path to connect to stdin\n" . michael@360: " -F, --files filesystem path to write RPM \%files list to\n" . michael@360: " -U, --unquoted output RPM \%files list in unquoted format\n" . michael@360: " -n, --pkgname name of involved RPM package\n" . michael@360: "\n" . michael@360: " -q, --quiet operate in quiet run-time mode\n" . michael@360: " -v, --verbose operate in verbose run-time mode\n" . michael@360: "\n" . michael@360: " -V, --version print out program version\n" . michael@360: " -h, --help print out program usage help\n"; michael@360: exit(0); michael@360: } michael@360: if ($CF->{run_version}) { michael@360: print "OpenPKG $ME->{prog_name} $ME->{prog_vers} ($ME->{prog_date})\n"; michael@360: exit(0); michael@360: } michael@360: michael@360: # fix configuration parameters michael@360: foreach my $cf (keys(%{$CF})) { michael@360: $CF->{$cf} =~ s|\%([A-Za-z_][A-Za-z0-9_]*)\%|$CF->{$1}|sge; michael@360: } michael@360: michael@360: # determine operation steps michael@360: my @steps_exist = qw(prepare configure build install fixate cleanup); michael@360: my @steps_run = (); michael@360: if (@ARGV > 0) { michael@360: foreach my $step (@ARGV) { michael@360: if (not grep { $_ eq $step } @steps_exist) { michael@360: die "operation step \"$step\" not existing"; michael@360: } michael@360: push(@steps_run, $step); michael@360: } michael@360: my $steps_exist = "-".join("-", @steps_exist)."-"; michael@360: my $steps_run = "-".join("-", @steps_run)."-"; michael@360: if ($steps_exist !~ m|^.*${steps_run}.*$|s) { michael@360: die "invalid operation step order \"".join(" ", @ARGV)."\""; michael@360: } michael@360: } michael@360: else { michael@360: @steps_run = @steps_exist; michael@360: } michael@360: michael@360: # friendly header ;-) michael@360: &verbose("OpenPKG $ME->{prog_name} $ME->{prog_vers} ($ME->{prog_date})"); michael@360: michael@360: # determine RPM program michael@360: if (not -x $CF->{prog_rpm}) { michael@360: $CF->{prog_rpm} = &fullpath($CF->{prog_rpm}); michael@360: } michael@360: my $V = `$CF->{prog_rpm} --version 2>/dev/null`; michael@360: $V =~ s/^(?:rpm \(OpenPKG RPM\)|RPM version|OpenPKG RPM|rpm\s+\(.+?\))\s+([0-9ab.]+)(\.(?:SNAPSHOT|DEVEL).*)?\s*$/$1/s || michael@360: die "program '$CF->{prog_rpm}' seems to be not RPM"; michael@360: &verbose("determined RPM program: $CF->{prog_rpm} ($V)"); michael@360: michael@360: # determine Perl program michael@360: if (not -x $CF->{prog_perl}) { michael@360: $CF->{prog_perl} = &fullpath($CF->{prog_perl}); michael@360: } michael@360: $V = `$CF->{prog_perl} --version 2>/dev/null`; michael@360: $V =~ s|^.*This is perl.+v?(5\.[\d+.]+).*$|$1|s || michael@360: die "program '$CF->{prog_perl}' seems to be not Perl"; michael@360: &verbose("determined Perl program: $CF->{prog_perl} ($V)"); michael@360: michael@360: # check for existing paths michael@360: if ($CF->{path_buildroot} eq '') { michael@360: die "RPM build root directory not known (specify one with option --buildroot)"; michael@360: } michael@360: if ($CF->{path_buildwork} eq '') { michael@360: die "RPM build work directory not known (specify one with option --buildwork)"; michael@360: } michael@360: mkdir($CF->{path_buildroot}, 0700); michael@360: mkdir($CF->{path_buildwork}, 0700); michael@360: michael@360: ## michael@360: ## OPERATION SEQUENCE michael@360: ## michael@360: michael@360: # establish standard environment michael@360: umask(022); michael@360: michael@360: # determine name of temporary directory michael@360: my $tmpdir = $CF->{path_tmpdir}; michael@360: $tmpdir =~ s|/+$||s; michael@360: my $user = (getlogin() || getpwuid($<) || $ENV{LOGNAME} || $ENV{USERNAME} || "unknown"); michael@360: my $program = $ME->{prog_name}; michael@360: my $package = ($CF->{pkg_name} || "unknown"); michael@360: $tmpdir .= "/$user-$program-$package"; michael@360: michael@360: # determine name of perl wrapper script michael@360: my $perlwrap = "$tmpdir/perl.sh"; michael@360: michael@360: # optionally change working directory michael@360: my $dir = $CF->{path_wrkdir}; michael@360: if ($dir ne '') { michael@360: if (not -d $dir) { michael@360: # be smart and guess correct directory to michael@360: # reduce special cases during packaging michael@360: $dir =~ s|^.+/||s; michael@360: my $parent = ""; michael@360: my $child = $dir; michael@360: $child =~ s|^(.+/)([^/]+)$|$parent = $1, $2|se; michael@360: LOOP: while ($child ne '') { michael@360: foreach my $dir (glob("${parent}${child}*")) { michael@360: if (-d "$parent$dir") { michael@360: $child = $dir; michael@360: last LOOP; michael@360: } michael@360: } michael@360: $child =~ s|\W\w+$||s || last; michael@360: last if (-d "$parent$child"); michael@360: } michael@360: $dir = "$parent$child"; michael@360: } michael@360: chdir($dir) || die "cannot change to working directory \"$dir\""; michael@360: } michael@360: michael@360: # determine Perl configuration michael@360: my $pcfg = {}; michael@360: my $cmd = "$CF->{prog_perl}" . michael@360: " -V:installarchlib -V:installprivlib" . michael@360: " -V:installsitearch -V:installsitelib -V:sitelib_stem" . michael@360: " -V:installvendorarch -V:installvendorlib -V:vendorlib_stem"; michael@360: my $out = `$cmd 2>/dev/null || true`; michael@360: $out =~ s|^(\S+)='([^'']*)';$|$pcfg->{$1} = $2, ''|mge; michael@360: michael@360: # ==== COMPAT prolog/epilog ==== michael@360: if (grep { $_ eq "prolog" or $_ eq "epilog" } @steps_run) { michael@360: print "This is the perl-openpkg >= 20040126 version.\n" . michael@360: "It was redesigned and is incompatible to previous\n" . michael@360: "versions. It does not support prolog/epilog steps.\n" . michael@360: "Please upgrade the package that uses perl-openpkg\n" . michael@360: "or, as a temporary workaround, downgrade perl-openpkg\n"; michael@360: die "package/perl-openpkg incompatiblity"; michael@360: } michael@360: michael@360: # ==== STEP: 1. prepare ==== michael@360: if (grep { $_ eq "prepare" } @steps_run) { michael@360: &verbose("step 1: prepare"); michael@360: michael@360: # establish temporary directory michael@360: system("rm -rf $tmpdir >/dev/null 2>&1"); michael@360: mkdir($tmpdir, 0700) || die "cannot create temporary directory '$tmpdir'"; michael@360: michael@360: # create Perl executable wrapper script michael@360: my $io = new IO::File ">$perlwrap" michael@360: || die "unable to open \"$perlwrap\" for writing"; michael@360: print $io michael@360: "#!/bin/sh\n" . michael@360: "exec $CF->{prog_perl} \\\n" . michael@360: " -I$CF->{path_buildroot}$pcfg->{installarchlib} \\\n" . michael@360: " -I$CF->{path_buildroot}$pcfg->{installprivlib} \\\n" . michael@360: " -I$CF->{path_buildroot}$pcfg->{installsitearch} \\\n" . michael@360: " -I$CF->{path_buildroot}$pcfg->{installsitelib} \\\n" . michael@360: " -I$CF->{path_buildroot}$pcfg->{installvendorarch} \\\n" . michael@360: " -I$CF->{path_buildroot}$pcfg->{installvendorlib} \\\n" . michael@360: " \"\$@\"\n"; michael@360: $io->close(); michael@360: &runcmd("chmod 755 $perlwrap"); michael@360: michael@360: # establish Perl module installation areas michael@360: &mkdirp("$CF->{path_buildroot}$pcfg->{installarchlib}"); michael@360: &mkdirp("$CF->{path_buildroot}$pcfg->{installprivlib}"); michael@360: &mkdirp("$CF->{path_buildroot}$pcfg->{installsitearch}"); michael@360: &mkdirp("$CF->{path_buildroot}$pcfg->{installsitelib}"); michael@360: &mkdirp("$CF->{path_buildroot}$pcfg->{installvendorarch}"); michael@360: &mkdirp("$CF->{path_buildroot}$pcfg->{installvendorlib}"); michael@360: } michael@360: michael@360: # ==== STEP: 2. configure ==== michael@360: if (grep { $_ eq "configure" } @steps_run) { michael@360: &verbose("step 2: configure"); michael@360: michael@360: # determine build environment and basic arguments michael@360: my $environment = ""; michael@360: my $perl_args = ''; michael@360: if (-f "Build.PL" and (system("$perlwrap -MModule::Build -e '1;' >/dev/null 2>&1") >> 8) == 0) { michael@360: # new-style Module::Build "Build.PL" michael@360: $perl_args .= " installdirs=$CF->{perl_schema}"; michael@360: $perl_args .= " --install_path libdoc=remove-me-later"; michael@360: $perl_args .= " destdir=$CF->{path_buildroot}"; michael@360: if ($CF->{path_prefix} ne '' and $CF->{path_prefix} ne '@l_prefix@') { michael@360: $perl_args .= " install_base=$CF->{path_prefix}"; michael@360: } michael@360: if ($CF->{path_libdir} ne '') { michael@360: $perl_args .= " --install_path lib=$CF->{path_libdir}"; michael@360: } michael@360: $environment = 'Module::Build'; michael@360: } michael@360: elsif (-f "Makefile.PL") { # ExtUtils::MakeMaker is part of the Perl distribution michael@360: # old-style ExtUtils::MakeMaker "Makefile.PL" michael@360: $perl_args .= " PERL=$perlwrap FULLPERL=$perlwrap"; michael@360: $perl_args .= " INSTALLDIRS=$CF->{perl_schema}"; michael@360: $perl_args .= " INSTALLMAN3DIR=none INSTALLSITEMAN3DIR=none INSTALLVENDORMAN3DIR=none"; michael@360: $perl_args .= " DESTDIR=$CF->{path_buildroot}"; michael@360: if ($CF->{path_prefix} ne '' and $CF->{path_prefix} ne '@l_prefix@') { michael@360: $perl_args .= " PREFIX=$CF->{path_prefix}"; michael@360: } michael@360: if ($CF->{path_libdir} ne '') { michael@360: $perl_args .= " LIB=$CF->{path_libdir}"; michael@360: } michael@360: $environment = 'ExtUtils::MakeMaker'; michael@360: } michael@360: else { michael@360: die "neither usable Module::Build \"Build.PL\" nor ExtUtils::MakeMaker \"Makefile.PL\" file found"; michael@360: } michael@360: michael@360: # determine build-time extra arguments michael@360: # (assuming that they are either work for both Module::Build and michael@360: # ExtUtils::MakeMaker or the supplier knows what is used by us) michael@360: if ($#{$CF->{perl_args}} >= 0) { michael@360: my $user_args = join(" ", @{$CF->{perl_args}}); michael@360: if ($user_args =~ m|#|) { michael@360: $user_args =~ s|#| $perl_args |; michael@360: $perl_args = $user_args; michael@360: } michael@360: else { michael@360: $perl_args .= " " . $user_args; michael@360: } michael@360: } michael@360: michael@360: # determine stdin michael@360: if ($CF->{perl_stdin} ne "-") { michael@360: $perl_args .= " <$CF->{perl_stdin}"; michael@360: } michael@360: michael@360: # setup the build environment michael@360: if ($environment eq 'Module::Build') { michael@360: &verbose("configuring module via Module::Build environment"); michael@360: &runcmd("chmod u+rw Build.PL"); michael@360: &runcmd("cp Build.PL Build.PL.orig"); michael@360: &runcmd("(cat Build.PL.orig; echo '') | sed -e \"s:\\\$^X:'$perlwrap':g\" >Build.PL"); michael@360: &runcmd("$perlwrap ./Build.PL $perl_args") michael@360: or die "failed to \"configure\""; michael@360: } michael@360: elsif ($environment eq 'ExtUtils::MakeMaker') { michael@360: &verbose("configuring module via ExtUtils::MakeMaker environment"); michael@360: &runcmd("chmod u+rw Makefile.PL"); michael@360: &runcmd("cp Makefile.PL Makefile.PL.orig"); michael@360: &runcmd("(cat Makefile.PL.orig; echo '') | sed -e \"s:\\\$^X:'$perlwrap':g\" >Makefile.PL"); michael@360: &runcmd("$perlwrap ./Makefile.PL $perl_args") michael@360: or die "failed to \"configure\""; michael@360: } michael@360: } michael@360: michael@360: # ==== STEP: 3. build ==== michael@360: if (grep { $_ eq "build" } @steps_run) { michael@360: &verbose("step 3: build"); michael@360: michael@360: if (-f "Build.PL" and -f "Build") { michael@360: # execute Build script michael@360: &verbose("building module via Module::Build environment"); michael@360: &runcmd("$perlwrap Build build") michael@360: or die "failed to \"build\""; michael@360: } michael@360: elsif (-f "Makefile.PL" and -f "Makefile") { michael@360: # execute Makefile procedure michael@360: &verbose("building module via ExtUtils::MakeMaker environment"); michael@360: my $make = `$CF->{prog_rpm} --eval '\%{l_make} \%{l_mflags}'`; michael@360: $make =~ s|\n+$||s; michael@360: my $make_args = "PERL=$perlwrap FULLPERL=$perlwrap"; michael@360: &runcmd("$make $make_args pure_all") michael@360: or die "failed to \"build\""; michael@360: } michael@360: else { michael@360: die "neither \"Build\" nor \"Makefile\" found in working directory"; michael@360: } michael@360: } michael@360: michael@360: # ==== STEP: 4. install ==== michael@360: if (grep { $_ eq "install" } @steps_run) { michael@360: &verbose("step 4: install"); michael@360: michael@360: if (-f "Build.PL" and -f "Build") { michael@360: # execute Build script michael@360: &verbose("installing module via Module::Build environment"); michael@360: &runcmd("$perlwrap Build install") michael@360: or die "failed to \"install\""; michael@360: &runcmd("rm -rf $CF->{path_buildroot}$CF->{path_prefix}/remove-me-later"); michael@360: } michael@360: elsif (-f "Makefile.PL" and -f "Makefile") { michael@360: # execute Makefile procedure michael@360: &verbose("installing module via ExtUtils::MakeMaker environment"); michael@360: my $make = `$CF->{prog_rpm} --eval '\%{l_make} \%{l_mflags}'`; michael@360: $make =~ s|\n+$||s; michael@360: my $make_args = "PERL=$perlwrap FULLPERL=$perlwrap"; michael@360: &runcmd("$make $make_args pure_install") michael@360: or die "failed to \"install\""; michael@360: } michael@360: else { michael@360: die "neither \"Build\" nor \"Makefile\" found in working directory"; michael@360: } michael@360: } michael@360: michael@360: # ==== STEP: 5. fixate ==== michael@360: if (grep { $_ eq "fixate" } @steps_run) { michael@360: &verbose("step 5: fixate"); michael@360: michael@360: # prune installation files michael@360: my $libdir; michael@360: if ($CF->{path_libdir} ne '') { michael@360: $libdir = "$CF->{path_buildroot}$CF->{path_libdir}"; michael@360: } michael@360: else { michael@360: $libdir = "$CF->{path_buildroot}$CF->{path_prefix}/lib/perl"; michael@360: } michael@360: &runcmd("find $libdir -name perllocal.pod -print | xargs rm -f"); michael@360: &runcmd("find $libdir -name .packlist -print | xargs rm -f"); michael@360: &runcmd("find $libdir -depth -type d -print | (xargs rmdir >/dev/null 2>&1 || true)"); michael@360: michael@360: # determine RPM installation file list michael@360: my @files = (); michael@360: if ($CF->{path_libdir} eq '') { michael@360: push(@files, '%not %dir '.$CF->{path_prefix}.'/lib/perl'); michael@360: push(@files, '%not %dir '.$pcfg->{installarchlib}.'/auto'); michael@360: push(@files, '%not %dir '.$pcfg->{installarchlib}); michael@360: push(@files, '%not %dir '.$pcfg->{installprivlib}.'/auto'); michael@360: push(@files, '%not %dir '.$pcfg->{installprivlib}); michael@360: push(@files, '%not %dir '.$pcfg->{sitelib_stem}); michael@360: push(@files, '%not %dir '.$pcfg->{installsitearch}.'/auto'); michael@360: push(@files, '%not %dir '.$pcfg->{installsitearch}); michael@360: push(@files, '%not %dir '.$pcfg->{installsitelib}.'/auto'); michael@360: push(@files, '%not %dir '.$pcfg->{installsitelib}); michael@360: push(@files, '%not %dir '.$pcfg->{vendorlib_stem}); michael@360: push(@files, '%not %dir '.$pcfg->{installvendorarch}.'/auto'); michael@360: push(@files, '%not %dir '.$pcfg->{installvendorarch}); michael@360: push(@files, '%not %dir '.$pcfg->{installvendorlib}.'/auto'); michael@360: push(@files, '%not %dir '.$pcfg->{installvendorlib}); michael@360: } michael@360: else { michael@360: push(@files, $CF->{path_libdir}); michael@360: } michael@360: michael@360: # output RPM installation file list michael@360: my $out; michael@360: if ($CF->{files_file} eq "-") { michael@360: $out = new IO::Handle; michael@360: $out->fdopen(fileno(STDOUT), "w"); michael@360: } michael@360: else { michael@360: $out = new IO::File ">$CF->{files_file}"; michael@360: } michael@360: if ($CF->{files_unquoted}) { michael@360: print $out join("\n", @files) . "\n"; michael@360: } michael@360: else { michael@360: print $out '"'. join('"'."\n".'"', @files).'"'."\n"; michael@360: } michael@360: $out->close(); michael@360: } michael@360: michael@360: # ==== STEP: 6. cleanup ==== michael@360: if (grep { $_ eq "cleanup" } @steps_run) { michael@360: &verbose("step 6: cleanup"); michael@360: michael@360: # remove temporary directory and its contents michael@360: &runcmd("rm -rf $tmpdir"); michael@360: } michael@360: michael@360: # die gracefully... michael@360: &verbose("cleaning up environment"); michael@360: &cleanup_perform(); michael@360: exit(0); michael@360: michael@360: __END__ michael@360: michael@360: ## michael@360: ## UNIX MANUAL PAGE michael@360: ## michael@360: michael@360: =pod michael@360: michael@360: =head1 NAME michael@360: michael@360: B - B michael@360: michael@360: =head1 SYNOPSIS michael@360: michael@360: B michael@360: [B<-p>|B<--prefix> I] michael@360: [B<-D>|B<--libdir> I] michael@360: [B<-t>|B<--tmpdir> I] michael@360: [B<-d>|B<--wrkdir> I] michael@360: [B<-r>|B<--buildroot> I] michael@360: [B<-w>|B<--buildwork> I] michael@360: [B<-R>|B<--rpm> I] michael@360: [B<-P>|B<--perl> I] michael@360: [B<-s>|B<--schema> I michael@360: [B<-A>|B<--args> I] michael@360: [B<-I>|B<--stdin> I] michael@360: [B<-F>|B<--files> I] michael@360: [B<-U>|B<--unquoted>] michael@360: [B<-n>|B<--pkgname> I] michael@360: [B<-q>|B<--quiet>] michael@360: [B<-v>|B<--verbose>] michael@360: [I ...] michael@360: michael@360: B michael@360: [B<-v>|B<--version>] michael@360: [B<-h>|B<--help>] michael@360: michael@360: =head1 DESCRIPTION michael@360: michael@360: The B program is an internal B packaging utility michael@360: for building C based Perl modules during the build michael@360: procedure of Perl module based B packages. It provides an michael@360: adjustable C environment. michael@360: michael@360: =head1 OPTIONS michael@360: michael@360: The following command line options are available: michael@360: michael@360: =head2 Filesystem Paths michael@360: michael@360: The following command-line options set various filesystem paths. michael@360: michael@360: =over 4 michael@360: michael@360: =item B<-p>, B<--prefix> I michael@360: michael@360: Filesystem path to OpenPKG instance. Default is C<@l_prefix@>. michael@360: michael@360: =item B<-l>, B<--libdir> I michael@360: michael@360: Filesystem path to Perl lib directory. Default is michael@360: "IC". michael@360: michael@360: =item B<-t>, B<--tmpdir> I michael@360: michael@360: Filesystem path to temporary directory. Default is C<$TMPDIR>, michael@360: as provided by the RPM build-time environment. michael@360: michael@360: =item B<-d>, B<--wrkdir> I michael@360: michael@360: Filesystem path to working directory. Default is current working directory michael@360: as provided by the RPM build-time environment. michael@360: michael@360: =item B<-r>, B<--buildroot> I michael@360: michael@360: Filesystem path to RPM build root directory. Default is C<$RPM_BUILD_ROOT>, michael@360: as provided by the RPM build-time environment. michael@360: michael@360: =item B<-w>, B<--buildwork> I michael@360: michael@360: Filesystem path to RPM build work directory. Default is C<$RPM_BUILD_DIR>, michael@360: as provided by the RPM build-time environment. michael@360: michael@360: =item B<-R>, B<--rpm> I michael@360: michael@360: Filesystem path to RPM program. Default is "IC". michael@360: michael@360: =item B<-P>, B<--perl> I michael@360: michael@360: Filesystem path to Perl program. Default is IC. michael@360: michael@360: =back michael@360: michael@360: =head2 OpenPKG Package Information michael@360: michael@360: The following command-line options set various package information. michael@360: michael@360: =over 4 michael@360: michael@360: =item B<-s>, B<--schema> I michael@360: michael@360: Sets the Perl C schema. Allowed values are michael@360: "C", "C" and "C". The default is "C". michael@360: michael@360: =item B<-A>, B<--args> I michael@360: michael@360: Sets additional arguments which are passed through on the "C" command line. This option can be specified multiple times, michael@360: args are joined with a space between them. If joined args contain a '#' then michael@360: it is substituted by the automatically generated args otherwise joined args michael@360: are appended to automatically generated args. Default is empty. michael@360: michael@360: =item B<-I>, B<--stdin> I michael@360: michael@360: Filesystem path to connect to F on the "C" michael@360: command line. Default is "C". A value of "C<->" means reading michael@360: from F. michael@360: michael@360: =item B<-F>, B<--files> I michael@360: michael@360: Filesystem path to write the RPM C<%files> entries to describing the michael@360: packaging list of all installed files. The default is "C<->" meaning michael@360: that the list is written to F. michael@360: michael@360: =item B<-U>, B<--unquoted> michael@360: michael@360: By default the RPM <%files> list is written with each path entry michael@360: enclosed in quotation marks. For raw post-processing, this option allows michael@360: the list to be written without enclosing quotation marks. michael@360: michael@360: =item B<-n>, B<--pkgname> I michael@360: michael@360: Name of involved RPM package. michael@360: michael@360: =back michael@360: michael@360: =head2 Run-Time Modes michael@360: michael@360: The following command-line options set various run-time modes. michael@360: michael@360: =over 4 michael@360: michael@360: =item B<-q>, B<--quiet> michael@360: michael@360: Operate in quiet run-time mode. michael@360: michael@360: =item B<-v>, B<--verbose> michael@360: michael@360: Operate in verbose run-time mode. michael@360: michael@360: =back michael@360: michael@360: =head2 Stand-Alone Operations michael@360: michael@360: The following command-line options trigger various stand-alone operations. michael@360: michael@360: =over 4 michael@360: michael@360: =item B<-V>, B<--version> michael@360: michael@360: Print program version only. michael@360: michael@360: =item B<-h>, B<--help> michael@360: michael@360: Print program usage help only. michael@360: michael@360: =back michael@360: michael@360: =head1 OPERATION STEPS michael@360: michael@360: The operation procedure of B is divided into the following michael@360: six distinguished steps: michael@360: michael@360: =over 3 michael@360: michael@360: =item B<1. prepare> michael@360: michael@360: This prepares the build environment by optionally creating a temporary michael@360: directory and establishing a Perl wrapper script. michael@360: This step can be shared between the configuration, building and installation michael@360: of multiple modules. michael@360: michael@360: =item B<2. configure> michael@360: michael@360: This configures the Perl module by performing the equivalent of michael@360: the command "C". This step has to be performed michael@360: individually for each particular module. michael@360: michael@360: =item B<3. build> michael@360: michael@360: This builds the Perl module by performing the equivalent of the command michael@360: "C". This step has to be performed individually for each michael@360: particular module. michael@360: michael@360: =item B<4. install> michael@360: michael@360: This installs the Perl module by performing the equivalent of the michael@360: command "C". This step has to be performed individually michael@360: for each particular module. michael@360: michael@360: =item B<5. fixate> michael@360: michael@360: This fixates the installed files by removing unnecessary ones, fixing michael@360: permissions and determining the resulting file list. This step can be michael@360: shared between the configuration, building and installation of multiple michael@360: modules. michael@360: michael@360: =item B<6. cleanup> michael@360: michael@360: This cleans up the build environment by removing all temporary files. michael@360: This step can be shared between the configuration, building and michael@360: installation of multiple modules. michael@360: michael@360: =back michael@360: michael@360: By default all operation steps are performed in sequence. Alternatively, michael@360: the sequence of steps can be individually specified on the command michael@360: line as one or more I arguments. The given sequence of Is michael@360: has to be exactly a contiguous sub-sequence of the sequence listed michael@360: above. As the extrem cases, it can be "C" (the same as not specifying any steps) or just perhaps michael@360: "C" (for executing only a particular step). michael@360: michael@360: =head1 EXAMPLE michael@360: michael@360: # packaging of single module michael@360: perl-openpkg michael@360: michael@360: # packaging of multiple modules michael@360: perl-openpkg prepare michael@360: perl-openpkg -d Foo-1 configure build install michael@360: perl-openpkg -d Bar-2 configure build install michael@360: perl-openpkg -d Baz-3 configure build install michael@360: perl-openpkg fixate cleanup michael@360: michael@360: =head1 HISTORY michael@360: michael@360: The B utility was originally implemented as a small michael@360: Bourne-Shell script for use in OpenPKG 1.1. It was later rewritten from michael@360: scratch in Perl for OpenPKG 2.0 and especially made more flexible to michael@360: reduce the complexity in numerious packages. michael@360: michael@360: =head1 SEE ALSO michael@360: michael@360: perl(1), "C". michael@360: michael@360: =head1 AUTHORS michael@360: michael@360: Ralf S. Engelschall Erse@engelschall.comE. michael@360: michael@360: =cut michael@360: