source: trunk/debbuild@ 75

Last change on this file since 75 was 75, checked in by kdeugau, 17 years ago

/trunk

Clean up pre/post (un)install scriptlet handling to support subpackage
scriptlets

  • Property svn:executable set to *
  • Property svn:keywords set to Date Rev Author
File size: 43.0 KB
Line 
1#!/usr/bin/perl
2# debbuild script
3# Shamlessly steals intreface from rpm's "rpmbuild" to create
4# Debian packages. Please note that such packages are highly
5# unlikely to conform to "Debian Policy".
6###
7# SVN revision info
8# $Date: 2006-11-15 22:46:44 +0000 (Wed, 15 Nov 2006) $
9# SVN revision $Rev: 75 $
10# Last update by $Author: kdeugau $
11###
12# Copyright 2005,2006 Kris Deugau <kdeugau@deepnet.cx>
13#
14# This program is free software; you can redistribute it and/or modify
15# it under the terms of the GNU General Public License as published by
16# the Free Software Foundation; either version 2 of the License, or
17# (at your option) any later version.
18#
19# This program is distributed in the hope that it will be useful,
20# but WITHOUT ANY WARRANTY; without even the implied warranty of
21# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22# GNU General Public License for more details.
23#
24# You should have received a copy of the GNU General Public License
25# along with this program; if not, write to the Free Software
26# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27
28use strict;
29use warnings;
30use Fcntl; # for sysopen flags
31use Cwd 'abs_path'; # for finding where files really are
32
33# regex debugger
34#use re "debug";
35
36# Program flow:
37# -> Parse/execute "system" config/macros (if any - should be rare)
38# -> Parse/execute "user" config/macros (if any - *my* requirement is %_topdir)
39# -> Parse command line for options, spec file/tarball/.src.deb (NB - also accept .src.rpm)
40
41sub expandmacros;
42
43# User's prefs for dirs, environment, etc,etc,etc.
44# config file ~/.debmacros
45# Default ordered search paths for config/macros:
46# /usr/lib/rpm/rpmrc /usr/lib/rpm/redhat/rpmrc /etc/rpmrc ~/.rpmrc
47# /usr/lib/rpm/macros /usr/lib/rpm/redhat/macros /etc/rpm/macros ~/.rpmmacros
48# **NOTE: May be possible to (ab)use bits of debhelper
49
50# Build tree
51# default is /usr/src/debian/{BUILD,SOURCES,SPECS,DEBS,SDEBS}
52
53# Globals
54my $specfile;
55my $tarball;
56my $srcpkg;
57my $cmdbuildroot;
58my $tarballdir; # This should really be initialized, but the coding makes it, um, ugly.
59my %specglobals; # For %define's in specfile, among other things.
60
61# Initialized globals
62my $verbosity = 0;
63my %cmdopts = (type => '',
64 stage => 'a',
65 short => 'n'
66 );
67my $topdir = "/usr/src/debian";
68my $buildroot = "%{_tmppath}/%{name}-%{version}-%{release}.root".int(rand(99998)+1);
69
70# "Constants"
71my %targets = ('p' => 'Prep',
72 'c' => 'Compile',
73 'i' => 'Install',
74 'l' => 'Verify %files',
75 'a' => 'Build binary and source',
76 'b' => 'Build binary',
77 's' => 'Build source'
78 );
79my $scriptletbase =
80q(#!/bin/sh
81
82 RPM_SOURCE_DIR="%{_topdir}/SOURCES"
83 RPM_BUILD_DIR="%{_topdir}/BUILD"
84 RPM_OPT_FLAGS="-O2 -g -march=i386 -mcpu=i686"
85 RPM_ARCH="i386"
86 RPM_OS="linux"
87 export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_ARCH RPM_OS
88 RPM_DOC_DIR="/usr/share/doc"
89 export RPM_DOC_DIR
90 RPM_PACKAGE_NAME="%{name}"
91 RPM_PACKAGE_VERSION="%{version}"
92 RPM_PACKAGE_RELEASE="%{release}"
93 export RPM_PACKAGE_NAME RPM_PACKAGE_VERSION RPM_PACKAGE_RELEASE
94 RPM_BUILD_ROOT="%{buildroot}"
95 export RPM_BUILD_ROOT
96);
97foreach (`dpkg-architecture`) {
98 s/=(.+)/="$1"/;
99 $scriptletbase .= " $_";
100}
101$scriptletbase .=
102q(
103 set -x
104 umask 022
105 cd %{_topdir}/BUILD
106);
107
108# Package data
109# This is the form of $pkgdata{pkgname}{meta}
110# meta includes Summary, Name, Version, Release, Group, Copyright,
111# Source, URL, Packager, BuildRoot, Description, BuildReq(uires),
112# Requires, Provides
113# 10/31/2005 Maybe this should be flatter? -kgd
114my %pkgdata;
115my @pkglist = ('main'); #sigh
116# Files listing. Embedding this in %pkgdata would be, um, messy.
117my %filelist;
118my $buildreq = '';
119
120# Scriptlets
121my $prepscript = '';
122my $buildscript = '';
123# %install doesn't need the full treatment from %clean; just an empty place to install to.
124# NB - rpm doesn't do this; is it really necessary?
125my $installscript = '[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT'."\n";
126my $cleanscript = '';
127
128die "Not enough arguments\n" if #$argv == 0;
129
130# Snag some environment data
131my $tmpdir;
132if (defined $ENV{TMP} && $ENV{TMP} =~ /^(\/var)?\/tmp$/) {
133 $tmpdir = $ENV{TMP};
134} else {
135 $tmpdir = "/var/tmp";
136}
137
138##main
139
140load_userconfig();
141parse_cmd();
142
143if ($cmdopts{install}) {
144 install_sdeb();
145 exit 0;
146}
147
148if ($cmdopts{type} eq 'd') {
149 parse_spec();
150 foreach my $pkg (@pkglist) {
151 $pkgdata{$pkg}{name} =~ tr/_/-/;
152
153 my $pkgfullname = "$pkgdata{$pkg}{name}_$pkgdata{$pkg}{version}-$pkgdata{main}{release}_i386.deb";
154
155 print "$pkgfullname\n";
156 }
157 exit 0;
158}
159
160# Stick --rebuild handling in here - basically install_sdeb()
161# followed by tweaking options to run with -ba
162if ($cmdopts{type} eq 's') {
163 if ($srcpkg =~ /\.src\.rpm$/) {
164 my @srclist = qx { rpm -qlp $srcpkg };
165 foreach (@srclist) {
166 chomp;
167 $specfile = "$topdir/SPECS/$_" if /\.spec$/;
168 }
169 qx { rpm -i $srcpkg };
170 } else {
171 install_sdeb();
172 my @srclist = qx { pax < $srcpkg };
173 foreach (@srclist) {
174 chomp;
175 $specfile = "$topdir/$_" if /SPECS/;
176 }
177 }
178 $cmdopts{type} = 'b';
179 $cmdopts{stage} = 'a';
180}
181
182if ($cmdopts{type} eq 'b') {
183 # Need to read the spec file to find the tarball. Note that
184 # this also generates most of the shell script required.
185 parse_spec();
186 die "Can't build $pkgdata{main}{name}: build requirements not met.\n"
187 if !checkbuildreq();
188}
189
190if ($cmdopts{type} eq 't') {
191 # Need to unpack the tarball to find the spec file. Sort of the inverse of -b above.
192 # zcat $tarball |tar -t |grep .spec
193 # collect some info about the tarball
194 $specfile = "$topdir/BUILD/". qx { zcat $tarball |tar -t |grep .spec\$ };
195 chomp $specfile;
196 my ($fileonly, $dirname) = ($tarball =~ /(([a-zA-Z0-9._-]+)\.tar\.(?:gz|bz2))$/);
197
198 $tarball = abs_path($tarball);
199 my $unpackcmd = "cd $topdir/BUILD; tar -".
200 ( $tarball =~ /\.tar\.gz$/ ? "z" : "" ).
201 ( $tarball =~ /\.tar\.bz2$/ ? "j" : "" ). "xf $tarball";
202 system "$unpackcmd";
203 system "cp $tarball $topdir/SOURCES/$fileonly";
204 system "cp $specfile $topdir/SPECS/";
205 parse_spec();
206 die "Can't build $pkgdata{main}{name}: build requirements not met.\n"
207 if !checkbuildreq();
208}
209
210# -> srcpkg if -.s
211if ($cmdopts{stage} eq 's') {
212 srcpackage();
213 exit 0;
214}
215
216# Hokay. Need to:
217# -> prep if -.p OR (-.[cilabs] AND !--short-circuit)
218if ($cmdopts{stage} eq 'p' || ($cmdopts{stage} =~ /[cilabs]/ && $cmdopts{short} ne 'y')) {
219 prep();
220}
221# -> build if -.c OR (-.[ilabs] AND !--short-circuit)
222if ($cmdopts{stage} eq 'c' || ($cmdopts{stage} =~ /[ilabs]/ && $cmdopts{short} ne 'y')) {
223 build();
224}
225# -> install if -.[ilabs]
226#if ($cmdopts{stage} eq 'i' || ($cmdopts{stage} =~ /[labs]/ && $cmdopts{short} ne 'y')) {
227if ($cmdopts{stage} =~ /[ilabs]/) {
228 install();
229#foreach my $pkg (@pkglist) {
230# print "files in $pkg:\n ".$filelist{$pkg}."\n";
231#}
232
233}
234# -> binpkg and srcpkg if -.a
235if ($cmdopts{stage} eq 'a') {
236 binpackage();
237 srcpackage();
238}
239# -> binpkg if -.b
240if ($cmdopts{stage} eq 'b') {
241 binpackage();
242}
243
244# Just in case.
245exit 0;
246
247
248## load_userconfig()
249# Loads user configuration (if any)
250# Currently only handles .debmacros
251# Needs to handle "other files"
252sub load_userconfig {
253 my (undef,undef,undef,undef,undef,undef,undef,$homedir,undef) = getpwuid($<);
254 if (-e "$homedir/.debmacros") {
255 open USERMACROS,"<$homedir/.debmacros";
256 while (<USERMACROS>) {
257 # And we also only handle a few macros at the moment.
258 if (/^\%_topdir/) {
259 my (undef,$tmp) = split /\s+/, $_;
260 $topdir = $tmp;
261 }
262 }
263 }
264} # end load_userconfig()
265
266
267## parse_cmd()
268# Parses command line into global hash %cmdopts, other globals
269# Options based on rpmbuild's options
270sub parse_cmd {
271 # Don't feel like coding my own option parser...
272 #use Getopt::Long;
273 # ... but I may have to: (OTOH, rpm uses popt, so maybe we can too.)
274 #use Getopt::Popt qw(:all);
275 # Or not. >:( Stupid Debian lack of findable Perl module names in packages.
276
277 # Stuff it.
278 my $prevopt = '';
279 foreach (@ARGV) {
280 chomp;
281
282 # Is it an option?
283 if (/^-/) {
284
285 # Is it a long option?
286 if (/^--/) {
287 if (/^--short-circuit/) {
288 $cmdopts{short} = 'y';
289 } elsif (/^--rebuild/) {
290 $cmdopts{type} = 's';
291 } elsif (/^--showpkgs/) {
292 $cmdopts{type} = 'd'; # d for 'diagnostic' or 'debug' or 'dump'
293 } else {
294 print "Long opt $_\n";
295 }
296 } else {
297 # Not a long option
298 if (/^-[bt]/) {
299 if ($cmdopts{stage} eq 's') {
300 # Mutually exclusive options.
301 die "Can't use $_ with --rebuild\n";
302 } else {
303 # Capture the type (from "bare" files or tarball) and the stage (prep, build, etc)
304 ($cmdopts{stage}) = (/^-[bt]([pcilabs])/);
305 ($cmdopts{type}) = (/^-([bt])[pcilabs]/);
306 }
307 } elsif (/^-v/) {
308 # bump verbosity. Not sure what I'll actually do here...
309 } elsif (/^-i/) {
310 $cmdopts{install} = 1;
311 $prevopt = '-i';
312 } else {
313 die "Bad option $_\n";
314 }
315 }
316
317 } else { # Not an option argument
318
319 # --buildroot is the only option that takes an argument
320 # Therefore, any *other* bare arguments are the spec file,
321 # tarball, or source package we're operating on - depending
322 # on which one we meet.
323 if ($prevopt eq '--buildroot') {
324 $cmdbuildroot = $_;
325 } elsif ($prevopt eq '-i') {
326 $srcpkg = $_;
327 } else {
328 if ($cmdopts{type} eq 's') {
329 # Source package
330 if (!/(sdeb|\.src\.rpm)$/) {
331 die "Can't --rebuild with $_\n";
332 }
333 $srcpkg = $_;
334 } elsif ($cmdopts{type} eq 'b' || $cmdopts{type} eq 'd') {
335 # Spec file
336 $specfile = $_;
337 } else {
338 # Tarball build. Need to extract tarball to find spec file. Whee.
339 $tarball = $_;
340 }
341 }
342 }
343 $prevopt = $_;
344 } # foreach @ARGV
345
346 # Some cross-checks. rpmbuild limits --short-circuit to just
347 # the "compile" and "install" targets - with good reason IMO.
348 # Note that --short-circuit with -.p is not really an error, just redundant.
349 # NB - this is NOT fatal, just ignored!
350 if ($cmdopts{short} eq 'y' && $cmdopts{stage} =~ /[labs]/) {
351 warn "Can't use --short-circuit for $targets{$cmdopts{stage}} stage. Ignoring.\n";
352 $cmdopts{short} = 'n';
353 }
354
355 # Valid options, with example arguments (if any):
356# Build from .spec file; mutually exclusive:
357 # -bp
358 # -bc
359 # -bi
360 # -bl
361 # -ba
362 # -bb
363 # -bs
364# Build from tarball; mutually exclusive:
365 # -tp
366 # -tc
367 # -ti
368 # -ta
369 # -tb
370 # -ts
371# Build from .src.(deb|rpm)
372 # --rebuild
373 # --recompile
374
375# General options
376 # --buildroot=DIRECTORY
377 # --clean
378 # --nobuild
379 # --nodeps
380 # --nodirtokens
381 # --rmsource
382 # --rmspec
383 # --short-circuit
384 # --target=CPU-VENDOR-OS
385
386 #my $popt = new Getopt::Popt(argv => \@ARGV, options => \@optionsTable);
387
388} # end parse_cmd()
389
390
391## parse_spec()
392# Parse the .spec file.
393sub parse_spec {
394 open SPECFILE,"<$specfile" or die "specfile ($specfile) barfed: $!";
395
396LINE: while (<SPECFILE>) {
397 next if /^#/; # Ignore comments...
398 next if /^\s+$/; # ... and blank lines.
399
400 if (/^\%/) {
401 # A macro that needs further processing.
402
403 if (my ($key, $def) = (/^\%define\s+([^\s]+)\s+(.+)$/) ) {
404 $specglobals{$key} = expandmacros($def,'g');
405 }
406
407 if (/^\%description(?:\s+(?:-n\s+)?(.+))?/) {
408 my $subname = "main";
409 if ($1) {
410 my $tmp = expandmacros("$1", 'g');
411 if (/-n/) { $subname = $tmp; } else { $subname = "$pkgdata{main}{name}-$tmp"; }
412 }
413 while (<SPECFILE>) {
414 next if /^#/; # Messy. Should be possible to do better. :/
415 redo LINE if /^\%/;
416 $pkgdata{$subname}{desc} .= " $_";
417 }
418 }
419 if (/^\%package\s+(?:-n\s+)?(.+)/) {
420 # gotta expand %defines here. Whee.
421 my $subname = expandmacros("$1", 'g');
422 if (! /-n/) { $subname = "$pkgdata{main}{name}-$1"; }
423 push @pkglist, $subname;
424 $pkgdata{$subname}{name} = $subname;
425 $pkgdata{$subname}{version} = $pkgdata{main}{version};
426 while (<SPECFILE>) {
427 redo LINE if /^\%/;
428 if (my ($dname,$dvalue) = (/^(Summary|Group|Version|Requires|Provides):\s+(.+)$/i)) {
429 $dname =~ tr/[A-Z]/[a-z]/;
430 $pkgdata{$subname}{$dname} = expandmacros($dvalue, 'gp');
431 }
432 }
433 }
434
435 if (/^\%prep/) {
436 # %prep section. May have %setup macro; may include %patch tags,
437 # may be just a bare shell script.
438
439 # This really should be local-ish, but we need just the filename for the source
440 $pkgdata{main}{source} =~ s|.+/([^/]+)$|$1|;
441
442 # Replace some core macros
443 $pkgdata{main}{source} = expandmacros($pkgdata{main}{source},'gp');
444
445PREPSCRIPT: while (<SPECFILE>) {
446 if (/^\%setup/) {
447 # Parse out the %setup macro. Note that we aren't supporting
448 # many of RPM's %setup features.
449 $prepscript .= "cd $topdir/BUILD\n";
450 if ( /\s+-n\s+([^\s]+)\s+/ ) {
451 $tarballdir = $1;
452 } else {
453 $tarballdir = "$pkgdata{main}{name}-$pkgdata{main}{version}";
454 }
455 $tarballdir = expandmacros($tarballdir,'gp');
456 $prepscript .= "rm -rf $tarballdir\n";
457 if (/\s+-c\s+/) {
458 $prepscript .= "mkdir $tarballdir\ncd $tarballdir\n";
459 }
460 $prepscript .= "tar -".
461 ( $pkgdata{main}{source} =~ /\.tar\.gz$/ ? "z" : "" ).
462 ( $pkgdata{main}{source} =~ /\.tar\.bz2$/ ? "j" : "" ).
463 ( /\s+-q\s+/ ? '' : 'vv' )."xf ".
464 "$topdir/SOURCES/$pkgdata{main}{source}\n".
465 qq(STATUS=\$?\nif [ \$STATUS -ne 0 ]; then\n exit \$STATUS\nfi\n).
466 "cd $topdir/BUILD/$tarballdir\n".
467 qq([ `/usr/bin/id -u` = '0' ] && /bin/chown -Rhf root .\n).
468 qq([ `/usr/bin/id -u` = '0' ] && /bin/chgrp -Rhf root .\n).
469 qq(/bin/chmod -Rf a+rX,g-w,o-w .\n);
470 } elsif ( my ($patchnum,$patchopts) = (/^\%patch([^\s]+)(\s+.+)?$/) ) {
471 chomp $patchnum;
472 $prepscript .= qq(echo "Patch #$patchnum ($pkgdata{main}{"patch$patchnum"}):"\n).
473 "patch ";
474 # If there are options passed, use'em.
475 # Otherwise, catch a bare %patch and ASS-U-ME it's '-p0'-able.
476 # Will break on options that don't provide -pnn, but what the hell.
477 $prepscript .= $patchopts if $patchopts;
478 $prepscript .= "-p0" if !$patchopts;
479 $prepscript .= " -s <$topdir/SOURCES/".$pkgdata{main}{"patch$patchnum"}."\n";
480 } else {
481 last PREPSCRIPT if /^\%/;
482 $prepscript .= $_;
483 }
484 }
485 redo LINE;
486 }
487 if (/^\%build/) {
488 # %build. This is pretty much just a shell script. There
489 # *are* a few macros, but we're not going to deal with them yet.
490 $buildscript .= "cd $tarballdir\n";
491BUILDSCRIPT: while (<SPECFILE>) {
492 if (/^\%configure/) {
493 $buildscript .= expandmacros($_,'cgbp');
494 } elsif (/^\%\{__make\}/) {
495 $buildscript .= expandmacros($_,'mgbp');
496 } else {
497 last BUILDSCRIPT if /^\%[^{]/;
498 $buildscript .= $_;
499 }
500 }
501 redo LINE;
502 }
503 if (/^\%install/) {
504 $installscript .= "cd $tarballdir\n";
505INSTALLSCRIPT: while (<SPECFILE>) {
506 if (/^\%makeinstall/) {
507 $installscript .= expandmacros($_,'igbp');
508 } else {
509 last INSTALLSCRIPT if /^\%/;
510 $installscript .= $_;
511 }
512 }
513 redo LINE;
514 }
515 if (/^\%clean/) {
516 while (<SPECFILE>) {
517 redo LINE if /^\%/;
518 $cleanscript .= $_;
519 }
520 $cleanscript = expandmacros($cleanscript,'gp');
521 }
522
523 # pre/post (un)install scripts. Note that we expand macros later anyway, so we'll leave them unexpanded here.
524 if (/^\%(pre|post|preun|postun)\b(?:\s+(?:-n\s+)?(.+))?/i) {
525 my $scriptlet = lc $1;
526 my $pkgname = 'main';
527 if ($2) { # Magic to add entries to the right list of files
528 my $tmp = expandmacros("$2", 'g');
529 if (/-n/) { $pkgname = $tmp; } else { $pkgname = "$pkgdata{main}{name}-$tmp"; }
530 }
531 while (<SPECFILE>) {
532 redo LINE if /^\%/;
533 $pkgdata{$pkgname}{$scriptlet} .= $_;
534 }
535 }
536 # done %pre/%post scripts
537
538 if (/^\%files(?:\s+(?:-n\s+)?(.+))?/) {
539 my $pkgname = 'main';
540 if ($1) { # Magic to add entries to the right list of files
541 my $tmp = expandmacros("$1", 'g');
542 if (/-n/) { $pkgname = $tmp; } else { $pkgname = "$pkgdata{main}{name}-$tmp"; }
543 }
544
545 # Set this now, so it can be flipped a bit later, and used much later.
546 #$pkgdata{$pkgname}{conffiles} = 0;
547
548 while (<SPECFILE>) {
549 chomp;
550 next if /^#/;
551 # need to update this to deal (properly) with %dir, %attr, etc
552 next if /^\%dir/;
553 next if /^\%attr/;
554 next if /^\%defattr/;
555
556 # Debian dpkg doesn't speak "%docdir". Meh.
557 next if /^\%docdir/;
558
559 # %doc needs extra processing, because it can be a space-separated list.
560 if (/^\%doc/) {
561 s/^\%doc\s+//;
562 foreach (split()) {
563 $filelist{$pkgname} .= " %{_docdir}/$_";
564 }
565 next;
566 }
567
568 # Conffiles. Note that Debian and RH have similar, but not
569 # *quite* identical ideas of what constitutes a conffile. Nrgh.
570 if (/^\%config\s+(.+)$/) {
571 $pkgdata{$pkgname}{conffiles} = 1; # Flag it for later
572 my $tmp = $1; # Now we can mangleificationate it. And we probably need to. :/
573 $tmp = expandmacros($tmp, 'gp'); # Expand common macros
574 if ($tmp !~ /\s+/) {
575 # Simplest case, just a file. Whew.
576 push @{$pkgdata{$pkgname}{conflist}}, $tmp;
577 $filelist{$pkgname} .= " $tmp";
578 } else {
579 # Wot? Spaces? That means extra %-macros. Which, for the most part, can be ignored.
580 ($tmp) = ($tmp =~ /.+\s([^\s]+)/); # Strip everything before the last space
581 push @{$pkgdata{$pkgname}{conflist}}, $tmp;
582 $filelist{$pkgname} .= " $tmp";
583 }
584 next;
585 }
586
587 # and finally we can fall through %{_<FHS>}-prefixed locations...
588 if (/^\%\{_/) {
589 $filelist{$pkgname} .= " $_";
590 next;
591 }
592 # EW. Necessary to clear up %define expansions before we exit with redo.
593 $_ = expandmacros $_, 'g';
594
595 # ... unknown or "next section" % directives ...
596 redo LINE if /^\%/;
597
598 # ... and "normal" files
599 $filelist{$pkgname} .= " $_";
600 }
601 $filelist{$pkgname} = expandmacros($filelist{$pkgname}, 'gp');
602 } # done %file section
603
604 if (/^\%changelog/) {
605 $pkgdata{main}{changelog} = '';
606 while (<SPECFILE>) {
607 redo LINE if /^\%/;
608 $pkgdata{main}{changelog} .= $_;
609 }
610 }
611
612 } else { # Data from the spec file "header"
613
614 if (/^summary:\s+(.+)/i) {
615 $pkgdata{main}{summary} = $1;
616 } elsif (/^name:\s+(.+)/i) {
617 $pkgdata{main}{name} = expandmacros($1,'g');
618 } elsif (/^version:\s+(.+)/i) {
619 $pkgdata{main}{version} = expandmacros($1,'g');
620 } elsif (/^release:\s+(.+)/i) {
621 $pkgdata{main}{release} = expandmacros($1,'g');
622 } elsif (/^group:\s+(.+)/i) {
623 $pkgdata{main}{group} = $1;
624 } elsif (/^copyright:\s+(.+)/i) {
625 $pkgdata{main}{copyright} = $1;
626 } elsif (/^url:\s+(.+)/i) {
627 $pkgdata{main}{url} = $1;
628 } elsif (/^packager:\s+(.+)/i) {
629 $pkgdata{main}{packager} = $1;
630 } elsif (/^buildroot:\s+(.+)/i) {
631 $buildroot = $1;
632 } elsif (/^source0?:\s+(.+)/i) {
633 $pkgdata{main}{source} = $1;
634 die "Unknown tarball format $1\n" if $1 !~ /\.tar\.(?:gz|bz2)$/;
635 } elsif (/^source([0-9]+):\s+(.+)/i) {
636 $pkgdata{sources}{$1} = $2;
637 } elsif (/^patch([^:]+):\s+(.+)$/i) {
638 my $patchname = "patch$1";
639 $pkgdata{main}{$patchname} = $2;
640 if ($pkgdata{main}{$patchname} =~ /\//) {
641 # URL-style patch. Rare but not unheard-of.
642 my @patchbits = split '/', $pkgdata{main}{$patchname};
643 $pkgdata{main}{$patchname} = $patchbits[$#patchbits];
644 }
645 chomp $pkgdata{main}{$patchname};
646 } elsif (/^buildreq(?:uires)?:\s+(.+)/i) {
647 $buildreq .= ", $1";
648 } elsif (/^requires:\s+(.+)/i) {
649 $pkgdata{main}{requires} .= ", ".expandmacros("$1", 'gp');
650 } elsif (/^provides:\s+(.+)/i) {
651 $pkgdata{main}{provides} .= ", $1";
652 } elsif (/^conflicts:\s+(.+)/i) {
653 $pkgdata{main}{conflicts} .= ", $1";
654 }
655#Name: suwrap
656#Version: 0.04
657#Release: 3
658#Group: Applications/System
659#Copyright: WebHart internal ONLY. :(
660#BuildArchitectures: i386
661#BuildRoot: /tmp/%{name}-%{version}
662#Url: http://virtual.webhart.net
663#Packager: Kris Deugau <kdeugau@deepnet.cx>
664#Source: ftp://virtual.webhart.net/%{name}-%{version}.tar.gz
665
666 }
667 }
668
669 # Parse and replace some more macros. More will be replaced even later.
670
671 # Expand macros as necessary.
672 $scriptletbase = expandmacros($scriptletbase,'gp');
673
674 $buildroot = $cmdbuildroot if $cmdbuildroot;
675 $buildroot = expandmacros($buildroot,'gp');
676
677 close SPECFILE;
678} # end parse_spec()
679
680
681## prep()
682# Writes and executes the %prep script (mostly) built while reading the spec file.
683sub prep {
684 # Replace some things here just to make sure.
685 $prepscript = expandmacros($prepscript,'gp');
686
687#print $prepscript; exit 0;
688
689 # create script filename
690 my $prepscriptfile = "$tmpdir/deb-tmp.prep.".int(rand(99998)+1);
691 sysopen(PREPSCRIPT, $prepscriptfile, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW)
692 or die $!;
693 print PREPSCRIPT $scriptletbase;
694 print PREPSCRIPT $prepscript;
695 close PREPSCRIPT;
696
697 # execute
698 print "Calling \%prep script $prepscriptfile...\n";
699 system("/bin/sh -e $prepscriptfile") == 0
700 or die "Can't exec: $!\n";
701
702 # and clean up
703 unlink $prepscriptfile;
704} # end prep()
705
706
707## build()
708# Writes and executes the %build script (mostly) built while reading the spec file.
709sub build {
710 # Expand the macros
711 $buildscript = expandmacros($buildscript,'cgbp');
712
713 # create script filename
714 my $buildscriptfile = "$tmpdir/deb-tmp.build.".int(rand(99998)+1);
715 sysopen(BUILDSCRIPT, $buildscriptfile, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW)
716 or die $!;
717 print BUILDSCRIPT $scriptletbase;
718 print BUILDSCRIPT $buildscript;
719 close BUILDSCRIPT;
720
721 # execute
722 print "Calling \%build script $buildscriptfile...\n";
723 system("/bin/sh -e $buildscriptfile") == 0
724 or die "Can't exec: $!\n";
725
726 # and clean up
727 unlink $buildscriptfile;
728} # end build()
729
730
731## install()
732# Writes and executes the %install script (mostly) built while reading the spec file.
733sub install {
734 # Expand the macros
735 $installscript = expandmacros($installscript,'igbp');
736
737 # create script filename
738 my $installscriptfile = "$tmpdir/deb-tmp.inst.".int(rand(99998)+1);
739 sysopen(INSTSCRIPT, $installscriptfile, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW)
740 or die $!;
741 print INSTSCRIPT $scriptletbase;
742# print INSTSCRIPT $cleanscript; # Clean up our install target before installing into it.
743 print INSTSCRIPT $installscript;
744 close INSTSCRIPT;
745
746 # execute
747 print "Calling \%install script $installscriptfile...\n";
748 system("/bin/sh -e $installscriptfile") == 0
749 or die "Can't exec: $!\n";
750
751 # and clean up
752 unlink $installscriptfile;
753} # end install()
754
755
756## binpackage()
757# Creates the binary .deb package from the installed tree in $buildroot.
758# Writes and executes a shell script to do so.
759# Creates miscellaneous files required by dpkg-deb to actually build the package file.
760# Should handle simple subpackages
761sub binpackage {
762 # Make sure we have somewhere to write the .deb file
763 if (!-e "$topdir/DEBS/i386") {
764 mkdir "$topdir/DEBS/i386";
765 }
766
767 foreach my $pkg (@pkglist) {
768
769 # Skip building a package if it doesn't actually have any files. NB: This
770 # differs slightly from rpm's behaviour where a package *will* be built -
771 # even without any files - if %files is specified anywhere. I can think
772 # of odd corner cases where that *may* be desireable.
773 next if (!$filelist{$pkg} or $filelist{$pkg} =~ /^\s*$/);
774
775 # Gotta do this first, otherwise we don't have a place to move files from %files
776 mkdir "$buildroot/$pkg";
777
778 # Eliminate any lingering % macros
779 $filelist{$pkg} = expandmacros $filelist{$pkg}, 'g';
780
781 my @pkgfilelist = split ' ', $filelist{$pkg};
782 foreach my $pkgfile (@pkgfilelist) {
783 $pkgfile = expandmacros($pkgfile, 'gp');
784 my ($fpath,$fname) = ($pkgfile =~ m|(.+?/?)?([^/]+)$|); # We don't need $fname now, but we might.
785 qx { mkdir -p $buildroot/$pkg$fpath }
786 if $fpath && $fpath ne '';
787 qx { mv $buildroot$pkgfile $buildroot/$pkg$fpath };
788 }
789
790 # Get the "Depends" (Requires) a la RPM. Ish. We strip the leading
791 # comma and space here (if needed) in case there were "Requires" specified
792 # in the spec file - those would precede these.
793 $pkgdata{$pkg}{requires} .= getreqs("$buildroot/$pkg");
794
795 # magic needed to properly version dependencies...
796 # only provided deps will really be included
797 $pkgdata{$pkg}{requires} =~ s/^, //; # Still have to do this here.
798 $pkgdata{$pkg}{requires} =~ s/\s+//g;
799 my @deps = split /,/, $pkgdata{$pkg}{requires};
800 my $tmp = '';
801 foreach my $dep (@deps) {
802 # Hack up the perl(Class::SubClass) deps into something dpkg can understand.
803 # May or may not be versioned.
804 # We do this first so the version rewriter can do its magic next.
805 if (my ($mod,$ver) = ($dep =~ /^perl\(([A-Za-z0-9\:\-]+)\)([><=]+.+)?/) ) {
806 $mod =~ s/^perl\(//;
807 $mod =~ s/\)$//;
808 $mod =~ s/::/-/g;
809 $mod =~ tr/A-Z/a-z/;
810 $mod = "lib$mod-perl";
811 $mod .= $ver if $ver;
812 $dep = $mod;
813 }
814 if (my ($name,$rel,$value) = ($dep =~ /^([a-zA-Z0-9._-]+)([><=]+)([a-zA-Z0-9._-]+)$/)) {
815 $tmp .= ", $name ($rel $value)";
816 } else {
817 $tmp .= ", $dep";
818 }
819 }
820 ($pkgdata{$pkg}{requires} = $tmp) =~ s/^, //;
821
822 # Do this here since we're doing {depends}...
823 if (defined($pkgdata{$pkg}{provides})) {
824 $pkgdata{$pkg}{provides} =~ s/^, //;
825 $pkgdata{$pkg}{provides} = expandmacros($pkgdata{$pkg}{provides},'gp');
826 }
827 if (defined($pkgdata{$pkg}{conflicts})) {
828 $pkgdata{$pkg}{conflicts} =~ s/^, //;
829 $pkgdata{$pkg}{conflicts} = expandmacros($pkgdata{$pkg}{conflicts},'gp');
830 }
831
832 # Gotta do this next, otherwise the control file has nowhere to go. >:(
833 mkdir "$buildroot/$pkg/DEBIAN";
834
835 # Hack the filename for the package into a Debian-tool-compatible format. GRRRRRR!!!!!
836 # Have I mentioned I hate Debian Policy?
837 $pkgdata{$pkg}{name} =~ tr/_/-/;
838
839 # create script filename
840 my $debscriptfile = "$tmpdir/deb-tmp.pkg.".int(rand(99998)+1);
841 sysopen(DEBSCRIPT, $debscriptfile, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW)
842 or die $!;
843 print DEBSCRIPT $scriptletbase;
844 print DEBSCRIPT "fakeroot dpkg-deb -b $buildroot/$pkg $topdir/DEBS/i386/".
845 "$pkgdata{$pkg}{name}_$pkgdata{$pkg}{version}-$pkgdata{main}{release}_i386.deb\n";
846 # %$&$%@#@@#%@@@ Debian and their horrible ugly package names. >:(
847 close DEBSCRIPT;
848
849 my $control = "Package: $pkgdata{$pkg}{name}\n".
850 "Version: $pkgdata{$pkg}{version}-$pkgdata{main}{release}\n".
851 "Section: $pkgdata{$pkg}{group}\n".
852 "Priority: optional\n".
853 "Architecture: i386\n".
854 "Maintainer: $pkgdata{main}{packager}\n".
855 ( $pkgdata{$pkg}{requires} ne '' ? "Depends: $pkgdata{$pkg}{requires}\n" : '' ).
856 ( defined($pkgdata{$pkg}{provides}) ? "Provides: $pkgdata{$pkg}{provides}\n" : '' ).
857 ( defined($pkgdata{$pkg}{conflicts}) ? "Conflicts: $pkgdata{$pkg}{conflicts}\n" : '' ).
858 "Description: $pkgdata{$pkg}{summary}\n";
859 $control .= "$pkgdata{$pkg}{desc}\n";
860
861 open CONTROL, ">$buildroot/$pkg/DEBIAN/control";
862 print CONTROL $control;
863 close CONTROL;
864
865 # Iff there are conffiles (as specified in the %files list(s), add'em
866 # in so dpkg-deb can tag them.
867 if ($pkgdata{$pkg}{conffiles}) {
868 open CONFLIST, ">$buildroot/$pkg/DEBIAN/conffiles";
869 foreach my $conffile (@{$pkgdata{$pkg}{conflist}}) {
870 print CONFLIST "$conffile\n";
871 }
872 close CONFLIST;
873 }
874
875 # found the point of scripts on subpackages.
876 if ($pkgdata{$pkg}{'pre'}) {
877 $pkgdata{$pkg}{'pre'} = expandmacros($pkgdata{$pkg}{'pre'},'gp');
878 open PREINST, ">$buildroot/$pkg/DEBIAN/preinst";
879 print PREINST "#!/bin/sh\nset -e\n\n";
880 print PREINST $pkgdata{$pkg}{'pre'};
881 close PREINST;
882 `chmod 0755 $buildroot/$pkg/DEBIAN/preinst`;
883 }
884 if ($pkgdata{$pkg}{'post'}) {
885 $pkgdata{$pkg}{'post'} = expandmacros($pkgdata{$pkg}{'post'},'gp');
886 open PREINST, ">$buildroot/$pkg/DEBIAN/postinst";
887 print PREINST "#!/bin/sh\nset -e\n\n";
888 print PREINST $pkgdata{$pkg}{'post'};
889 close PREINST;
890 `chmod 0755 $buildroot/$pkg/DEBIAN/postinst`;
891 }
892 if ($pkgdata{$pkg}{'preun'}) {
893 $pkgdata{$pkg}{'pre'} = expandmacros($pkgdata{$pkg}{'preun'},'gp');
894 open PREINST, ">$buildroot/$pkg/DEBIAN/prerm";
895 print PREINST "#!/bin/sh\nset -e\n\n";
896 print PREINST $pkgdata{$pkg}{'preun'};
897 close PREINST;
898 `chmod 0755 $buildroot/$pkg/DEBIAN/prerm`;
899 }
900 if ($pkgdata{$pkg}{'postun'}) {
901 $pkgdata{$pkg}{'postun'} = expandmacros($pkgdata{$pkg}{'postun'},'gp');
902 open PREINST, ">$buildroot/$pkg/DEBIAN/postrm";
903 print PREINST "#!/bin/sh\nset -e\n\n";
904 print PREINST $pkgdata{$pkg}{'postun'};
905 close PREINST;
906 `chmod 0755 $buildroot/$pkg/DEBIAN/postrm`;
907 }
908
909 # execute
910 print "Calling package creation script $debscriptfile for $pkgdata{$pkg}{name}...\n";
911 system("/bin/sh -e $debscriptfile") == 0
912 or die "Can't exec: $!\n";
913
914 # and clean up
915 unlink $debscriptfile;
916
917 } # subpackage loop
918
919} # end binpackage()
920
921
922## srcpackage()
923# Builds a .src.deb source package. Note that Debian's idea of
924# a "source package" is seriously flawed IMO, because you can't
925# easily copy it as-is.
926# Not quite identical to RPM, but Good Enough (TM).
927sub srcpackage {
928 # In case we were called with -bs.
929 $pkgdata{main}{name} =~ tr/_/-/;
930 my $pkgsrcname = "$pkgdata{main}{name}-$pkgdata{main}{version}-$pkgdata{main}{release}.sdeb";
931
932 my $paxcmd;
933
934 # We'll definitely need this later, and *may* need it sooner.
935 (my $barespec = $specfile) =~ s|.+/([^/]+)$|$1|;
936
937 # Copy the specfile to the build tree, but only if it's not there already.
938##buglet: need to deal with silly case where silly user has put the spec
939# file in a subdir of %{_topdir}/SPECS. Ewww. Silly user!
940 if (abs_path($specfile) !~ /^$topdir\/SPECS/) {
941 $paxcmd .= "cp $specfile %{_topdir}/SPECS/; \n"
942 }
943
944 # use pax -w [file] [file] ... >outfile.sdeb
945 $paxcmd = "cd $topdir; pax -w ";
946
947# tweak source entry into usable form. Need it locally somewhere along the line.
948 (my $pkgsrc = $pkgdata{main}{source}) =~ s|.+/([^/]+)$|$1|;
949 $paxcmd .= "SOURCES/$pkgsrc ";
950
951 # create file list: Source[nn], Patch[nn]
952 foreach my $specbit (keys %{$pkgdata{main}} ) {
953 next if $specbit eq 'source';
954 $paxcmd .= "SOURCES/$pkgdata{main}{$specbit} " if $specbit =~ /^patch/;
955##buglet: need to deal with case where patches are listed as URLs?
956# or other extended pathnames? Silly !@$%^&!%%!%!! user!
957 }
958
959 foreach my $source (keys %{$pkgdata{sources}}) {
960 $paxcmd .= "SOURCES/$pkgdata{sources}{$source} ";
961 }
962
963 # add the spec file, source package destination, and cd back where we came from.
964 $paxcmd .= "SPECS/$barespec > $topdir/SDEBS/$pkgsrcname; cd -";
965
966 # In case of %-macros...
967 $paxcmd = expandmacros($paxcmd,'gp');
968
969 system "$paxcmd";
970 print "Wrote source package $pkgsrcname in $topdir/SDEBS.\n";
971}
972
973
974## checkbuildreq()
975# Checks the build requirements (if any)
976# Spits out a rude warning and returns a true-false error if any
977# requirements are not met.
978sub checkbuildreq {
979 return 1 if $buildreq eq ''; # No use doing extra work.
980
981 if ( ! -e "/usr/bin/dpkg-query" ) {
982 print "**WARNING** dpkg-query not found. Can't check build-deps.\n".
983 " Required for sucessful build:\n".$buildreq."\n".
984 " Continuing anyway.\n";
985 return 1;
986 }
987
988 my $reqflag = 1; # unset iff a buildreq is missing
989
990 $buildreq =~ s/^, //; # Strip the leading comma and space
991 my @reqlist = split /,\s+/, $buildreq;
992
993 foreach my $req (@reqlist) {
994 my ($pkg,$rel,$ver);
995
996 # We have two classes of requirements - versioned and unversioned.
997 if ($req =~ /[><=]/) {
998 # Pick up the details of versioned buildreqs
999 ($pkg,$rel,$ver) = ($req =~ /([a-z0-9._-]+)\s+([><=]+)\s+([a-z0-9._-]+)/);
1000 } else {
1001 # And the unversioned ones.
1002 $pkg = $req;
1003 $rel = '>=';
1004 $ver = 0;
1005 }
1006
1007 my @pkglist = qx { dpkg-query --showformat '\${status}\t\${version}\n' -W $pkg };
1008# need to check if no lines returned - means a bad buildreq
1009 my ($reqstat,undef,undef,$reqver) = split /\s+/, $pkglist[0];
1010 if ($reqstat !~ /install/) {
1011 print " * Missing build-dependency $pkg!\n";
1012 $reqflag = 0;
1013 } else {
1014# gotta be a better way to do this... :/
1015 if ($rel eq '>=' && !($reqver ge $ver)) {
1016 print " * Buildreq $pkg is installed, but wrong version ($reqver): Need $ver\n";
1017 $reqflag = 0;
1018 }
1019 if ($rel eq '>' && !($reqver gt $ver)) {
1020 print " * Buildreq $pkg is installed, but wrong version ($reqver): Need $ver\n";
1021 $reqflag = 0;
1022 }
1023 if ($rel eq '<=' && !($reqver le $ver)) {
1024 print " * Buildreq $pkg is installed, but wrong version ($reqver): Need $ver\n";
1025 $reqflag = 0;
1026 }
1027 if ($rel eq '<' && !($reqver lt $ver)) {
1028 print " * Buildreq $pkg is installed, but wrong version ($reqver): Need $ver\n";
1029 $reqflag = 0;
1030 }
1031 if ($rel eq '=' && !($reqver eq $ver)) {
1032 print " * Buildreq $pkg is installed, but wrong version ($reqver): Need $ver\n";
1033 $reqflag = 0;
1034 }
1035 } # end not installed/installed check
1036 } # end req loop
1037
1038 return $reqflag;
1039} # end checkbuildreq()
1040
1041
1042## getreqs()
1043# Find out which libraries/packages are required for any
1044# executables and libs in a given file tree.
1045# (Debian doesn't have soname-level deps; just package-level)
1046# Returns an empty string if the tree contains no binaries.
1047# Doesn't work well on shell scripts. but those *should* be
1048# fine anyway. (Yeah, right...)
1049sub getreqs() {
1050 my $pkgtree = $_[0];
1051
1052 print "Checking library requirements...\n";
1053 my @binlist = qx { find $pkgtree -type f -perm 755 };
1054
1055 if (scalar(@binlist) == 0) {
1056 return '';
1057 }
1058
1059 my @reqlist;
1060 foreach (@binlist) {
1061 push @reqlist, qx { ldd $_ };
1062 }
1063
1064 # Get the list of libs provided by this package. Still doesn't
1065 # handle the case where the lib gets stuffed into a subpackage. :/
1066 my @intprovlist = qx { find $pkgtree -type f -name "*.so*" };
1067 my $provlist = '';
1068 foreach (@intprovlist) {
1069 s/$pkgtree//;
1070 $provlist .= "$_";
1071 }
1072
1073 my %reqs;
1074 my $reqlibs = '';
1075
1076 foreach (@reqlist) {
1077 next if /^$pkgtree/;
1078 next if /not a dynamic executable/;
1079 next if m|/lib/ld-linux.so|; # Hack! Hack! PTHBTT! (libc suxx0rz)
1080
1081 my ($req) = (/^\s+([a-z0-9._-]+)/); # dig out the actual library (so)name
1082
1083 # Ignore libs provided by this package. Note that we don't match
1084 # on word-boundary at the *end* of the lib we're looking for, as the
1085 # looked-for lib may not have the full soname version. (ie, it may
1086 # "just" point to one of the symlinks that get created somewhere.)
1087 next if $provlist =~ /\b$req/;
1088
1089 $reqlibs .= " $req";
1090 }
1091
1092 if ($reqlibs ne '') {
1093 foreach (qx { dpkg -S $reqlibs }) {
1094 my ($libpkg,undef) = split /:\s+/;
1095 $reqs{$libpkg} = 1;
1096 }
1097 }
1098
1099 my $deplist = '';
1100 foreach (keys %reqs) {
1101 $deplist .= ", $_";
1102 }
1103
1104# For now, we're done. We're not going to meddle with versions yet.
1105# Among other things, it's messier than handling "simple" yes/no "do
1106# we have this lib?" deps. >:(
1107
1108 return $deplist;
1109} # end getreqs()
1110
1111
1112## install_sdeb()
1113# Extracts .sdeb contents to %_topdir as appropriate
1114sub install_sdeb {
1115 my $paxcmd = "cd $topdir; pax -r <$srcpkg; cd -";
1116
1117 # In case of %-macros...
1118 $paxcmd = expandmacros($paxcmd,'gp');
1119
1120 system "$paxcmd";
1121 print "Extracted source package $srcpkg to $topdir.\n";
1122} # end install_sdeb()
1123
1124
1125## expandmacros()
1126# Expands all %{blah} macros in the passed string
1127# Split up a bit with some sections so we don't spend time trying to
1128# expand macros that are only used in a few specific places.
1129sub expandmacros {
1130 my $macrostring = shift;
1131 my $section = shift;
1132
1133 # To allow the FHS-ish %configure and %makeinstall to work The Right Way.
1134 # (Without clobbering the global $buildroot.)
1135 my $prefix = '';
1136
1137 if ($section =~ /c/) {
1138 # %configure macro
1139# Don't know what it's for, don't have a useful default replacement
1140# --program-prefix=%{_program_prefix} \
1141 $macrostring =~ s'%configure'./configure --host=$DEB_HOST_GNU_TYPE \
1142 --build=$DEB_BUILD_GNU_TYPE \
1143 --prefix=%{_prefix} \
1144 --exec-prefix=%{_exec_prefix} \
1145 --bindir=%{_bindir} \
1146 --sbindir=%{_sbindir} \
1147 --sysconfdir=%{_sysconfdir} \
1148 --datadir=%{_datadir} \
1149 --includedir=%{_includedir} \
1150 --libdir=%{_libdir} \
1151 --libexecdir=%{_libexecdir} \
1152 --localstatedir=%{_localstatedir} \
1153 --sharedstatedir=%{_sharedstatedir} \
1154 --mandir=%{_mandir} \
1155 --infodir=%{_infodir} ';
1156 } # done %configure
1157
1158 if ($section =~ /m/) {
1159 $macrostring =~ s'%{__make}'make ';
1160 } # done make
1161
1162 if ($section =~ /i/) {
1163 # This is where we need to mangle $prefix.
1164 $macrostring =~ s'%makeinstall'make %{fhs} install';
1165 $prefix = $buildroot;
1166 } # done %install and/or %makeinstall
1167
1168 # Build data
1169 # Note that these are processed in reverse order to get the substitution order right
1170 if ($section =~ /b/) {
1171# $macrostring =~ s'%{fhs}'host=$DEB_HOST_GNU_TYPE \
1172# build=$DEB_BUILD_GNU_TYPE \
1173 $macrostring =~ s'%{fhs}'prefix=%{_prefix} \
1174 exec-prefix=%{_exec_prefix} \
1175 bindir=%{_bindir} \
1176 sbindir=%{_sbindir} \
1177 sysconfdir=%{_sysconfdir} \
1178 datadir=%{_datadir} \
1179 includedir=%{_includedir} \
1180 libdir=%{_libdir} \
1181 libexecdir=%{_libexecdir} \
1182 localstatedir=%{_localstatedir} \
1183 sharedstatedir=%{_sharedstatedir} \
1184 mandir=%{_mandir} \
1185 infodir=%{_infodir} \
1186';
1187
1188 # Note that the above regex terminates with the extra space
1189 # "Just In Case" of user additions, which will then get neatly
1190 # tagged on the end where they take precedence (supposedly)
1191 # over the "default" ones.
1192
1193 # Now we cascade the macros introduced above. >_<
1194 # Wot ot to go theah:
1195 $macrostring =~ s|%{_mandir}|%{_datadir}/man|g; #/usr/share/man
1196 $macrostring =~ s|%{_infodir}|%{_datadir}/info|g; #/usr/share/info
1197 $macrostring =~ s|%{_oldincludedir}|/usr/include|g; #/usr/include
1198 $macrostring =~ s|%{_includedir}|%{_prefix\}/include|g; #/usr/include
1199 $macrostring =~ s|%{_libdir}|%{_exec_prefix}/%{_lib}|g; #/usr/lib
1200 $macrostring =~ s|%{_lib}|lib|g; #?
1201 $macrostring =~ s|%{_localstatedir}|/var|g; #/var
1202 $macrostring =~ s|%{_sharedstatedir}|%{_prefix}/com|g; #/usr/com WTF?
1203 $macrostring =~ s|%{_sysconfdir}|/etc|g; #/etc
1204 $macrostring =~ s|%{_datadir}|%{_prefix}/share|g; #/usr/share
1205 $macrostring =~ s|%{_libexecdir}|%{_exec_prefix}/libexec|g; #/usr/libexec
1206 $macrostring =~ s|%{_sbindir}|%{_exec_prefix}/sbin|g; #/usr/sbin
1207 $macrostring =~ s|%{_bindir}|%{_exec_prefix}/bin|g; #/usr/bin
1208 $macrostring =~ s|%{_exec_prefix}|%{_prefix}|g; #/usr
1209 $macrostring =~ s|%{_prefix}|/usr|g; #/usr
1210 } # done with config section
1211
1212 # Package data
1213 if ($section =~ /p/) {
1214 $macrostring =~ s/\%\{buildroot\}/$buildroot/gi;
1215 foreach my $source (keys %{$pkgdata{sources}}) {
1216 $macrostring =~ s/\%\{source$source\}/$topdir\/SOURCES\/$pkgdata{sources}{$source}/gi;
1217 }
1218 $macrostring =~ s/\%\{name\}/$pkgdata{main}{name}/gi;
1219 $macrostring =~ s/\%\{version\}/$pkgdata{main}{version}/gi;
1220 $macrostring =~ s/\%\{release\}/$pkgdata{main}{release}/gi;
1221 }
1222
1223 # Globals, and not-so-globals
1224 if ($section =~ /g/) {
1225
1226 # special %define's. Handle the general case where we eval anything.
1227 # Prime example:
1228 #%define perl_vendorlib %(eval "`perl -V:installvendorlib`"; echo $installvendorlib)
1229 if ($macrostring =~ /^\%\(eval.+\)$/) {
1230 $macrostring =~ s/^\%\(//;
1231 $macrostring =~ s/\)$//;
1232 # Oy vey this gets silly for the perl bits. Executing a shell to
1233 # call Perl to get the vendorlib/sitelib/whatever "core" globals.
1234 # This can do more, but... eww.
1235 # Next line is non-optimal - what if $macrostring contains ' characters?
1236 $macrostring = qx { /bin/sh -c '$macrostring' };
1237 }
1238
1239 $macrostring =~ s|%{_builddir}|%{_topdir}/BUILD|g;
1240 $macrostring =~ s|%{_topdir}|$topdir|g;
1241 $macrostring =~ s|%{_tmppath}|$tmpdir|g;
1242 $macrostring =~ s'%{_docdir}'/usr/share/doc'g;
1243
1244 # Standard FHS locations. More or less.
1245 $macrostring =~ s'%{_bindir}'/usr/bin'g;
1246 $macrostring =~ s'%{_sbindir}'/usr/sbin'g;
1247 $macrostring =~ s'%{_mandir}'/usr/share/man'g;
1248 $macrostring =~ s'%{_includedir}'/usr/include'g;
1249 $macrostring =~ s'%{_libdir}'/usr/lib'g;
1250 $macrostring =~ s'%{_sysconfdir}'/etc'g;
1251 $macrostring =~ s'%{_localstatedir}'/var'g;
1252
1253 # %define's
1254 foreach my $key (keys %specglobals) {
1255 $macrostring =~ s|%{$key}|$specglobals{$key}|g;
1256 }
1257
1258 # system programs. RPM uses a global config file for these; we'll just
1259 # ASS-U-ME and make life a little simpler.
1260 if ($macrostring =~ /\%\{\_\_([a-z0-9_-]+)\}/) {
1261 $macrostring =~ s|%{__([a-z0-9_-]+)}|$1|g;
1262 }
1263 } # done with globals section
1264
1265 return $macrostring;
1266} # end expandmacros()
1267
1268
1269
1270__END__
1271
1272
1273
1274=head1 NAME
1275
1276debbuild - Build Debian-compatible packages from RPM spec files
1277
1278=head1 SYNOPSIS
1279
1280 debbuild {-ba|-bb|-bp|-bc|-bi|-bl|-bs} [build-options] file.spec
1281
1282 debbuild {-ta|-tb|-tp|-tc|-ti|-tl|-ts} [build-options] file.tar.{gz|bz2}
1283
1284 debbuild --rebuild file.{src.rpm|sdeb}
1285
1286=head1 DESCRIPTION
1287
1288This script attempts to build Debian-friendly semi-native packages from RPM spec files,
1289RPM-friendly tarballs, and RPM source packages (.src.rpm files). It accepts I<most> of the
1290options rpmbuild does, and should be able to interpret most spec files usefully. Perl
1291modules should be handled via CPAN+dh-make-perl instead; Debian's conventions for such
1292things do not lend themselves to automated conversion.
1293
1294As far as possible, the command-line options are identical to those from rpmbuild, although
1295several rpmbuild options are not supported:
1296
1297 --recompile
1298 --showrc
1299 --buildroot
1300 --clean
1301 --nobuild
1302 --rmsource
1303 --rmspec
1304 --sign
1305 --target
1306
1307Some of these could probably be trivially added. Feel free to send me a patch. ;)
1308
1309Complex spec files will most likely not work well, if at all. Rewrite them from scratch -
1310you'll have to make heavy modifications anyway.
1311
1312If you see something you don't like, mail me. Send a patch if you feel inspired. I don't
1313promise I'll do anything other than say "Yup, that's broken" or "Got your message".
1314
1315=head1 ASSUMPTIONS
1316
1317As with rpmbuild, debbuild makes some assumptions about your system.
1318
1319=over 4
1320
1321=item *
1322
1323Either you have rights to do as you please under /usr/src/debian, or you have created a file
1324~/.debmacros containing a suitable %_topdir definition.
1325
1326Both rpmbuild and debbuild require the directories %_topdir/{BUILD,SOURCES,SPECS}. However,
1327where rpmbuild requires the %_topdir/{RPMS,SRPMS} directories, debbuild
1328requires %_topdir/{DEBS,SDEBS} instead. Create them in advance;
1329some subdirectories are created automatically as needed, but most are not.
1330
1331=item *
1332
1333/var/tmp must allow script execution - rpmbuild and debbuild both rely on creating and
1334executing shell scripts for much of their functionality. By default, debbuild also creates
1335install trees under /var/tmp - however this is (almost) entirely under the control of the
1336package's .spec file.
1337
1338=item *
1339
1340If you wish to --rebuild a .src.rpm, your %_topdir for both debbuild and rpmbuild must either
1341match, or be suitably symlinked one direction or another so that both programs are effectively
1342working in the same tree. (Or you could just manually wrestle files around your system.)
1343
1344You could symlink ~/.rpmmacros to ~/.debmacros (or vice versa) and save yourself some hassle
1345if you need to rebuild .src.rpm packages on a regular basis. Currently debbuild only uses the
1346%_topdir macro definition, although there are many more things that rpmbuild can use from
1347~/.rpmmacros.
1348
1349=back
1350
1351=head1 AUTHOR
1352
1353debbuild was written by Kris Deugau <kdeugau@deepnet.cx>. A version that approximates
1354current is available at http://www.deepnet.cx/debbuild/.
1355
1356=head1 BUGS
1357
1358Funky Things Happen if you forget a command-line option or two. I've been too lazy to bother
1359fixing this.
1360
1361Many macro expansions are unsupported or incompletely supported.
1362
1363The generated scriptlets don't quite match those from rpmbuild exactly. There are extra
1364environment variables and preprocessing that I haven't needed (yet).
1365
1366Dcumentation, such as it is, will likely remain perpetually out of date.
1367
1368%_topdir and the five "working" directories under %_topdir could arguably be created by
1369debbuild. However, rpmbuild doesn't create these directories either.
1370
1371=head1 SEE ALSO
1372
1373rpm(8), rpmbuild(8), and pretty much any document describing how to write a .spec file.
1374
1375=cut
Note: See TracBrowser for help on using the repository browser.