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>