1: #!/usr/bin/perl
2:
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
8: # The LearningOnline Network with CAPA
9: # make_rpm.pl - make RedHat package manager file (A CLEAN AND CONFIGURABLE WAY)
10: #
11: # $Id: make_rpm.pl,v 1.18 2002/04/10 05:58:17 harris41 Exp $
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
40: # 1/4,1/8,1/9,2/13,4/7 - Scott Harrison
41: #
42: ###
43:
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.
47:
48: ###############################################################################
49: ## ##
50: ## ORGANIZATION OF THIS PERL SCRIPT ##
51: ## ##
52: ## 1. Check to see if RPM builder application is available ##
53: ## 2. Read in command-line arguments ##
54: ## 3. Generate temporary directories (subdirs of first command-line argument)##
55: ## 4. Initialize some variables ##
56: ## 5. Create a stand-alone rpm building environment ##
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 ##
64: ## 13. subroutines ##
65: ## 13a. find_info - recursively gather information from a directory ##
66: ## 13b. grabtag - grab a tag from an XML string ##
67: ## 14. Plain Old Documentation ##
68: ## ##
69: ###############################################################################
70:
71: use strict;
72:
73: # ------------------------ Check to see if RPM builder application is available
74:
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
78: application.
79: Cannot find /usr/lib/rpm/rpmrc, so cannot generate customized rpmrc file.
80: Script aborting.
81: END
82: exit(1);
83: }
84:
85: # ---------------------------------------------- Read in command-line arguments
86:
87: my ($tag,$version,$configuration_files,$documentation_files,
88: $pathprefix,$customize)=@ARGV;
89: @ARGV=(); # read standard input based on a pipe, not a command-line argument
90:
91: # standardize pathprefix argument
92: $pathprefix=~s/\/$//; # OTHERWISE THE BEGINNING SLASH MIGHT BE REMOVED
93:
94: if (!$version) {# version should be defined and string length greater than zero
95: print(<<END);
96: See "perldoc make_rpm.pl" for more information.
97:
98: Usage:
99: <STDIN> | perl make_rpm.pl <TAG> <VERSION> [CONFIGURATION_FILES]
100: [DOCUMENTATION_FILES] [PATHPREFIX] [CUSTOMIZATION_XML]
101:
102: Standard input provides the list of files to work with.
103: TAG, required descriptive tag. For example, a kerberos software
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.)
107: VERSION, required version. Needed to generate version information
108: for the RPM. It is recommended that this be in the format N.M where N and
109: M are integers.
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,
122: description, and pre-installation scripts (see more in the POD,
123: "perldoc make_rpm.pl").
124: END
125: exit(1);
126: }
127:
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);
156:
157: # -------------------------------------------------------- Initialize variables
158:
159: my $file;
160: my $binaryroot=$tag.'/BinaryRoot';
161: my ($type,$size,$octalmode,$user,$group);
162:
163: my $currentdir=`pwd`; chomp($currentdir); my $invokingdir=$currentdir;
164: $currentdir.='/'.$tag;
165:
166: # ------------------------------- Create a stand-alone rpm building environment
167:
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");
170: my @lines=<IN>;
171: close(IN);
172:
173: open(RPMRC,">$tag/SPECS/rpmrc");
174: foreach my $line (@lines) {
175: if ($line=~/^macrofiles/) {
176: chomp($line);
177: $line.=":$currentdir/SPECS/rpmmacros\n";
178: }
179: print(RPMRC $line);
180: }
181: close(RPMRC);
182:
183: open(RPMMACROS,">$tag/SPECS/rpmmacros");
184: print(RPMMACROS <<END);
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
191: close(RPMMACROS);
192:
193: # ------------------------- Perform variable initializations and customizations
194:
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: );
203: my @clines=(<IN>);
204: $cu=join('',@clines);
205: close(IN);
206: }
207:
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,
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:
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: }
224:
225: my $requires='';
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:
236: my $summary='Files for the '.$name.' software package.';
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:
241: my $autoreqprov='no';
242: # read in autoreqprov from customization if available
243: $tv=grabtag('autoreqprov',$cu,1); $autoreqprov=$tv if $tv;
244:
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:
250: open(SPEC,">$tag/SPECS/$name-$version.spec");
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:
262: my $pre='';
263: # read in pre-installation script if available
264: $tv=grabtag('pre',$cu,0); $pre=$tv if $tv;
265: $pre=~s/\<tag \/\>/$tag/g;
266:
267: # ------------------------------------- Print header information for .spec file
268:
269: print(SPEC <<END);
270: Summary: $summary
271: Name: $name
272: Version: $version
273: Release: 1
274: Vendor: $vendor
275: BuildRoot: $currentdir/BuildRoot
276: Copyright: $copyright
277: Group: Utilities/System
278: Source: $name-$version.tar.gz
279: AutoReqProv: $autoreqprov
280: $requires
281: # requires: filesystem
282: \%description
283: $description
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
297: $pre
298:
299: \%post
300: \%postun
301:
302: \%files
303: END
304:
305: # ------------------------------------ Process file list and gather information
306:
307: my %BinaryRootMakefile;
308: my %Makefile;
309: my %dotspecfile;
310:
311: foreach my $file (<>) {
312: chomp($file);
313: my $comment="";
314: if ($file=~/\s+\#(.*)$/) {
315: $file=~s/\s+\#(.*)$//;
316: $comment=$1;
317: }
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";
327: }
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") {
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");
340: }
341: elsif ($type eq "directories") {
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");
348: }
349: elsif ($type eq "links") {
350: my $link=$size; # I use the size variable to pass the link value
351: # from the subroutine find_info
352: $link=~s/^$pathprefix//;
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");
357: }
358: }
359: }
360:
361: # -------------------------------------- Generate SRPM and BinaryRoot Makefiles
362:
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");
370: foreach $type ("directories","files","links") {
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}}))
376: if $BinaryRootMakefile{$type};
377: print(OUTB "\n");
378: print(SPEC join("",@{$dotspecfile{$type}})) if $dotspecfile{$type};
379: }
380: close(OUTB);
381: close(OUTS);
382:
383: close(SPEC);
384:
385: # ------------------ mirror copy (BinaryRoot) files under a temporary directory
386:
387: `make -f $tag/BinaryRootMakefile directories`;
388: `make -f $tag/BinaryRootMakefile files`;
389: `make -f $tag/BinaryRootMakefile links`;
390:
391: # ------------------------------------------------- roll everything into an RPM
392: print('Build a tarball and then run the rpm -ba command.'."\n");
393: my $command="cd $currentdir/SOURCES; tar czvf $name-$version.tar.gz ".
394: "$name-$version";
395: print(`$command`);
396: $command="cd $currentdir/SPECS; rpm --rcfile=./rpmrc -ba ".
397: "$name-$version.spec; cd ../RPMS/i386; cp -v ".
398: "$name-$version-1.i386.rpm $invokingdir/.";
399: print(`$command`);
400:
401: # --------------------------------------------------------- clean everything up
402: print('Removing temporary ./'.$tag.' directory'."\n");
403: print(`cd $invokingdir; rm -Rf $tag`);
404:
405: # -------------------------------------------------------- Yeah! We're all done
406: print('Success. Script complete.'."\n");
407:
408: # ----------------------------------------------------------------- SUBROUTINES
409: # ----- Subroutine: find_info - recursively gather information from a directory
410: sub find_info {
411: my ($file)=@_;
412: my $line='';
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"`;
415: return("files",split(/\t/,$line));
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"`;
419: return("directories",split(/\t/,$line));
420: }
421: elsif (($line=`find $file -type l -prune`)=~/^$file\n/) {
422: $line=`find $file -type l -prune -printf "\%l\t\%m\t\%u\t\%g"`;
423: return("links",split(/\t/,$line));
424: }
425: die("**** ERROR **** $file is neither a directory, soft link, or file.\n");
426: }
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
432: my $value='';
433: $cu=~/\<$tag\>(.*?)\<\/$tag\>/s;
434: $value=$1; $value=~s/^\s+//;
435: if ($clean==1) {
436: $value=~s/\n\s/ /g;
437: $value=~s/\s\n/ /g;
438: $value=~s/\n/ /g;
439: $value=~s/\s+$//;
440: }
441: return($value);
442: }
443:
444: # ----------------------------------------------------- Plain Old Documentation
445:
446: =head1 NAME
447:
448: make_rpm.pl - cleanly generate an rpm in a simple one-line command
449:
450: =head1 SYNOPSIS
451:
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.)
514:
515: =head2 Description of command-line arguments
516:
517: I<TAG> ($tag), B<required> descriptive tag. For example, a kerberos software
518: package might be tagged as "krb4".
519:
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
522: integers.
523:
524: I<CONFIGURATION_FILES>, B<optional> comma-separated listing of files to
525: be treated as configuration files by RPM (and thus subject to saving
526: during RPM upgrades). Configuration files can also be specified in
527: the standard input stream (as described in L<"The standard input stream">).
528:
529: I<DOCUMENTATION_FILES>, B<optional> comma-separated listing of files to be
530: treated as documentation files by RPM (and thus subject to being
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">).
534:
535: I<PATHPREFIX>, B<optional> path to be removed from file listing. This
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:
540: I<CUSTOMIZATION_XML>, B<optional> filename where XML-ish information exists.
541: Allows for customizing various pieces of information such
542: as vendor, summary, name, copyright, group, autoreqprov, requires, prereq,
543: description, and pre-installation scripts
544: (see L<"Customizing descriptive data of your RPM software package">).
545:
546: =head2 Examples
547:
548: bash$ find /notreallyrootdir | perl make_rpm.pl \
549: makemoney 3.1 '' \
550: '/usr/doc/man/man3/makemoney.3' \
551: /notreallyrootdir
552: would generate makemoney-3.1-1.i386.rpm
553:
554: bash$ find /usr/local/bin | \
555: perl make_rpm.pl mybinfiles 1.0
556: would generate mybinfiles-1.0-1.i386.rpm
557:
558: bash$ find /home/joe/romeodir/buildloc | \
559: perl make_rpm.pl romeo \
560: 1.0 '' '' '/home/joe/romeodir/buildloc' customize.xml
561: would generate romeo with customizations from customize.xml.
562:
563: The I<CUSTOMIZATION_XML> argument represents a way to customize the
564: numerous variables associated with RPMs. This argument represents
565: a file name. (Parsing is done in an unsophisticated fashion using
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">):
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>
643: echo "************************************************************"
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 " "
654: echo "The files in this package are for the <tag /> component."
655: echo "***********************************************************"
656: </pre>
657:
658: =head1 DESCRIPTION
659:
660: Automatically generate an RPM software package from a list of files.
661:
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
664: file intermediates left over!)
665:
666: B<make_rpm.pl> generates and then deletes temporary
667: files needed to build an RPM with.
668: It works cleanly and independently from pre-existing
669: directory trees such as F</usr/src/redhat/*>.
670:
671: Input to the script is simple. B<make_rpm.pl> accepts five kinds of
672: information, three of which are mandatory:
673:
674: =over 4
675:
676: =item *
677:
678: (required) a list of files that are to be part of the software package;
679:
680: =item *
681:
682: (required) the absolute filesystem location of these files
683: (see L<"The standard input stream">);
684:
685: =item *
686:
687: (required) a descriptive tag and a version tag for the naming of the
688: RPM software package;
689:
690: =item *
691:
692: (optional) documentation and configuration files;
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:
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:
744:
745: =over 4
746:
747: =item *
748:
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
767:
768: =item *
769:
770: SOURCE directory: / (your entire filesystem)
771:
772: =item *
773:
774: TARGET directory: F<./$tag/BinaryRoot/>
775:
776: =back
777:
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>.
784:
785: B<make_rpm.pl> is compatible with either rpm version 3.* or rpm version 4.*.
786:
787: =head1 README
788:
789: Automatically generate an RPM software package from a list of files.
790:
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.)
793:
794: B<make_rpm.pl> generates and then deletes temporary
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:
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
836:
837: Linux
838:
839: =head1 SCRIPT CATEGORIES
840:
841: UNIX/System_administration
842:
843: =cut
844:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>