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