version 1.6, 2000/12/21 19:26:01
|
version 1.20, 2002/07/03 21:17:56
|
Line 1
|
Line 1
|
#!/usr/bin/perl |
#!/usr/bin/perl |
|
|
# Scott Harrison, September 30 |
# -------------------------------------------------------- Documentation notice |
# Automatically generate RPM listing files |
# Run "perldoc ./make_rpm.pl" in order to best view the software documentation |
# from file listing. |
# internalized in this program. |
|
|
# GNU General Public License, Version 2, June 1991 |
# --------------------------------------------------------- License Information |
# See http://www.gnu.org/copyleft/gpl.html. |
# The LearningOnline Network with CAPA |
|
# make_rpm.pl - make RedHat package manager file (A CLEAN AND CONFIGURABLE WAY) |
# This script does actually "build" the RPM. |
# |
|
# $Id$ |
# This script also generates and then deletes temporary |
# |
# files (and binary root directory tree) to build an RPM with. |
# Written by Scott Harrison, harris41@msu.edu |
|
# |
# I still need to implement the CONFIGURATION_FILES and |
# Copyright Michigan State University Board of Trustees |
# DOCUMENTATION_FILES portion of the command line interface to this |
# |
# script. |
# This file is part of the LearningOnline Network with CAPA (LON-CAPA). |
|
# |
# Take in a file list (from standard input), |
# LON-CAPA is free software; you can redistribute it and/or modify |
# a description tag and version tag from command line argument |
# it under the terms of the GNU General Public License as published by |
# and temporarily generate a: |
# the Free Software Foundation; either version 2 of the License, or |
# RPM .spec file |
# (at your option) any later version. |
# RPM Makefile |
# |
# SourceRoot |
# LON-CAPA is distributed in the hope that it will be useful, |
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
# A resulting .rpm file is generated. |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
# GNU General Public License for more details. |
unless (-e "/usr/lib/rpm/rpmrc") { |
# |
print <<END; |
# You should have received a copy of the GNU General Public License |
ERROR: This script only works with a properly installed RPM builder application. |
# along with LON-CAPA; if not, write to the Free Software |
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
# |
|
# http://www.lon-capa.org/ |
|
# |
|
# YEAR=2000 |
|
# 9/30,10/2,12/11,12/12,12/21 - Scott Harrison |
|
# YEAR=2001 |
|
# 1/8,1/10,1/13,1/23,5/16 - Scott Harrison |
|
# YEAR=2002 |
|
# 1/4,1/8,1/9,2/13,4/7 - Scott Harrison |
|
# |
|
### |
|
|
|
# make_rpm.pl automatically generate RPM software packages |
|
# from a target image directory and file listing. POD |
|
# documentation is at the end of this file. |
|
|
|
############################################################################### |
|
## ## |
|
## ORGANIZATION OF THIS PERL SCRIPT ## |
|
## ## |
|
## 1. Check to see if RPM builder application is available ## |
|
## 2. Read in command-line arguments ## |
|
## 3. Generate temporary directories (subdirs of first command-line argument)## |
|
## 4. Initialize some variables ## |
|
## 5. Create a stand-alone rpm building environment ## |
|
## 6. Perform variable initializations and customizations ## |
|
## 7. Print header information for .spec file ## |
|
## 8. Process file list and generate information ## |
|
## 9. Generate SRPM and BinaryRoot Makefiles ## |
|
## 10. mirror copy (BinaryRoot) files under a temporary directory ## |
|
## 11. roll everything into an rpm ## |
|
## 12. clean everything up ## |
|
## 13. subroutines ## |
|
## 13a. find_info - recursively gather information from a directory ## |
|
## 13b. grabtag - grab a tag from an XML string ## |
|
## 14. Plain Old Documentation ## |
|
## ## |
|
############################################################################### |
|
|
|
use strict; |
|
|
|
# ------------------------ Check to see if RPM builder application is available |
|
|
|
unless (-e '/usr/lib/rpm/rpmrc') { # part of the expected rpm software package |
|
print(<<END); |
|
**** ERROR **** This script only works with a properly installed RPM builder |
|
application. |
Cannot find /usr/lib/rpm/rpmrc, so cannot generate customized rpmrc file. |
Cannot find /usr/lib/rpm/rpmrc, so cannot generate customized rpmrc file. |
Script aborting. |
Script aborting. |
END |
END |
|
exit(1); |
} |
} |
|
|
my ($tag,$version,$configuration_files,$documentation_files,$pathprefix)=@ARGV; |
# ---------------------------------------------- Read in command-line arguments |
@ARGV=(); |
|
|
|
if (!$version) { |
my ($tag,$version,$configuration_files,$documentation_files, |
print "Usage: <TAG> <VERSION> [CONFIGURATION_FILES] [DOCUMENTATION] [PATHPREFIX]\n"; |
$pathprefix,$customize)=@ARGV; |
print "Standard input provides the list of files to work with.\n"; |
@ARGV=(); # read standard input based on a pipe, not a command-line argument |
print "TAG, required descriptive tag. For example, a kerberos software package might be tagged as \"krb4\".\n"; |
|
print "VERSION, required version. Needed to generate version information for the RPM. This should be in the format N.M where N and M are integers.\n"; |
# standardize pathprefix argument |
print "CONFIGURATION_FILES, optional comma-separated listing of files to be treated as configuration files by RPM (and thus subject to saving during RPM upgrades).\n"; |
$pathprefix=~s/\/$//; # OTHERWISE THE BEGINNING SLASH MIGHT BE REMOVED |
print "DOCUMENTATION, optional comma-separated listing of files to be treated as documentation files by RPM (and thus subject to being placed in the /usr/doc/RPM-NAME directory during RPM installation).\n"; |
|
print "PATHPREFIX, optional path to be removed from file listing. This is in case you are building an RPM from files elsewhere than root-level. Note, this still depends on a root directory hierarchy after PATHPREFIX.\n"; |
if (!$version) {# version should be defined and string length greater than zero |
exit; |
print(<<END); |
} |
See "perldoc make_rpm.pl" for more information. |
|
|
mkdir $tag,0755; |
Usage: |
mkdir "$tag/BuildRoot",0755; |
<STDIN> | perl make_rpm.pl <TAG> <VERSION> [CONFIGURATION_FILES] |
mkdir "$tag/SOURCES",0755; |
[DOCUMENTATION_FILES] [PATHPREFIX] [CUSTOMIZATION_XML] |
mkdir "$tag/SOURCES/LON-CAPA-$tag-$version",0755; |
|
mkdir "$tag/SPECS",0755; |
Standard input provides the list of files to work with. |
mkdir "$tag/BUILD",0755; |
TAG, required descriptive tag. For example, a kerberos software |
mkdir "$tag/SRPMS",0755; |
package might be tagged as "krb4". (This value is also used in |
mkdir "$tag/RPMS",0755; |
the generation of a temporary directory; you cannot have |
mkdir "$tag/RPMS/i386",0755; |
a pre-existing directory named ./TAG.) |
|
VERSION, required version. Needed to generate version information |
|
for the RPM. It is recommended that this be in the format N.M where N and |
|
M are integers. |
|
CONFIGURATION_FILES, optional comma-separated listing of files to |
|
be treated as configuration files by RPM (and thus subject to saving |
|
during RPM upgrades). |
|
DOCUMENTATION_FILES, optional comma-separated listing of files to be |
|
treated as documentation files by RPM (and thus subject to being |
|
placed in the /usr/doc/RPM-NAME directory during RPM installation). |
|
PATHPREFIX, optional path to be removed from file listing. This |
|
is in case you are building an RPM from files elsewhere than |
|
root-level. Note, this still depends on a root directory hierarchy |
|
after PATHPREFIX. |
|
CUSTOMIZATION_XML, allows for customizing various pieces of information such |
|
as vendor, summary, name, copyright, group, autoreqprov, requires, prereq, |
|
description, and pre-installation scripts (see more in the POD, |
|
"perldoc make_rpm.pl"). |
|
END |
|
exit(1); |
|
} |
|
|
|
# ----- Generate temporary directories (subdirs of first command-line argument) |
|
|
|
# Do some error-checking related to important first command-line argument. |
|
if ($tag=~/\W/) { # non-alphanumeric characters cause problems |
|
print(<<END); |
|
**** ERROR **** Invalid tag name "$tag" |
|
(The first command-line argument must be alphanumeric characters without |
|
spaces.) |
|
END |
|
exit(1); |
|
} |
|
if (-e $tag) { # do not overwrite or conflict with existing data |
|
print(<<END); |
|
**** ERROR **** a file or directory "./$tag" already exists |
|
(This program needs to generate a temporary directory named "$tag".) |
|
END |
|
exit(1); |
|
} |
|
|
|
print('Generating temporary directory ./'.$tag."\n"); |
|
mkdir($tag,0755) or die("**** ERROR **** cannot generate $tag directory\n"); |
|
mkdir("$tag/BuildRoot",0755); |
|
mkdir("$tag/SOURCES",0755); |
|
mkdir("$tag/SPECS",0755); |
|
mkdir("$tag/BUILD",0755); |
|
mkdir("$tag/SRPMS",0755); |
|
mkdir("$tag/RPMS",0755); |
|
mkdir("$tag/RPMS/i386",0755); |
|
|
|
# -------------------------------------------------------- Initialize variables |
|
|
my $file; |
my $file; |
my $binaryroot="$tag/BinaryRoot"; |
my $binaryroot=$tag.'/BinaryRoot'; |
my ($type,$size,$octalmode,$user,$group); |
my ($type,$size,$octalmode,$user,$group); |
|
|
$currentdir=`pwd`; chop $currentdir; $invokingdir=$currentdir; $currentdir.="/$tag"; |
my $currentdir=`pwd`; chomp($currentdir); my $invokingdir=$currentdir; |
|
$currentdir.='/'.$tag; |
|
|
open (IN,"</usr/lib/rpm/rpmrc") or die("Can't open /usr/lib/rpm/rpmrc"); |
# ------------------------------- Create a stand-alone rpm building environment |
@lines=<IN>; |
|
close IN; |
|
|
|
open (RPMRC,">$tag/SPECS/rpmrc"); |
print('Creating stand-alone rpm build environment.'."\n"); |
foreach $line (@lines) { |
open(IN,'</usr/lib/rpm/rpmrc') or die('Cannot open /usr/lib/rpm/rpmrc'."\n"); |
|
my @lines=<IN>; |
|
close(IN); |
|
|
|
open(RPMRC,">$tag/SPECS/rpmrc"); |
|
foreach my $line (@lines) { |
if ($line=~/^macrofiles/) { |
if ($line=~/^macrofiles/) { |
chop $line; |
chomp($line); |
$line.=":./rpmmacros\n"; |
$line.=":$currentdir/SPECS/rpmmacros\n"; |
} |
} |
print RPMRC $line; |
print(RPMRC $line); |
} |
} |
close RPMRC; |
close(RPMRC); |
|
|
open (RPMMACROS,">$tag/SPECS/rpmmacros"); |
open(RPMMACROS,">$tag/SPECS/rpmmacros"); |
print RPMMACROS <<END; |
print(RPMMACROS <<END); |
\%_topdir $currentdir |
\%_topdir $currentdir |
\%__spec_install_post \\ |
\%__spec_install_post \\ |
/usr/lib/rpm/brp-strip \\ |
/usr/lib/rpm/brp-strip \\ |
/usr/lib/rpm/brp-strip-comment-note \\ |
/usr/lib/rpm/brp-strip-comment-note \\ |
\%{nil} |
\%{nil} |
END |
END |
close RPMMACROS; |
close(RPMMACROS); |
|
|
|
# ------------------------- Perform variable initializations and customizations |
|
|
open (SPEC,">$tag/SPECS/LON-CAPA-$tag-$version.spec"); |
my $cu=''; # string that holds customization XML file contents |
|
if (length($customize)>0) { |
|
print('Reading in XML-formatted customizations from '.$customize."\n"); |
|
open(IN,"<$customize") or |
|
( |
|
print(`cd $invokingdir; rm -Rf $tag`) and |
|
die('Cannot open customization file "'.$customize.'"'."\n") |
|
); |
|
my @clines=(<IN>); |
|
$cu=join('',@clines); |
|
close(IN); |
|
} |
|
|
|
# tv - temporary variable (if it exists inside the XML document) then use it, |
|
# otherwise don't overwrite existing values of variables |
|
my $tv=''; |
|
|
|
# (Sure. We could use HTML::TokeParser here... but that wouldn't be fun now, |
|
# would it?) |
|
my $name=$tag; |
|
# read in name from customization if available |
|
$tv=grabtag('name',$cu,1); $name=$tv if $tv; |
|
$name=~s/\<tag \/\>/$tag/g; |
|
|
|
# (When in doubt, be paranoid about overwriting things.) |
|
if (-e "$name-$version-1.i386.rpm") { |
|
print(`cd $invokingdir; rm -Rf $tag`); # clean temporary filespace in use |
|
die("**** ERROR **** $name-$version-1.i386.rpm already exists.\n"); |
|
} |
|
|
print SPEC <<END; |
my $requires=''; |
Summary: Files for the $tag component of LON-CAPA. |
# read in relevant requires info from customization file (if applicable) |
Name: LON-CAPA-$tag |
# note that "PreReq: item" controls order of CD-ROM installation (if you |
|
# are making a customized CD-ROM) |
|
# "Requires: item" just enforces dependencies from the command-line invocation |
|
$tv=grabtag('requires',$cu,1); $requires=$tv if $tv; |
|
# do more require processing here |
|
$requires=~s/\s*\<\/item\>\s*//g; |
|
$requires=~s/\s*\<item\>\s*/\n/g; |
|
$requires=~s/^\s+//s; |
|
|
|
my $summary='Files for the '.$name.' software package.'; |
|
# read in summary from customization if available |
|
$tv=grabtag('summary',$cu,1); $summary=$tv if $tv; |
|
$summary=~s/\<tag \/\>/$tag/g; |
|
|
|
my $autoreqprov='no'; |
|
# read in autoreqprov from customization if available |
|
$tv=grabtag('autoreqprov',$cu,1); $autoreqprov=$tv if $tv; |
|
|
|
my $copyright="not specified here"; |
|
# read in copyright from customization if available |
|
$tv=grabtag('copyright',$cu,1); $copyright=$tv if $tv; |
|
$copyright=~s/\<tag \/\>/$tag/g; |
|
|
|
open(SPEC,">$tag/SPECS/$name-$version.spec"); |
|
|
|
my $vendor='Me'; |
|
# read in vendor from customization if available |
|
$tv=grabtag('vendor',$cu,1); $vendor=$tv if $tv; |
|
$vendor=~s/\<tag \/\>/$tag/g; |
|
|
|
my $description="$name software package"; |
|
# read in description from customization if available |
|
$tv=grabtag('description',$cu,0); $description=$tv if $tv; |
|
$description=~s/\<tag \/\>/$tag/g; |
|
|
|
my $pre=''; |
|
# read in pre-installation script if available |
|
$tv=grabtag('pre',$cu,0); $pre=$tv if $tv; |
|
$pre=~s/\<tag \/\>/$tag/g; |
|
|
|
# ------------------------------------- Print header information for .spec file |
|
print('Print header information for .spec file'."\n"); |
|
|
|
print(SPEC <<END); |
|
Summary: $summary |
|
Name: $name |
Version: $version |
Version: $version |
Release: 1 |
Release: 1 |
Vendor: Laboratory for Instructional Technology Education, Division of Science and Mathematics Education, Michigan State University. |
Vendor: $vendor |
BuildRoot: $currentdir/BuildRoot |
BuildRoot: $currentdir/BuildRoot |
Copyright: GNU General Public License. Version 2, June 1991. Michigan State University patents may apply. |
Copyright: $copyright |
Group: Utilities/System |
Group: Utilities/System |
Source: LON-CAPA-$tag-$version.tar.gz |
Source: $name-$version.tar.gz |
AutoReqProv: no |
AutoReqProv: $autoreqprov |
|
$requires |
# requires: filesystem |
# requires: filesystem |
\%description |
\%description |
This package is automatically generated by the make_rpm.pl perl |
$description |
script (written by the LON-CAPA development team, www.lon-capa.org, |
|
Scott Harrison). This implements the $tag component for LON-CAPA. |
|
For more on the LON-CAPA project, visit http://www.lon-capa.org/. |
|
|
|
\%prep |
\%prep |
\%setup |
\%setup |
Line 119 make ROOT="\$RPM_BUILD_ROOT" SOURCE="$cu
|
Line 295 make ROOT="\$RPM_BUILD_ROOT" SOURCE="$cu
|
make ROOT="\$RPM_BUILD_ROOT" SOURCE="$currentdir/BinaryRoot" links |
make ROOT="\$RPM_BUILD_ROOT" SOURCE="$currentdir/BinaryRoot" links |
|
|
\%pre |
\%pre |
echo "***********************************************************************" |
$pre |
echo "LON-CAPA LearningOnline with CAPA" |
|
echo "http://www.lon-capa.org/" |
|
echo "Gerd Kortemeyer, et al" |
|
echo "Laboratory for Instructional Technology Education" |
|
echo "Michigan State University" |
|
echo "General Public License, Version 2, June 1991" |
|
echo "** Michigan State University patents may apply **" |
|
echo " " |
|
echo "This installation assumes an installation of Redhat 6.2" |
|
echo " " |
|
echo "The server computer should be currently connected to the ethernet" |
|
echo " " |
|
echo "The files in this package are only those for the $tag component." |
|
echo "Configuration files are sometimes part of the LON-CAPA-base RPM." |
|
echo "***********************************************************************" |
|
|
|
\%post |
\%post |
\%postun |
\%postun |
Line 142 echo "**********************************
|
Line 303 echo "**********************************
|
\%files |
\%files |
END |
END |
|
|
foreach $file (<>) { |
# ------------------------------------ Process file list and gather information |
chop $file; |
print('Process standard input file list and gather information.'."\n"); |
|
|
|
my %BinaryRootMakefile; |
|
my %Makefile; |
|
my %dotspecfile; |
|
|
|
foreach my $file (<>) { |
|
chomp($file); |
my $comment=""; |
my $comment=""; |
if ($file=~/\s+\#(.*)$/) { |
if ($file=~/\s+\#(.*)$/) { |
$file=~s/\s+\#(.*)$//; |
$file=~s/\s+\#(.*)$//; |
$comment=$1; |
$comment=$1; |
} |
} |
my $config=""; |
my $directive=""; |
if ($comment=~/config/i) { |
if ($comment=~/config\(noreplace\)/) { |
$config="\%config "; |
$directive="\%config(noreplace) "; |
|
} |
|
elsif ($comment=~/config/) { |
|
$directive="\%config "; |
|
} |
|
elsif ($comment=~/doc/) { |
|
$directive="\%doc"; |
} |
} |
if (($type,$size,$octalmode,$user,$group)=find_info($file)) { |
if (($type,$size,$octalmode,$user,$group)=find_info($file)) { |
$octalmode="0" . $octalmode if length($octalmode)<4; |
$octalmode="0" . $octalmode if length($octalmode)<4; |
Line 159 foreach $file (<>) {
|
Line 333 foreach $file (<>) {
|
$file=~s/^$pathprefix//; |
$file=~s/^$pathprefix//; |
} |
} |
if ($type eq "files") { |
if ($type eq "files") { |
push @{$BinaryRootMakefile{$type}},"\tinstall -D -m $octalmode $pathprefix$file $binaryroot$file\n"; |
push(@{$BinaryRootMakefile{$type}},"\tinstall -D -m $octalmode ". |
push @{$Makefile{$type}},"\tinstall -D -m $octalmode \$(SOURCE)$file \$(ROOT)$file\n"; |
"$pathprefix$file $binaryroot$file\n"); |
push @{$dotspecfile{$type}},"$config\%attr($octalmode,$user,$group) $file\n"; |
push(@{$Makefile{$type}},"\tinstall -D -m $octalmode ". |
|
"\$(SOURCE)$file \$(ROOT)$file\n"); |
|
push(@{$dotspecfile{$type}},"$directive\%attr($octalmode,$user,". |
|
"$group) $file\n"); |
} |
} |
elsif ($type eq "directories") { |
elsif ($type eq "directories") { |
push @{$BinaryRootMakefile{$type}},"\tinstall -m $octalmode -d $binaryroot$file\n"; |
push(@{$BinaryRootMakefile{$type}},"\tinstall -m $octalmode -d ". |
push @{$Makefile{$type}},"\tinstall -m $octalmode -d \$(SOURCE)$file \$(ROOT)$file\n"; |
"$binaryroot$file\n"); |
push @{$dotspecfile{$type}},"\%dir \%attr($octalmode,$user,$group) $file\n"; |
push(@{$Makefile{$type}},"\tinstall -m $octalmode -d ". |
|
"\$(SOURCE)$file \$(ROOT)$file\n"); |
|
push(@{$dotspecfile{$type}},"\%dir \%attr($octalmode,$user,". |
|
"$group) $file\n"); |
} |
} |
elsif ($type eq "links") { |
elsif ($type eq "links") { |
my $link=$size; # I use the size variable to pass the link value from the subroutine find_info |
my $link=$size; # I use the size variable to pass the link value |
|
# from the subroutine find_info |
$link=~s/^$pathprefix//; |
$link=~s/^$pathprefix//; |
push @{$BinaryRootMakefile{$type}},"\tln -s $link $binaryroot$file\n"; |
push(@{$BinaryRootMakefile{$type}}, |
push @{$Makefile{$type}},"\tln -s $link \$(ROOT)$file\n"; |
"\tln -s $link $binaryroot$file\n"); |
push @{$dotspecfile{$type}},"\%attr(-,$user,$group) $file\n"; |
push(@{$Makefile{$type}},"\tln -s $link \$(ROOT)$file\n"); |
|
push(@{$dotspecfile{$type}},"\%attr(-,$user,$group) $file\n"); |
} |
} |
} |
} |
} |
} |
|
|
open OUT, ">$tag/SOURCES/LON-CAPA-$tag-$version/Makefile"; |
# -------------------------------------- Generate SRPM and BinaryRoot Makefiles |
open OUT2, ">$tag/BinaryRootMakefile"; |
print('Generate SRPM and BinaryRoot Makefiles.'."\n"); |
|
|
|
# Generate a much needed directory. |
|
# This directory is meant to hold all source code information |
|
# necessary for converting .src.rpm files into .i386.rpm files. |
|
mkdir("$tag/SOURCES/$name-$version",0755); |
|
|
|
open(OUTS,">$tag/SOURCES/$name-$version/Makefile"); |
|
open(OUTB, ">$tag/BinaryRootMakefile"); |
foreach $type ("directories","files","links") { |
foreach $type ("directories","files","links") { |
print OUT "$type\:\n"; |
print(OUTS "$type\:\n"); |
print OUT join("",@{$Makefile{$type}}); |
print(OUTS join("",@{$Makefile{$type}})) if $Makefile{$type}; |
print OUT "\n"; |
print(OUTS "\n"); |
print OUT2 "$type\:\n"; |
print(OUTB "$type\:\n"); |
print OUT2 join("",@{$BinaryRootMakefile{$type}}); |
print(OUTB join("",@{$BinaryRootMakefile{$type}})) |
print OUT2 "\n"; |
if $BinaryRootMakefile{$type}; |
print SPEC join("",@{$dotspecfile{$type}}); |
print(OUTB "\n"); |
|
print(SPEC join("",@{$dotspecfile{$type}})) if $dotspecfile{$type}; |
} |
} |
close OUT2; |
close(OUTB); |
close OUT; |
close(OUTS); |
|
|
|
close(SPEC); |
|
|
close SPEC; |
# ------------------ mirror copy (BinaryRoot) files under a temporary directory |
|
print('Mirror copy (BinaryRoot) files.'."\n"); |
|
|
`make -f $tag/BinaryRootMakefile directories`; |
`make -f $tag/BinaryRootMakefile directories`; |
`make -f $tag/BinaryRootMakefile files`; |
`make -f $tag/BinaryRootMakefile files`; |
`make -f $tag/BinaryRootMakefile links`; |
`make -f $tag/BinaryRootMakefile links`; |
|
|
print `cd $currentdir/SOURCES; tar czvf LON-CAPA-$tag-$version.tar.gz LON-CAPA-$tag-$version`; |
# ------------------------------------------------- roll everything into an RPM |
print `cd $currentdir/SPECS; rpm --rcfile=./rpmrc -ba LON-CAPA-$tag-$version.spec; cd ../RPMS/i386; cp LON-CAPA-$tag-$version-1.i386.rpm $invokingdir/.`; |
print('Build a tarball and then run the rpm -ba command.'."\n"); |
print `cd $invokingdir; rm -Rf $tag`; |
my $command="cd $currentdir/SOURCES; tar czvf $name-$version.tar.gz ". |
|
"$name-$version"; |
|
print(`$command`); |
|
$command="cd $currentdir/SPECS; rpm --rcfile=./rpmrc -ba ". |
|
"$name-$version.spec; cd ../RPMS/i386; cp -v ". |
|
"$name-$version-1.i386.rpm $invokingdir/."; |
|
print(`$command`); |
|
|
|
# --------------------------------------------------------- clean everything up |
|
print('Removing temporary ./'.$tag.' directory'."\n"); |
|
print(`cd $invokingdir; rm -Rf $tag`); |
|
|
|
# -------------------------------------------------------- Yeah! We're all done |
|
print('Success. Script complete.'."\n"); |
|
|
|
# ----------------------------------------------------------------- SUBROUTINES |
|
# ----- Subroutine: find_info - recursively gather information from a directory |
sub find_info { |
sub find_info { |
# only look for |
|
my ($file)=@_; |
my ($file)=@_; |
my $line; |
my $line=''; |
if (($line=`find $file -type f -prune`)=~/^$file\n/) { |
if (($line=`find $file -type f -prune`)=~/^$file\n/) { |
$line=`find $file -type f -prune -printf "\%s\t\%m\t\%u\t\%g"`; |
$line=`find $file -type f -prune -printf "\%s\t\%m\t\%u\t\%g"`; |
return ("files",split(/\t/,$line)); |
return("files",split(/\t/,$line)); |
} |
} |
elsif (($line=`find $file -type d -prune`)=~/^$file\n/) { |
elsif (($line=`find $file -type d -prune`)=~/^$file\n/) { |
$line=`find $file -type d -prune -printf "\%s\t\%m\t\%u\t\%g"`; |
$line=`find $file -type d -prune -printf "\%s\t\%m\t\%u\t\%g"`; |
return ("directories",split(/\t/,$line)); |
return("directories",split(/\t/,$line)); |
} |
} |
elsif (($line=`find $file -type l -prune`)=~/^$file\n/) { |
elsif (($line=`find $file -type l -prune`)=~/^$file\n/) { |
$line=`find $file -type l -prune -printf "\%l\t\%m\t\%u\t\%g"`; |
$line=`find $file -type l -prune -printf "\%l\t\%m\t\%u\t\%g"`; |
return ("links",split(/\t/,$line)); |
return("links",split(/\t/,$line)); |
} |
} |
|
die("**** ERROR **** $file is neither a directory, soft link, or file.\n"); |
|
} |
|
|
|
# ------------------------- Subroutine: grabtag - grab a tag from an xml string |
|
sub grabtag { |
|
my ($tag,$text,$clean)=@_; |
|
# meant to be quick and dirty as opposed to a formal state machine parser |
|
my $value=''; |
|
$cu=~/\<$tag\>(.*?)\<\/$tag\>/s; |
|
$value=$1; $value=~s/^\s+//; |
|
if ($clean==1) { |
|
$value=~s/\n\s/ /g; |
|
$value=~s/\s\n/ /g; |
|
$value=~s/\n/ /g; |
|
$value=~s/\s+$//; |
|
} |
|
return($value); |
} |
} |
|
|
|
# ----------------------------------------------------- Plain Old Documentation |
|
|
|
=pod |
|
|
|
=head1 NAME |
|
|
|
make_rpm.pl - cleanly generate an rpm in a simple one-line command |
|
|
|
=head1 SYNOPSIS |
|
|
|
Usage: <STDIN> | make_rpm.pl <TAG> <VERSION> |
|
[CONFIGURATION_FILES] [DOCUMENTATION_FILES] |
|
[PATHPREFIX] [CUSTOMIZATION_XML] |
|
|
|
=head2 The standard input stream |
|
|
|
I<STDIN>, the standard input stream, provides the list of files to work |
|
with. This list of file names must give the complete filesystem |
|
path starting from '/'. |
|
|
|
=over 4 |
|
|
|
=item * For instance, the following is invalid: |
|
|
|
romeodir/file1.txt # ** INVALID! ** missing leading filesystem path |
|
romeodir/file2.txt |
|
romeodir/file3.txt |
|
|
|
=item * Whereas, the following is valid: |
|
|
|
/home/joe/romeodir/file1.txt |
|
/home/joe/romeodir/file2.txt |
|
/home/joe/romeodir/file3.txt |
|
|
|
=item * In terms of the B<find> command, |
|
|
|
"find romeodir | perl make_rpm.pl [COMMAND-LINE ARGUMENTS]" |
|
|
|
is incorrect, whereas |
|
|
|
"find /home/joe/romeodir |perl make_rpm.pl [COMMAND-LINE ARGUMENTS]" |
|
|
|
or |
|
|
|
"find `pwd`/romeodir |perl make_rpm.pl [COMMAND-LINE ARGUMENTS]" |
|
|
|
is correct. |
|
|
|
=back |
|
|
|
The standard input stream can also |
|
specify configuration files and documentation files through |
|
'#'-style commenting. |
|
|
|
For example, the following file listing encodes some of these directives: |
|
|
|
/home/joe/romeodir/buildloc/etc/romeo/user.conf # config(noreplace) |
|
/home/joe/romeodir/buildloc/etc/romeo/juliet.conf # config |
|
/home/joe/romeodir/buildloc/doc/man/man.1/romeo.1 # doc |
|
/home/joe/romeodir/buildloc/doc/man/man.1/romeo_talks.1 # doc |
|
/home/joe/romeodir/buildloc/usr/local/bin/where_art_thou |
|
/home/joe/romeodir/buildloc/usr/local/bin/romeo_talks |
|
|
|
The I<config> directive controls how files are replaced |
|
and/or backed up when a user attempts to install (B<rpm -i>) the F<.rpm> |
|
file generated by B<make_rpm.pl>. The I<doc> directive controls how a |
|
given file is placed inside special documentation directories |
|
on the filesystem during rpm installation (B<rpm -i>). |
|
(If you want to learn more on how the B<rpm> tool gives configuration and |
|
documentation files special treatment, you should read about "Directives" |
|
in Edward Bailey's well-known "Maximum RPM" book available online |
|
at http://www.rpm.org/max-rpm/s1-rpm-inside-files-list-directives.html.) |
|
|
|
=head2 Description of command-line arguments |
|
|
|
I<TAG> ($tag), B<required> descriptive tag. For example, a kerberos software |
|
package might be tagged as "krb4". |
|
|
|
I<VERSION> ($version), B<required> version. Needed to generate version |
|
information for the RPM. This should be in the format N.M where N and M are |
|
integers. |
|
|
|
I<CONFIGURATION_FILES>, B<optional> comma-separated listing of files to |
|
be treated as configuration files by RPM (and thus subject to saving |
|
during RPM upgrades). Configuration files can also be specified in |
|
the standard input stream (as described in L<"The standard input stream">). |
|
|
|
I<DOCUMENTATION_FILES>, B<optional> comma-separated listing of files to be |
|
treated as documentation files by RPM (and thus subject to being |
|
placed in the F</usr/doc/RPM-NAME> directory during RPM installation). |
|
Documentation files can also be specified in |
|
the standard input stream (as described in L<"The standard input stream">). |
|
|
|
I<PATHPREFIX>, B<optional> path to be removed from file listing. This |
|
is in case you are building an RPM from files elsewhere than |
|
root-level. Note, this still depends on a root directory hierarchy |
|
after PATHPREFIX. |
|
|
|
I<CUSTOMIZATION_XML>, B<optional> filename where XML-ish information exists. |
|
Allows for customizing various pieces of information such |
|
as vendor, summary, name, copyright, group, autoreqprov, requires, prereq, |
|
description, and pre-installation scripts |
|
(see L<"Customizing descriptive data of your RPM software package">). |
|
|
|
=head2 Examples |
|
|
|
bash$ find /notreallyrootdir | perl make_rpm.pl \ |
|
makemoney 3.1 '' \ |
|
'/usr/doc/man/man3/makemoney.3' \ |
|
/notreallyrootdir |
|
would generate makemoney-3.1-1.i386.rpm |
|
|
|
bash$ find /usr/local/bin | \ |
|
perl make_rpm.pl mybinfiles 1.0 |
|
would generate mybinfiles-1.0-1.i386.rpm |
|
|
|
bash$ find /home/joe/romeodir/buildloc | \ |
|
perl make_rpm.pl romeo \ |
|
1.0 '' '' '/home/joe/romeodir/buildloc' customize.xml |
|
would generate romeo with customizations from customize.xml. |
|
|
|
The I<CUSTOMIZATION_XML> argument represents a way to customize the |
|
numerous variables associated with RPMs. This argument represents |
|
a file name. (Parsing is done in an unsophisticated fashion using |
|
regular expressions.) See |
|
L<"Customizing descriptive data of your RPM software package">. |
|
|
|
=head1 Customizing descriptive data of your RPM software package |
|
|
|
RPMS can be (and often are) packaged with descriptive data |
|
describing authorship, dependencies, descriptions, etc. |
|
|
|
The following values can be tagged inside an XML file |
|
(specified by the 6th command-line argument) |
|
and made part of the RPM package information |
|
(B<rpm -qi E<lt>package-nameE<gt>>). |
|
|
|
=over 4 |
|
|
|
=item * vendor |
|
|
|
=item * summary |
|
|
|
=item * name |
|
|
|
(overrides the <TAG> argument value; see |
|
L<"Description of command-line arguments>) |
|
|
|
=item * copyright |
|
|
|
=item * group |
|
|
|
(the software package group; |
|
e.g. Applications/System, User Interface/X, Development/Libraries, |
|
etc.) |
|
|
|
=item * requires |
|
|
|
Contains all the dependency information (see the example below). |
|
|
|
=item * description |
|
|
|
=item * pre |
|
|
|
Commands to be executed prior to software package installation. |
|
|
|
=back |
|
|
|
Here is an example (note that B<make_rpm.pl> automatically substitutes |
|
any "<tag />" string with the first command-line argument described |
|
in L<"Description of command-line arguments">): |
|
|
|
<vendor> |
|
Laboratory for Instructional Technology Education, Division of |
|
Science and Mathematics Education, Michigan State University. |
|
</vendor> |
|
<summary>Files for the <tag /> component of LON-CAPA</summary> |
|
<name>LON-CAPA-<tag /></name> |
|
<copyright>Michigan State University patents may apply.</copyright> |
|
<group>Utilities/System</group> |
|
<AutoReqProv>no</AutoReqProv> |
|
<requires tag='setup'> |
|
<item>PreReq: setup</item> |
|
<item>PreReq: passwd</item> |
|
<item>PreReq: util-linux</item> |
|
</requires> |
|
<requires tag='base'> |
|
<item>PreReq: LON-CAPA-setup</item> |
|
<item>PreReq: apache</item> |
|
<item>PreReq: /etc/httpd/conf/access.conf</item> |
|
</requires> |
|
<requires> |
|
<item>Requires: LON-CAPA-base</item> |
|
</requires> |
|
<description> |
|
This package is automatically generated by the make_rpm.pl perl |
|
script (written by the LON-CAPA development team, www.lon-capa.org, |
|
Scott Harrison). This implements the <tag /> component for LON-CAPA. |
|
For more on the LON-CAPA project, visit http://www.lon-capa.org/. |
|
</description> |
|
<pre> |
|
echo "************************************************************" |
|
echo "LON-CAPA LearningOnline with CAPA" |
|
echo "http://www.lon-capa.org/" |
|
echo " " |
|
echo "Laboratory for Instructional Technology Education" |
|
echo "Michigan State University" |
|
echo " " |
|
echo "** Michigan State University patents may apply **" |
|
echo " " |
|
echo "This installation assumes an installation of Redhat 6.2" |
|
echo " " |
|
echo "The files in this package are for the <tag /> component." |
|
echo "***********************************************************" |
|
</pre> |
|
|
|
=head1 DESCRIPTION |
|
|
|
Automatically generate an RPM software package from a list of files. |
|
|
|
B<make_rpm.pl> builds the RPM in a very clean and configurable fashion. |
|
(Finally! Making RPMs outside of F</usr/src/redhat> without a zillion |
|
file intermediates left over!) |
|
|
|
B<make_rpm.pl> generates and then deletes temporary |
|
files needed to build an RPM with. |
|
It works cleanly and independently from pre-existing |
|
directory trees such as F</usr/src/redhat/*>. |
|
|
|
Input to the script is simple. B<make_rpm.pl> accepts five kinds of |
|
information, three of which are mandatory: |
|
|
|
=over 4 |
|
|
|
=item * |
|
|
|
(required) a list of files that are to be part of the software package; |
|
|
|
=item * |
|
|
|
(required) the absolute filesystem location of these files |
|
(see L<"The standard input stream">); |
|
|
|
=item * |
|
|
|
(required) a descriptive tag and a version tag for the naming of the |
|
RPM software package; |
|
|
|
=item * |
|
|
|
(optional) documentation and configuration files; |
|
|
|
=item * |
|
|
|
and (optional) an XML file that defines the additional metadata |
|
associated with the RPM software package. |
|
|
|
=back |
|
|
|
A temporary directory named $tag (first argument described in |
|
L<"Description of command-line arguments">) is |
|
|
|
=over 4 |
|
|
|
=item * |
|
|
|
generated under the directory from which you run B<make_rpm.pl>. |
|
|
|
For example, user "joe" running |
|
|
|
cat file_list.txt | make_rpm.pl krb4 1.0 |
|
|
|
would temporarily generate F</home/joe/krb4/>. |
|
|
|
=item * |
|
|
|
F</home/joe/krb4/> is deleted after the *.rpm |
|
file is generated. |
|
|
|
=back |
|
|
|
The RPM will typically be named $name-$version.i386.rpm |
|
where $name=$tag. (The $name can be overridden in the customization |
|
XML file; see |
|
L<"Customizing descriptive data of your RPM software package">.) |
|
|
|
Here are some of the items are generated inside |
|
the $tag directory during the construction of an RPM: |
|
|
|
=over 4 |
|
|
|
=item * |
|
|
|
RPM .spec file (F<./$tag/SPECS/$name-$version.spec>) |
|
|
|
=item * |
|
|
|
RPM Makefile (F<./$tag/SOURCES/$name-$version/Makefile>) |
|
|
|
This is the Makefile that is called by the rpm |
|
command in building the .i386.rpm from the .src.rpm. |
|
The following directories are generated and/or used: |
|
|
|
=over 4 |
|
|
|
=item * |
|
|
|
SOURCE directory: F<./$tag/BinaryRoot/> |
|
|
|
=item * |
|
|
|
TARGET directory: F<./$tag/BuildRoot/> |
|
|
|
=back |
|
|
|
=item * |
|
|
|
BinaryRootMakefile (F<./$tag/BinaryRootMakefile>) |
|
|
|
This is the Makefile that this script creates and calls |
|
to build the F<$tag/BinaryRoot/> directory from the existing |
|
filesystem. |
|
The following directories are generated and/or used: |
|
|
|
=over 4 |
|
|
|
=item * |
|
|
|
SOURCE directory: / (your entire filesystem) |
|
|
|
=item * |
|
|
|
TARGET directory: F<./$tag/BinaryRoot/> |
|
|
|
=back |
|
|
|
=back |
|
|
|
The final output of B<make_rpm.pl> is a binary F<.rpm> file. |
|
The F<./tag> directory is deleted (along with the F<.src.rpm> |
|
file). The typical file name generated by B<make_rpm.pl> is |
|
F<$tag-$version.i386.rpm>. |
|
|
|
B<make_rpm.pl> is compatible with either rpm version 3.* or rpm version 4.*. |
|
|
|
=head1 README |
|
|
|
Automatically generate an RPM software package from a list of files. |
|
|
|
B<make_rpm.pl> builds the RPM in a very clean and configurable fashion. |
|
(Making RPMs "the simple way" in a one-line command.) |
|
|
|
B<make_rpm.pl> generates and then deletes temporary |
|
files (and binary root directory tree) to build an RPM with. |
|
It is designed to work cleanly and independently from pre-existing |
|
directory trees such as /usr/src/redhat/*. |
|
|
|
=head1 PREREQUISITES |
|
|
|
This script requires the C<strict> module. |
|
|
|
=head1 AUTHOR |
|
|
|
Scott Harrison |
|
harris41@msu.edu |
|
|
|
Please let me know how/if you are finding this script useful and |
|
any/all suggestions. -Scott |
|
|
|
=head1 LICENSE |
|
|
|
Written by Scott Harrison, harris41@msu.edu |
|
|
|
Copyright Michigan State University Board of Trustees |
|
|
|
This file is part of the LearningOnline Network with CAPA (LON-CAPA). |
|
|
|
This is free software; you can redistribute it and/or modify |
|
it under the terms of the GNU General Public License as published by |
|
the Free Software Foundation; either version 2 of the License, or |
|
(at your option) any later version. |
|
|
|
This file is distributed in the hope that it will be useful, |
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
GNU General Public License for more details. |
|
|
|
The GNU Public License is available for review at |
|
http://www.gnu.org/copyleft/gpl.html. |
|
|
|
For information on the LON-CAPA project, please visit |
|
http://www.lon-capa.org/. |
|
|
|
=head1 OSNAMES |
|
|
|
Linux |
|
|
|
=head1 SCRIPT CATEGORIES |
|
|
|
UNIX/System_administration |
|
|
|
=cut |
|
|