Annotation of loncom/build/make_rpm.pl, revision 1.16
1.1 harris41 1: #!/usr/bin/perl
2:
1.16 ! harris41 3: # -------------------------------------------------------- Documentation notice
! 4: # Run "perldoc ./make_rpm.pl" in order to best view the software documentation
! 5: # internalized in this program.
! 6:
! 7: # --------------------------------------------------------- License Information
1.12 harris41 8: # The LearningOnline Network with CAPA
1.13 harris41 9: # make_rpm.pl - make RedHat package manager file (A CLEAN AND CONFIGURABLE WAY)
1.12 harris41 10: #
1.16 ! harris41 11: # $Id: make_rpm.pl,v 1.15 2002/02/16 19:53:46 harris41 Exp $
1.12 harris41 12: #
13: # Written by Scott Harrison, harris41@msu.edu
14: #
15: # Copyright Michigan State University Board of Trustees
16: #
17: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
18: #
19: # LON-CAPA is free software; you can redistribute it and/or modify
20: # it under the terms of the GNU General Public License as published by
21: # the Free Software Foundation; either version 2 of the License, or
22: # (at your option) any later version.
23: #
24: # LON-CAPA is distributed in the hope that it will be useful,
25: # but WITHOUT ANY WARRANTY; without even the implied warranty of
26: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27: # GNU General Public License for more details.
28: #
29: # You should have received a copy of the GNU General Public License
30: # along with LON-CAPA; if not, write to the Free Software
31: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32: #
33: # http://www.lon-capa.org/
34: #
35: # YEAR=2000
36: # 9/30,10/2,12/11,12/12,12/21 - Scott Harrison
37: # YEAR=2001
38: # 1/8,1/10,1/13,1/23,5/16 - Scott Harrison
39: # YEAR=2002
1.16 ! harris41 40: # 1/4,1/8,1/9,2/13,4/7 - Scott Harrison
1.12 harris41 41: #
42: ###
43:
1.15 harris41 44: # make_rpm.pl automatically generate RPM software packages
45: # from a target image directory and file listing. POD
46: # documentation is at the end of this file.
1.1 harris41 47:
1.13 harris41 48: ###############################################################################
49: ## ##
50: ## ORGANIZATION OF THIS PERL SCRIPT ##
51: ## ##
52: ## 1. Check to see if RPM builder application is available ##
1.16 ! harris41 53: ## 2. Read in command-line arguments ##
! 54: ## 3. Generate temporary directories (subdirs of first command-line argument)##
1.13 harris41 55: ## 4. Initialize some variables ##
1.16 ! harris41 56: ## 5. Create a stand-alone rpm building environment ##
1.13 harris41 57: ## 6. Perform variable initializations and customizations ##
58: ## 7. Print header information for .spec file ##
59: ## 8. Process file list and generate information ##
60: ## 9. Generate SRPM and BinaryRoot Makefiles ##
61: ## 10. mirror copy (BinaryRoot) files under a temporary directory ##
62: ## 11. roll everything into an rpm ##
63: ## 12. clean everything up ##
1.15 harris41 64: ## 13. subroutines ##
65: ## 13a. find_info - recursively gather information from a directory ##
66: ## 13b. grabtag - grab a tag from an XML string ##
1.13 harris41 67: ## 14. Plain Old Documentation ##
68: ## ##
69: ###############################################################################
70:
71: use strict;
72:
73: # ------------------------ Check to see if RPM builder application is available
74:
1.16 ! harris41 75: unless (-e '/usr/lib/rpm/rpmrc') { # part of the expected rpm software package
! 76: print(<<END);
! 77: **** ERROR **** This script only works with a properly installed RPM builder
1.12 harris41 78: application.
1.1 harris41 79: Cannot find /usr/lib/rpm/rpmrc, so cannot generate customized rpmrc file.
80: Script aborting.
81: END
1.16 ! harris41 82: exit(1);
1.1 harris41 83: }
84:
1.16 ! harris41 85: # ---------------------------------------------- Read in command-line arguments
1.13 harris41 86:
87: my ($tag,$version,$configuration_files,$documentation_files,
88: $pathprefix,$customize)=@ARGV;
1.16 ! harris41 89: @ARGV=(); # read standard input based on a pipe, not a command-line argument
1.3 harris41 90:
1.16 ! harris41 91: if (!$version) {# version should be defined and string length greater than zero
! 92: print(<<END);
1.13 harris41 93: See "perldoc make_rpm.pl" for more information.
94:
1.15 harris41 95: Usage:
96: <STDIN> | perl make_rpm.pl <TAG> <VERSION> [CONFIGURATION_FILES]
1.13 harris41 97: [DOCUMENTATION_FILES] [PATHPREFIX] [CUSTOMIZATION_XML]
1.15 harris41 98:
1.13 harris41 99: Standard input provides the list of files to work with.
100: TAG, required descriptive tag. For example, a kerberos software
1.16 ! harris41 101: package might be tagged as "krb4". (This value is also used in
! 102: the generation of a temporary directory; you cannot have
! 103: a pre-existing directory named ./TAG.)
1.13 harris41 104: VERSION, required version. Needed to generate version information
1.16 ! harris41 105: for the RPM. It is recommended that this be in the format N.M where N and
! 106: M are integers.
1.13 harris41 107: CONFIGURATION_FILES, optional comma-separated listing of files to
108: be treated as configuration files by RPM (and thus subject to saving
109: during RPM upgrades).
110: DOCUMENTATION_FILES, optional comma-separated listing of files to be
111: treated as documentation files by RPM (and thus subject to being
112: placed in the /usr/doc/RPM-NAME directory during RPM installation).
113: PATHPREFIX, optional path to be removed from file listing. This
114: is in case you are building an RPM from files elsewhere than
115: root-level. Note, this still depends on a root directory hierarchy
116: after PATHPREFIX.
117: CUSTOMIZATION_XML, allows for customizing various pieces of information such
118: as vendor, summary, name, copyright, group, autoreqprov, requires, prereq,
1.16 ! harris41 119: description, and pre-installation scripts (see more in the POD,
! 120: "perldoc make_rpm.pl").
1.13 harris41 121: END
1.16 ! harris41 122: exit(1);
1.1 harris41 123: }
124:
1.16 ! harris41 125: # ----- Generate temporary directories (subdirs of first command-line argument)
! 126:
! 127: # Do some error-checking related to important first command-line argument.
! 128: if ($tag=~/\W/) { # non-alphanumeric characters cause problems
! 129: print(<<END);
! 130: **** ERROR **** Invalid tag name "$tag"
! 131: (The first command-line argument must be alphanumeric characters without
! 132: spaces.)
! 133: END
! 134: exit(1);
! 135: }
! 136: if (-e $tag) { # do not overwrite or conflict with existing data
! 137: print(<<END);
! 138: **** ERROR **** a file or directory "./$tag" already exists
! 139: (This program needs to generate a temporary directory named "$tag".)
! 140: END
! 141: exit(1);
! 142: }
! 143:
! 144: print('Generating temporary directory ./'.$tag."\n");
! 145: mkdir($tag,0755) or die("**** ERROR **** cannot generate $tag directory\n");
! 146: mkdir("$tag/BuildRoot",0755);
! 147: mkdir("$tag/SOURCES",0755);
! 148: mkdir("$tag/SPECS",0755);
! 149: mkdir("$tag/BUILD",0755);
! 150: mkdir("$tag/SRPMS",0755);
! 151: mkdir("$tag/RPMS",0755);
! 152: mkdir("$tag/RPMS/i386",0755);
1.1 harris41 153:
1.13 harris41 154: # -------------------------------------------------------- Initialize variables
155:
1.1 harris41 156: my $file;
1.16 ! harris41 157: my $binaryroot=$tag.'/BinaryRoot';
1.1 harris41 158: my ($type,$size,$octalmode,$user,$group);
159:
1.16 ! harris41 160: my $currentdir=`pwd`; chomp($currentdir); my $invokingdir=$currentdir;
! 161: $currentdir.='/'.$tag;
1.1 harris41 162:
1.16 ! harris41 163: # ------------------------------- Create a stand-alone rpm building environment
1.13 harris41 164:
1.16 ! harris41 165: print('Creating stand-alone rpm build environment.'."\n");
! 166: open(IN,'</usr/lib/rpm/rpmrc') or die('Cannot open /usr/lib/rpm/rpmrc'."\n");
1.13 harris41 167: my @lines=<IN>;
1.16 ! harris41 168: close(IN);
1.1 harris41 169:
1.16 ! harris41 170: open(RPMRC,">$tag/SPECS/rpmrc");
1.13 harris41 171: foreach my $line (@lines) {
1.1 harris41 172: if ($line=~/^macrofiles/) {
1.16 ! harris41 173: chomp($line);
1.11 harris41 174: $line.=":$currentdir/SPECS/rpmmacros\n";
1.1 harris41 175: }
1.16 ! harris41 176: print(RPMRC $line);
1.1 harris41 177: }
1.16 ! harris41 178: close(RPMRC);
1.1 harris41 179:
1.16 ! harris41 180: open(RPMMACROS,">$tag/SPECS/rpmmacros");
! 181: print(RPMMACROS <<END);
1.1 harris41 182: \%_topdir $currentdir
183: \%__spec_install_post \\
184: /usr/lib/rpm/brp-strip \\
185: /usr/lib/rpm/brp-strip-comment-note \\
186: \%{nil}
187: END
1.16 ! harris41 188: close(RPMMACROS);
1.1 harris41 189:
1.13 harris41 190: # ------------------------- Perform variable initializations and customizations
191:
1.16 ! harris41 192: my $cu=''; # string that holds customization XML file contents
! 193: if (length($customize)>0) {
! 194: print('Reading in XML-formatted customizations from '.$customize."\n");
! 195: open(IN,"<$customize") or
! 196: (
! 197: print(`cd $invokingdir; rm -Rf $tag`) and
! 198: die('Cannot open customization file "'.$customize.'"'."\n")
! 199: );
1.13 harris41 200: my @clines=(<IN>);
201: $cu=join('',@clines);
1.16 ! harris41 202: close(IN);
1.13 harris41 203: }
204:
1.16 ! harris41 205: # tv - temporary variable (if it exists inside the XML document) then use it,
! 206: # otherwise don't overwrite existing values of variables
! 207: my $tv='';
! 208:
! 209: # (Sure. We could use HTML::TokeParser here... but that wouldn't be fun now,
1.13 harris41 210: # would it?)
211: my $name=$tag;
212: # read in name from customization if available
213: $tv=grabtag('name',$cu,1); $name=$tv if $tv;
214: $name=~s/\<tag \/\>/$tag/g;
215:
1.16 ! harris41 216: # (When in doubt, be paranoid about overwriting things.)
! 217: if (-e "$name-$version-1.i386.rpm") {
! 218: print(`cd $invokingdir; rm -Rf $tag`); # clean temporary filespace in use
! 219: die("**** ERROR **** $name-$version-1.i386.rpm already exists.\n");
! 220: }
1.13 harris41 221:
1.16 ! harris41 222: my $requires='';
1.13 harris41 223: # read in relevant requires info from customization file (if applicable)
224: # note that "PreReq: item" controls order of CD-ROM installation (if you
225: # are making a customized CD-ROM)
226: # "Requires: item" just enforces dependencies from the command-line invocation
227: $tv=grabtag('requires',$cu,1); $requires=$tv if $tv;
228: # do more require processing here
229: $requires=~s/\s*\<\/item\>\s*//g;
230: $requires=~s/\s*\<item\>\s*/\n/g;
231: $requires=~s/^\s+//s;
232:
1.16 ! harris41 233: my $summary='Files for the '.$name.' software package.';
1.13 harris41 234: # read in summary from customization if available
235: $tv=grabtag('summary',$cu,1); $summary=$tv if $tv;
236: $summary=~s/\<tag \/\>/$tag/g;
237:
1.14 harris41 238: my $autoreqprov='no';
239: # read in autoreqprov from customization if available
240: $tv=grabtag('autoreqprov',$cu,1); $autoreqprov=$tv if $tv;
241:
1.13 harris41 242: my $copyright="not specified here";
243: # read in copyright from customization if available
244: $tv=grabtag('copyright',$cu,1); $copyright=$tv if $tv;
245: $copyright=~s/\<tag \/\>/$tag/g;
246:
1.16 ! harris41 247: open(SPEC,">$tag/SPECS/$name-$version.spec");
1.13 harris41 248:
249: my $vendor='Me';
250: # read in vendor from customization if available
251: $tv=grabtag('vendor',$cu,1); $vendor=$tv if $tv;
252: $vendor=~s/\<tag \/\>/$tag/g;
253:
254: my $description="$name software package";
255: # read in description from customization if available
256: $tv=grabtag('description',$cu,0); $description=$tv if $tv;
257: $description=~s/\<tag \/\>/$tag/g;
258:
1.16 ! harris41 259: my $pre='';
1.13 harris41 260: # read in pre-installation script if available
261: $tv=grabtag('pre',$cu,0); $pre=$tv if $tv;
262: $pre=~s/\<tag \/\>/$tag/g;
1.1 harris41 263:
1.13 harris41 264: # ------------------------------------- Print header information for .spec file
1.12 harris41 265:
1.16 ! harris41 266: print(SPEC <<END);
1.13 harris41 267: Summary: $summary
268: Name: $name
1.1 harris41 269: Version: $version
270: Release: 1
1.12 harris41 271: Vendor: $vendor
1.1 harris41 272: BuildRoot: $currentdir/BuildRoot
1.13 harris41 273: Copyright: $copyright
1.1 harris41 274: Group: Utilities/System
1.13 harris41 275: Source: $name-$version.tar.gz
1.14 harris41 276: AutoReqProv: $autoreqprov
1.7 harris41 277: $requires
1.1 harris41 278: # requires: filesystem
279: \%description
1.13 harris41 280: $description
1.1 harris41 281:
282: \%prep
283: \%setup
284:
285: \%build
286: rm -Rf "$currentdir/BuildRoot"
287:
288: \%install
289: make ROOT="\$RPM_BUILD_ROOT" SOURCE="$currentdir/BinaryRoot" directories
290: make ROOT="\$RPM_BUILD_ROOT" SOURCE="$currentdir/BinaryRoot" files
291: make ROOT="\$RPM_BUILD_ROOT" SOURCE="$currentdir/BinaryRoot" links
292:
293: \%pre
1.13 harris41 294: $pre
1.1 harris41 295:
296: \%post
297: \%postun
298:
299: \%files
300: END
301:
1.13 harris41 302: # ------------------------------------ Process file list and gather information
303:
304: my %BinaryRootMakefile;
305: my %Makefile;
306: my %dotspecfile;
307:
1.16 ! harris41 308: foreach my $file (<>) {
! 309: chomp($file);
1.4 harris41 310: my $comment="";
311: if ($file=~/\s+\#(.*)$/) {
312: $file=~s/\s+\#(.*)$//;
313: $comment=$1;
314: }
1.13 harris41 315: my $directive="";
316: if ($comment=~/config\(noreplace\)/) {
317: $directive="\%config(noreplace) ";
318: }
319: elsif ($comment=~/config/) {
320: $directive="\%config ";
321: }
322: elsif ($comment=~/doc/) {
323: $directive="\%doc";
1.4 harris41 324: }
1.1 harris41 325: if (($type,$size,$octalmode,$user,$group)=find_info($file)) {
326: $octalmode="0" . $octalmode if length($octalmode)<4;
327: if ($pathprefix) {
328: $file=~s/^$pathprefix//;
329: }
330: if ($type eq "files") {
1.16 ! harris41 331: push(@{$BinaryRootMakefile{$type}},"\tinstall -D -m $octalmode ".
! 332: "$pathprefix$file $binaryroot$file\n");
! 333: push(@{$Makefile{$type}},"\tinstall -D -m $octalmode ".
! 334: "\$(SOURCE)$file \$(ROOT)$file\n");
! 335: push(@{$dotspecfile{$type}},"$directive\%attr($octalmode,$user,".
! 336: "$group) $file\n");
1.1 harris41 337: }
338: elsif ($type eq "directories") {
1.16 ! harris41 339: push(@{$BinaryRootMakefile{$type}},"\tinstall -m $octalmode -d ".
! 340: "$binaryroot$file\n");
! 341: push(@{$Makefile{$type}},"\tinstall -m $octalmode -d ".
! 342: "\$(SOURCE)$file \$(ROOT)$file\n");
! 343: push(@{$dotspecfile{$type}},"\%dir \%attr($octalmode,$user,".
! 344: "$group) $file\n");
1.1 harris41 345: }
346: elsif ($type eq "links") {
1.12 harris41 347: my $link=$size; # I use the size variable to pass the link value
348: # from the subroutine find_info
1.1 harris41 349: $link=~s/^$pathprefix//;
1.16 ! harris41 350: push(@{$BinaryRootMakefile{$type}},
! 351: "\tln -s $link $binaryroot$file\n");
! 352: push(@{$Makefile{$type}},"\tln -s $link \$(ROOT)$file\n");
! 353: push(@{$dotspecfile{$type}},"\%attr(-,$user,$group) $file\n");
1.1 harris41 354: }
355: }
356: }
357:
1.13 harris41 358: # -------------------------------------- Generate SRPM and BinaryRoot Makefiles
359:
1.16 ! harris41 360: # Generate a much needed directory.
! 361: # This directory is meant to hold all source code information
! 362: # necessary for converting .src.rpm files into .i386.rpm files.
! 363: mkdir("$tag/SOURCES/$name-$version",0755);
! 364:
! 365: open(OUTS,">$tag/SOURCES/$name-$version/Makefile");
! 366: open(OUTB, ">$tag/BinaryRootMakefile");
1.1 harris41 367: foreach $type ("directories","files","links") {
1.16 ! harris41 368: print(OUTS "$type\:\n");
! 369: print(OUTS join("",@{$Makefile{$type}})) if $Makefile{$type};
! 370: print(OUTS "\n");
! 371: print(OUTB "$type\:\n");
! 372: print(OUTB join("",@{$BinaryRootMakefile{$type}}))
1.13 harris41 373: if $BinaryRootMakefile{$type};
1.16 ! harris41 374: print(OUTB "\n");
! 375: print(SPEC join("",@{$dotspecfile{$type}})) if $dotspecfile{$type};
1.1 harris41 376: }
1.16 ! harris41 377: close(OUTB);
! 378: close(OUTS);
1.1 harris41 379:
1.16 ! harris41 380: close(SPEC);
1.1 harris41 381:
1.13 harris41 382: # ------------------ mirror copy (BinaryRoot) files under a temporary directory
1.1 harris41 383:
384: `make -f $tag/BinaryRootMakefile directories`;
385: `make -f $tag/BinaryRootMakefile files`;
386: `make -f $tag/BinaryRootMakefile links`;
387:
1.13 harris41 388: # ------------------------------------------------- roll everything into an RPM
1.16 ! harris41 389: print('Build a tarball and then run the rpm -ba command.'."\n");
1.13 harris41 390: my $command="cd $currentdir/SOURCES; tar czvf $name-$version.tar.gz ".
391: "$name-$version";
1.16 ! harris41 392: print(`$command`);
1.12 harris41 393: $command="cd $currentdir/SPECS; rpm --rcfile=./rpmrc -ba ".
1.16 ! harris41 394: "$name-$version.spec; cd ../RPMS/i386; cp -v ".
1.13 harris41 395: "$name-$version-1.i386.rpm $invokingdir/.";
1.16 ! harris41 396: print(`$command`);
1.13 harris41 397:
398: # --------------------------------------------------------- clean everything up
1.16 ! harris41 399: print('Removing temporary ./'.$tag.' directory'."\n");
! 400: print(`cd $invokingdir; rm -Rf $tag`);
1.13 harris41 401:
1.16 ! harris41 402: # -------------------------------------------------------- Yeah! We're all done
! 403: print('Success. Script complete.'."\n");
1.1 harris41 404:
1.15 harris41 405: # ----------------------------------------------------------------- SUBROUTINES
1.13 harris41 406: # ----- Subroutine: find_info - recursively gather information from a directory
1.1 harris41 407: sub find_info {
408: my ($file)=@_;
1.16 ! harris41 409: my $line='';
1.1 harris41 410: if (($line=`find $file -type f -prune`)=~/^$file\n/) {
411: $line=`find $file -type f -prune -printf "\%s\t\%m\t\%u\t\%g"`;
1.16 ! harris41 412: return("files",split(/\t/,$line));
1.1 harris41 413: }
414: elsif (($line=`find $file -type d -prune`)=~/^$file\n/) {
415: $line=`find $file -type d -prune -printf "\%s\t\%m\t\%u\t\%g"`;
1.16 ! harris41 416: return("directories",split(/\t/,$line));
1.1 harris41 417: }
418: elsif (($line=`find $file -type l -prune`)=~/^$file\n/) {
1.6 harris41 419: $line=`find $file -type l -prune -printf "\%l\t\%m\t\%u\t\%g"`;
1.16 ! harris41 420: return("links",split(/\t/,$line));
1.1 harris41 421: }
1.16 ! harris41 422: die("**** ERROR **** $file is neither a directory, soft link, or file.\n");
1.1 harris41 423: }
1.13 harris41 424:
425: # ------------------------- Subroutine: grabtag - grab a tag from an xml string
426: sub grabtag {
427: my ($tag,$text,$clean)=@_;
428: # meant to be quick and dirty as opposed to a formal state machine parser
1.16 ! harris41 429: my $value='';
1.13 harris41 430: $cu=~/\<$tag\>(.*?)\<\/$tag\>/s;
431: $value=$1; $value=~s/^\s+//;
1.16 ! harris41 432: if ($clean==1) {
1.13 harris41 433: $value=~s/\n\s/ /g;
434: $value=~s/\s\n/ /g;
435: $value=~s/\n/ /g;
436: $value=~s/\s+$//;
437: }
1.16 ! harris41 438: return($value);
1.13 harris41 439: }
440:
441: # ----------------------------------------------------- Plain Old Documentation
442:
443: =head1 NAME
444:
1.16 ! harris41 445: make_rpm.pl - cleanly generate an rpm in a simple one-line command
1.13 harris41 446:
447: =head1 SYNOPSIS
448:
1.16 ! harris41 449: Usage: <STDIN> | make_rpm.pl <TAG> <VERSION>
! 450: [CONFIGURATION_FILES] [DOCUMENTATION_FILES]
! 451: [PATHPREFIX] [CUSTOMIZATION_XML]
! 452:
! 453: =head2 The standard input stream
! 454:
! 455: I<STDIN>, the standard input stream, provides the list of files to work
! 456: with. This list of file names must give the complete filesystem
! 457: path starting from '/'.
! 458:
! 459: =over 4
! 460:
! 461: =item * For instance, the following is invalid:
! 462:
! 463: romeodir/file1.txt # ** INVALID! ** missing leading filesystem path
! 464: romeodir/file2.txt
! 465: romeodir/file3.txt
! 466:
! 467: =item * Whereas, the following is valid:
! 468:
! 469: /home/joe/romeodir/file1.txt
! 470: /home/joe/romeodir/file2.txt
! 471: /home/joe/romeodir/file3.txt
! 472:
! 473: =item * In terms of the B<find> command,
! 474:
! 475: "find romeodir | perl make_rpm.pl [COMMAND-LINE ARGUMENTS]"
! 476:
! 477: is incorrect, whereas
! 478:
! 479: "find /home/joe/romeodir |perl make_rpm.pl [COMMAND-LINE ARGUMENTS]"
! 480:
! 481: or
! 482:
! 483: "find `pwd`/romeodir |perl make_rpm.pl [COMMAND-LINE ARGUMENTS]"
! 484:
! 485: is correct.
! 486:
! 487: =back
! 488:
! 489: The standard input stream can also
! 490: specify configuration files and documentation files through
! 491: '#'-style commenting.
! 492:
! 493: For example, the following file listing encodes some of these directives:
! 494:
! 495: /home/joe/romeodir/buildloc/etc/romeo/user.conf # config(noreplace)
! 496: /home/joe/romeodir/buildloc/etc/romeo/juliet.conf # config
! 497: /home/joe/romeodir/buildloc/doc/man/man.1/romeo.1 # doc
! 498: /home/joe/romeodir/buildloc/doc/man/man.1/romeo_talks.1 # doc
! 499: /home/joe/romeodir/buildloc/usr/local/bin/where_art_thou
! 500: /home/joe/romeodir/buildloc/usr/local/bin/romeo_talks
! 501:
! 502: The I<config> directive controls how files are replaced
! 503: and/or backed up when a user attempts to install (B<rpm -i>) the F<.rpm>
! 504: file generated by B<make_rpm.pl>. The I<doc> directive controls how a
! 505: given file is placed inside special documentation directories
! 506: on the filesystem during rpm installation (B<rpm -i>).
! 507: (If you want to learn more on how the B<rpm> tool gives configuration and
! 508: documentation files special treatment, you should read about "Directives"
! 509: in Edward Bailey's well-known "Maximum RPM" book available online
! 510: at http://www.rpm.org/max-rpm/s1-rpm-inside-files-list-directives.html.)
1.13 harris41 511:
1.16 ! harris41 512: =head2 Description of command-line arguments
1.13 harris41 513:
1.16 ! harris41 514: I<TAG> ($tag), B<required> descriptive tag. For example, a kerberos software
1.13 harris41 515: package might be tagged as "krb4".
516:
1.16 ! harris41 517: I<VERSION> ($version), B<required> version. Needed to generate version
! 518: information for the RPM. This should be in the format N.M where N and M are
1.13 harris41 519: integers.
520:
1.16 ! harris41 521: I<CONFIGURATION_FILES>, B<optional> comma-separated listing of files to
1.13 harris41 522: be treated as configuration files by RPM (and thus subject to saving
1.16 ! harris41 523: during RPM upgrades). Configuration files can also be specified in
! 524: the standard input stream (as described in L<"The standard input stream">).
1.13 harris41 525:
1.16 ! harris41 526: I<DOCUMENTATION_FILES>, B<optional> comma-separated listing of files to be
1.13 harris41 527: treated as documentation files by RPM (and thus subject to being
1.16 ! harris41 528: placed in the F</usr/doc/RPM-NAME> directory during RPM installation).
! 529: Documentation files can also be specified in
! 530: the standard input stream (as described in L<"The standard input stream">).
1.13 harris41 531:
1.16 ! harris41 532: I<PATHPREFIX>, B<optional> path to be removed from file listing. This
1.13 harris41 533: is in case you are building an RPM from files elsewhere than
534: root-level. Note, this still depends on a root directory hierarchy
535: after PATHPREFIX.
536:
1.16 ! harris41 537: I<CUSTOMIZATION_XML>, B<optional> filename where XML-ish information exists.
! 538: Allows for customizing various pieces of information such
1.13 harris41 539: as vendor, summary, name, copyright, group, autoreqprov, requires, prereq,
1.16 ! harris41 540: description, and pre-installation scripts
! 541: (see L<"Customizing descriptive data of your RPM software package">).
1.13 harris41 542:
1.16 ! harris41 543: =head2 Examples
1.13 harris41 544:
1.16 ! harris41 545: bash$ find /notreallyrootdir | perl make_rpm.pl \
! 546: makemoney 3.1 '' \
! 547: '/usr/doc/man/man3/makemoney.3' \
! 548: /notreallyrootdir
1.13 harris41 549: would generate makemoney-3.1-1.i386.rpm
550:
1.16 ! harris41 551: bash$ find /usr/local/bin | \
! 552: perl make_rpm.pl mybinfiles 1.0
1.13 harris41 553: would generate mybinfiles-1.0-1.i386.rpm
554:
1.16 ! harris41 555: bash$ find /home/joe/romeodir/buildloc | \
! 556: perl make_rpm.pl romeo \
! 557: 1.0 '' '' '/home/joe/romeodir/buildloc' customize.xml
1.13 harris41 558: would generate romeo with customizations from customize.xml.
559:
1.16 ! harris41 560: The I<CUSTOMIZATION_XML> argument represents a way to customize the
1.13 harris41 561: numerous variables associated with RPMs. This argument represents
562: a file name. (Parsing is done in an unsophisticated fashion using
1.16 ! harris41 563: regular expressions.) See
! 564: L<"Customizing descriptive data of your RPM software package">.
! 565:
! 566: =head1 Customizing descriptive data of your RPM software package
! 567:
! 568: RPMS can be (and often are) packaged with descriptive data
! 569: describing authorship, dependencies, descriptions, etc.
! 570:
! 571: The following values can be tagged inside an XML file
! 572: (specified by the 6th command-line argument)
! 573: and made part of the RPM package information
! 574: (B<rpm -qi E<lt>package-nameE<gt>>).
! 575:
! 576: =over 4
! 577:
! 578: =item * vendor
! 579:
! 580: =item * summary
! 581:
! 582: =item * name
! 583:
! 584: (overrides the <TAG> argument value; see
! 585: L<"Description of command-line arguments>)
! 586:
! 587: =item * copyright
! 588:
! 589: =item * group
! 590:
! 591: (the software package group;
! 592: e.g. Applications/System, User Interface/X, Development/Libraries,
! 593: etc.)
! 594:
! 595: =item * requires
! 596:
! 597: Contains all the dependency information (see the example below).
! 598:
! 599: =item * description
! 600:
! 601: =item * pre
! 602:
! 603: Commands to be executed prior to software package installation.
! 604:
! 605: =back
! 606:
! 607: Here is an example (note that B<make_rpm.pl> automatically substitutes
! 608: any "<tag />" string with the first command-line argument described
! 609: in L<"Description of command-line arguments">):
1.13 harris41 610:
611: <vendor>
612: Laboratory for Instructional Technology Education, Division of
613: Science and Mathematics Education, Michigan State University.
614: </vendor>
615: <summary>Files for the <tag /> component of LON-CAPA</summary>
616: <name>LON-CAPA-<tag /></name>
617: <copyright>Michigan State University patents may apply.</copyright>
618: <group>Utilities/System</group>
619: <AutoReqProv>no</AutoReqProv>
620: <requires tag='setup'>
621: <item>PreReq: setup</item>
622: <item>PreReq: passwd</item>
623: <item>PreReq: util-linux</item>
624: </requires>
625: <requires tag='base'>
626: <item>PreReq: LON-CAPA-setup</item>
627: <item>PreReq: apache</item>
628: <item>PreReq: /etc/httpd/conf/access.conf</item>
629: </requires>
630: <requires>
631: <item>Requires: LON-CAPA-base</item>
632: </requires>
633: <description>
634: This package is automatically generated by the make_rpm.pl perl
635: script (written by the LON-CAPA development team, www.lon-capa.org,
636: Scott Harrison). This implements the <tag /> component for LON-CAPA.
637: For more on the LON-CAPA project, visit http://www.lon-capa.org/.
638: </description>
639: <pre>
1.16 ! harris41 640: echo "************************************************************"
1.13 harris41 641: echo "LON-CAPA LearningOnline with CAPA"
642: echo "http://www.lon-capa.org/"
643: echo " "
644: echo "Laboratory for Instructional Technology Education"
645: echo "Michigan State University"
646: echo " "
647: echo "** Michigan State University patents may apply **"
648: echo " "
649: echo "This installation assumes an installation of Redhat 6.2"
650: echo " "
1.16 ! harris41 651: echo "The files in this package are for the <tag /> component."
! 652: echo "***********************************************************"
1.13 harris41 653: </pre>
654:
655: =head1 DESCRIPTION
656:
657: Automatically generate an RPM software package from a list of files.
658:
1.16 ! harris41 659: B<make_rpm.pl> builds the RPM in a very clean and configurable fashion.
! 660: (Finally! Making RPMs outside of F</usr/src/redhat> without a zillion
1.15 harris41 661: file intermediates left over!)
1.13 harris41 662:
1.16 ! harris41 663: B<make_rpm.pl> generates and then deletes temporary
1.15 harris41 664: files needed to build an RPM with.
665: It works cleanly and independently from pre-existing
1.16 ! harris41 666: directory trees such as F</usr/src/redhat/*>.
1.13 harris41 667:
1.16 ! harris41 668: Input to the script is simple. B<make_rpm.pl> accepts five kinds of
! 669: information, three of which are mandatory:
1.15 harris41 670:
671: =over 4
672:
673: =item *
674:
1.16 ! harris41 675: (required) a list of files that are to be part of the software package;
1.15 harris41 676:
1.16 ! harris41 677: =item *
! 678:
! 679: (required) the absolute filesystem location of these files
! 680: (see L<"The standard input stream">);
! 681:
! 682: =item *
1.15 harris41 683:
1.16 ! harris41 684: (required) a descriptive tag and a version tag for the naming of the
! 685: RPM software package;
1.15 harris41 686:
687: =item *
688:
1.16 ! harris41 689: (optional) documentation and configuration files;
1.15 harris41 690:
691: =item *
692:
693: and (optional) an XML file that defines the additional metadata
694: associated with the RPM software package.
695:
696: =back
697:
1.16 ! harris41 698: A temporary directory named $tag (first argument described in
! 699: L<"Description of command-line arguments">) is
! 700:
! 701: =over 4
! 702:
! 703: =item *
! 704:
! 705: generated under the directory from which you run B<make_rpm.pl>.
! 706:
! 707: For example, user "joe" running
! 708:
! 709: cat file_list.txt | make_rpm.pl krb4 1.0
! 710:
! 711: would temporarily generate F</home/joe/krb4/>.
! 712:
! 713: =item *
! 714:
! 715: F</home/joe/krb4/> is deleted after the *.rpm
! 716: file is generated.
! 717:
! 718: =back
! 719:
! 720: The RPM will typically be named $name-$version.i386.rpm
! 721: where $name=$tag. (The $name can be overridden in the customization
! 722: XML file; see
! 723: L<"Customizing descriptive data of your RPM software package">.)
! 724:
! 725: Here are some of the items are generated inside
! 726: the $tag directory during the construction of an RPM:
! 727:
! 728: =over 4
! 729:
! 730: =item *
! 731:
! 732: RPM .spec file (F<./$tag/SPECS/$name-$version.spec>)
! 733:
! 734: =item *
! 735:
! 736: RPM Makefile (F<./$tag/SOURCES/$name-$version/Makefile>)
! 737:
! 738: This is the Makefile that is called by the rpm
! 739: command in building the .i386.rpm from the .src.rpm.
! 740: The following directories are generated and/or used:
1.15 harris41 741:
742: =over 4
743:
744: =item *
745:
1.16 ! harris41 746: SOURCE directory: F<./$tag/BinaryRoot/>
! 747:
! 748: =item *
! 749:
! 750: TARGET directory: F<./$tag/BuildRoot/>
! 751:
! 752: =back
! 753:
! 754: =item *
! 755:
! 756: BinaryRootMakefile (F<./$tag/BinaryRootMakefile>)
! 757:
! 758: This is the Makefile that this script creates and calls
! 759: to build the F<$tag/BinaryRoot/> directory from the existing
! 760: filesystem.
! 761: The following directories are generated and/or used:
! 762:
! 763: =over 4
1.15 harris41 764:
765: =item *
766:
1.16 ! harris41 767: SOURCE directory: / (your entire filesystem)
1.15 harris41 768:
769: =item *
770:
1.16 ! harris41 771: TARGET directory: F<./$tag/BinaryRoot/>
1.15 harris41 772:
773: =back
1.13 harris41 774:
1.16 ! harris41 775: =back
! 776:
! 777: The final output of B<make_rpm.pl> is a binary F<.rpm> file.
! 778: The F<./tag> directory is deleted (along with the F<.src.rpm>
! 779: file). The typical file name generated by B<make_rpm.pl> is
! 780: F<$tag-$version.i386.rpm>.
1.13 harris41 781:
1.16 ! harris41 782: B<make_rpm.pl> is compatible with either rpm version 3.* or rpm version 4.*.
1.15 harris41 783:
1.13 harris41 784: =head1 README
785:
786: Automatically generate an RPM software package from a list of files.
787:
1.16 ! harris41 788: B<make_rpm.pl> builds the RPM in a very clean and configurable fashion.
! 789: (Making RPMs "the simple way" in a one-line command.)
1.13 harris41 790:
1.16 ! harris41 791: B<make_rpm.pl> generates and then deletes temporary
1.13 harris41 792: files (and binary root directory tree) to build an RPM with.
793: It is designed to work cleanly and independently from pre-existing
794: directory trees such as /usr/src/redhat/*.
795:
796: =head1 PREREQUISITES
797:
798: This script requires the C<strict> module.
799:
1.16 ! harris41 800: =head1 AUTHOR
! 801:
! 802: Scott Harrison
! 803: harris41@msu.edu
! 804:
! 805: Please let me know how/if you are finding this script useful and
! 806: any/all suggestions. -Scott
! 807:
! 808: =head1 LICENSE
! 809:
! 810: Written by Scott Harrison, harris41@msu.edu
! 811:
! 812: Copyright Michigan State University Board of Trustees
! 813:
! 814: This file is part of the LearningOnline Network with CAPA (LON-CAPA).
! 815:
! 816: This is free software; you can redistribute it and/or modify
! 817: it under the terms of the GNU General Public License as published by
! 818: the Free Software Foundation; either version 2 of the License, or
! 819: (at your option) any later version.
! 820:
! 821: This file is distributed in the hope that it will be useful,
! 822: but WITHOUT ANY WARRANTY; without even the implied warranty of
! 823: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! 824: GNU General Public License for more details.
! 825:
! 826: The GNU Public License is available for review at
! 827: http://www.gnu.org/copyleft/gpl.html.
! 828:
! 829: For information on the LON-CAPA project, please visit
! 830: http://www.lon-capa.org/.
! 831:
! 832: =head1 OSNAMES
1.13 harris41 833:
1.15 harris41 834: Linux
1.13 harris41 835:
1.16 ! harris41 836: =head1 SCRIPT CATEGORIES
1.13 harris41 837:
838: UNIX/System Administration
839:
840: =cut
1.16 ! harris41 841:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>