1: #!/usr/bin/perl -w
2: # Make an RPM from a perl module, straight from CPAN.
3:
4: use strict;
5:
6: use CPAN 1.54;
7: use Data::Dumper qw(Dumper); $Data::Dumper::Indent=1;
8: use Fatal qw(open close chdir opendir closedir);
9: use File::Copy qw(copy);
10: use Cwd qw(cwd);
11: use Getopt::Std;
12: use vars qw(*SPEC $opt_h $opt_n $opt_r $opt_i $opt_g $opt_c $VERSION);
13: require blib;
14:
15: $VERSION = '1.00';
16:
17: BEGIN {
18: unless ($< == $( && $< == 0) {
19: die "Must be running as root!";
20: }
21: }
22:
23: unless (caller) {
24: getopts(join('',
25: 'n:', # Name of rpm
26: 'r:', # Revision
27: 'i:', # Ignore list
28: 'g:', # Group
29: 'c:', # Copyright
30: 'h', # Help
31: )
32: );
33:
34: exit(main(@ARGV));
35: }
36:
37: sub main {
38: my @ARGS = @_;
39:
40: return usage() if $opt_h;
41: return usage() unless (@ARGS || -e 'Makefile.PL');
42:
43: if (!@ARGS) {
44: print "About to build local module, not a CPAN module. OK? [Y/n] ";
45: my $ret = <STDIN>;
46: if ($ret !~ /^y/i) {
47: print "OK, exiting\n";
48: return 1;
49: }
50: }
51:
52: my $perl_version = `rpm -q perl`;
53: $perl_version =~ s/^\D*([\d\.]+).*$/$1/s;
54: warn("got perl version: $perl_version\n");
55:
56: my $cpan_file = @ARGS ? get_cpan_file(shift(@ARGS)) : 'STAR/Module';
57:
58: # Get and set build dir
59: my $distro = $CPAN::META->instance('CPAN::Distribution', $cpan_file);
60: $distro->{writemakefile} = 1;
61: # warn("got distro:", Dumper($distro));
62: if (my $dir = $distro->dir) {
63: warn("Changing dir from ", cwd, " to $dir\n");
64: chdir($dir);
65: }
66: else {
67: $distro->{build_dir} = '.';
68: }
69:
70: xsystem("$^X Makefile.PL");
71:
72: # Build pre-requisites list
73: my $prereq = $distro->prereq_pm;
74: my $prereq_str = "perl = $perl_version";
75: foreach my $mod (keys %$prereq) {
76: next if $opt_i =~ /\Q$mod\E/;
77: $mod =~ s/::/-/g;
78: next if $opt_i =~ /\Q$mod\E/;
79: $prereq_str .= ", perl-$mod";
80: if ($prereq->{$mod}) {
81: $prereq_str .= " >= $prereq->{$mod}";
82: }
83: }
84: warn("Generated prereq string: $prereq_str\n");
85:
86: # Find distname and version from the Makefile
87: my $distname = `grep 'DISTNAME =' Makefile | cut -f3 -d' ' | head -1`;
88: chomp($distname);
89: my $version = `grep 'VERSION =' Makefile | cut -f3 -d' ' | head -1`;
90: chomp($version);
91: die "No version number!" unless $version;
92:
93: (my $modname = $distname) =~ s/-/::/g;
94:
95: warn("Building spec file for $modname $version\n");
96:
97: $opt_n ||= "perl-$distname";
98: my $copyright = '';
99: if ($opt_c) {
100: $copyright = "Copyright: $opt_c\n";
101: }
102: $opt_r ||= '1';
103: $opt_g ||= 'Perl';
104:
105: open(SPEC, ">${distname}.spec");
106: print SPEC <<"EOT";
107: Name: $opt_n
108: Version: $version
109: Release: $opt_r
110: $copyright
111: License: Artistic (probably)
112: Group: $opt_g
113: Source: $distname-\%{version}.tar.gz
114: BuildRoot: /tmp/\%{name}-buildroot
115: Summary: perl module $modname
116: Requires: $prereq_str
117:
118: %description
119: perl module $modname
120:
121: %prep
122: %setup -n ${distname}-${version}
123:
124: %build
125: $^X Makefile.PL
126: make
127: make test
128:
129: %install
130: rm -rf \$RPM_BUILD_ROOT
131: make PREFIX=\$RPM_BUILD_ROOT/usr INSTALLMAN3DIR=\$RPM_BUILD_ROOT/usr/man/man3 install
132: find \$RPM_BUILD_ROOT -name perllocal.pod | xargs rm -f
133:
134: %clean
135: rm -rf \$RPM_BUILD_ROOT
136:
137: %files
138: /usr/
139:
140: %changelog
141:
142: EOT
143:
144: close SPEC;
145:
146: xsystem("rm -f *.tar.gz");
147: xsystem("make dist");
148: copy("${distname}-${version}.tar.gz", "/usr/src/redhat/SOURCES/");
149: xsystem("rpm -bb ${distname}.spec");
150: return 0;
151: }
152:
153: sub usage {
154: print <<EOT;
155: This is mkperlrpm version $VERSION. This is free software.
156:
157: Usage: mkperlrpm [options] [Module-Name]
158: Options:
159:
160: -n name Name of rpm. Default: perl-[Module-Name]
161: -r revision Revision of the module (not version). Default: 1.
162: -g group Group to put module in. Default: Perl
163: -c copyright Copyright to use. Default: none
164: -i ignore list The ignore list is a list of perl modules to ignore
165: in the dependencies list. See the man page for details.
166:
167: EOT
168: return 1;
169: }
170:
171: sub get_cpan_file {
172: my $modulename = shift;
173: warn("Downloading $modulename from CPAN...\n");
174: my $obj = CPAN::Shell->expandany($modulename);
175: $obj->get();
176: my $cpan_file = $obj->cpan_file;
177: warn("Downloaded\n");
178: return $cpan_file;
179: }
180:
181: ##########################################################################################
182:
183: sub xsystem {
184: my $retval = system(@_);
185: my $exit_val = $? >> 8;
186: my $signal_num = $? & 127;
187: my $dumped_core = $? & 128;
188: if ($dumped_core) {
189: die "$_[0] failed: dumped core\n";
190: }
191: if ($signal_num) {
192: die "$_[0] failed: exited with signal $signal_num\n";
193: }
194: if ($exit_val) {
195: die "$_[0] failed: exited with code: $exit_val\n";
196: }
197: return;
198: }
199:
200: 1;