source: trunk/debbuild@ 130

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

/trunk

Exit cleanly on most of the no-specfile conditions

  • Property svn:executable set to *
  • Property svn:keywords set to Date Rev Author
File size: 59.0 KB
Line 
1#!/usr/bin/perl -w
2# debbuild script
3# Shamelessly steals interface 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: 2007-08-16 20:37:04 +0000 (Thu, 16 Aug 2007) $
9# SVN revision $Rev: 130 $
10# Last update by $Author: kdeugau $
11###
12# Copyright 2005-2007 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
32use Config;
33
34# regex debugger
35#use re "debug";
36
37die "No .spec file to work with! Exiting.\n" if scalar(@ARGV) == 0;
38
39# Program flow:
40# -> Parse/execute "system" config/macros (if any - should be rare)
41# -> Parse/execute "user" config/macros (if any - *my* requirement is %_topdir)
42# -> Parse command line for options, spec file/tarball/.src.deb (NB - also accept .src.rpm)
43
44sub expandmacros;
45
46# User's prefs for dirs, environment, etc,etc,etc.
47# config file ~/.debmacros
48# Default ordered search paths for config/macros:
49# /usr/lib/rpm/rpmrc /usr/lib/rpm/redhat/rpmrc /etc/rpmrc ~/.rpmrc
50# /usr/lib/rpm/macros /usr/lib/rpm/redhat/macros /etc/rpm/macros ~/.rpmmacros
51# **NOTE: May be possible to (ab)use bits of debhelper
52
53# Build tree
54# default is /usr/src/debian/{BUILD,SOURCES,SPECS,DEBS,SDEBS}
55
56# Globals
57my $finalmessages = ''; # A place to stuff messages that I want printed at the *very* end of any processing.
58my $specfile;
59my $tarball;
60my $srcpkg;
61my $cmdbuildroot;
62my $tarballdir = '%{name}-%{version}'; # We do this in case of a spec file not using %setup...
63my %specglobals; # For %define's in specfile, among other things.
64
65$specglobals{'_vendor'} = 'debbuild';
66
67# Initialized globals
68my $verbosity = 0;
69my $NoAutoReq = 0;
70my %cmdopts = (type => '',
71 stage => 'a',
72 short => 'n'
73 );
74my $topdir = "/usr/src/debian";
75my $buildroot = "%{_tmppath}/%{name}-%{version}-%{release}.root".int(rand(99998)+1);
76
77# "Constants"
78my %targets = ('p' => 'Prep',
79 'c' => 'Compile',
80 'i' => 'Install',
81 'l' => 'Verify %files',
82 'a' => 'Build binary and source',
83 'b' => 'Build binary',
84 's' => 'Build source'
85 );
86# Ah, the joys of multiple architectures. :( Feh.
87# As copied from rpm
88my %optflags = ( 'i386' => '-O2 -g -march=i386 -mcpu=i686',
89 'amd64' => '-O2 -g'
90 );
91my $hostarch; # we set this later...
92my $scriptletbase =
93q(#!/bin/sh
94
95 RPM_SOURCE_DIR="%{_topdir}/SOURCES"
96 RPM_BUILD_DIR="%{_topdir}/BUILD"
97 RPM_OPT_FLAGS="%{optflags}"
98 RPM_ARCH="%{_arch}"
99 RPM_OS="linux"
100 export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_ARCH RPM_OS
101 RPM_DOC_DIR="/usr/share/doc"
102 export RPM_DOC_DIR
103 RPM_PACKAGE_NAME="%{name}"
104 RPM_PACKAGE_VERSION="%{version}"
105 RPM_PACKAGE_RELEASE="%{release}"
106 export RPM_PACKAGE_NAME RPM_PACKAGE_VERSION RPM_PACKAGE_RELEASE
107 RPM_BUILD_ROOT="%{buildroot}"
108 export RPM_BUILD_ROOT
109);
110foreach (`dpkg-architecture`) {
111 s/=(.+)/="$1"/;
112 $scriptletbase .= " $_";
113 ($hostarch) = (/^DEB_HOST_ARCH="(.+)"$/) if /DEB_HOST_ARCH=/;
114}
115$scriptletbase .=
116q(
117 set -x
118 umask 022
119 cd %{_topdir}/BUILD
120);
121
122# Hackery to try to bring some semblance of sanity to packages built for more
123# than one Debian version at the same time. Whee.
124# /etc/debian-version
125my %distmap = (
126 "3.1.9ubuntu7.1" => "dapper",
127 "4ubuntu2" => "feisty",
128 "3.0" => "woody",
129 "3.1" => "sarge",
130 "4" => "etch",
131 "4.0" => "lenny",
132 "4.0.0" => "sid");
133# Enh. There doesn't seem to be any better way to do this... :(
134{
135 my $basever = qx { dpkg-query --showformat '\${version}' -W base-files };
136 if ($basever =~ /^\d\.\d\.(\d)$/) {
137 $basever =~ s/\.\d$// if $1 ne '0';
138 }
139# want to do something with this... erm, what was I going to do? O_o
140 my $releasever = qx { cat /etc/debian_version };
141 chomp $releasever;
142
143 $specglobals{"debdist"} = $distmap{$basever};
144 $specglobals{"debver"} = $basever; # this may have trouble with Ubuntu versions?
145}
146
147# Package data
148# This is the form of $pkgdata{pkgname}{meta}
149# meta includes Summary, Name, Version, Release, Group, Copyright,
150# Source, URL, Packager, BuildRoot, Description, BuildReq(uires),
151# Requires, Provides
152# 10/31/2005 Maybe this should be flatter? -kgd
153my %pkgdata;
154my @pkglist = ('main'); #sigh
155# Files listing. Embedding this in %pkgdata would be, um, messy.
156my %filelist;
157my %doclist;
158my $buildreq = '';
159
160# Scriptlets
161my $prepscript = '';
162my $buildscript = '';
163# %install doesn't need the full treatment from %clean; just an empty place to install to.
164# NB - rpm doesn't do this; is it really necessary?
165my $installscript = '[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT'."\n";
166my $cleanscript = '';
167
168# Snag some environment data
169my $tmpdir;
170if (defined $ENV{TMP} && $ENV{TMP} =~ /^(\/var)?\/tmp$/) {
171 $tmpdir = $ENV{TMP};
172} else {
173 $tmpdir = "/var/tmp";
174}
175
176##main
177
178load_userconfig();
179parse_cmd();
180
181if ($cmdopts{install}) {
182 install_sdeb();
183 exit 0;
184}
185
186# output stage of --showpkgs
187if ($cmdopts{type} eq 'd') {
188 parse_spec();
189 foreach my $pkg (@pkglist) {
190 $pkgdata{$pkg}{name} =~ tr/_/-/;
191
192 my $pkgfullname = "$pkgdata{$pkg}{name}_".
193 (defined($pkgdata{main}{epoch}) ? "$pkgdata{main}{epoch}:" : '').
194 "$pkgdata{$pkg}{version}-$pkgdata{main}{release}_$pkgdata{$pkg}{arch}.deb";
195
196 print "$pkgfullname\n" if $filelist{$pkg};
197
198 }
199 # Source package
200 print "$pkgdata{main}{name}-".
201 (defined($pkgdata{main}{epoch}) ? "$pkgdata{main}{epoch}:" : '').
202 "$pkgdata{main}{version}-$pkgdata{main}{release}.sdeb\n";
203 exit 0;
204}
205
206# Stick --rebuild handling in here - basically install_sdeb()
207# followed by tweaking options to run with -ba
208if ($cmdopts{type} eq 's') {
209 if ($srcpkg =~ /\.src\.rpm$/) {
210 my @srclist = qx { rpm -qlp $srcpkg };
211 foreach (@srclist) {
212 chomp;
213 $specfile = "$topdir/SPECS/$_" if /\.spec$/;
214 }
215 qx { rpm -i $srcpkg };
216 } else {
217 install_sdeb();
218 my @srclist = qx { pax < $srcpkg };
219 foreach (@srclist) {
220 chomp;
221 $specfile = "$topdir/$_" if /SPECS/;
222 }
223 }
224 $cmdopts{type} = 'b';
225 $cmdopts{stage} = 'a';
226}
227
228if ($cmdopts{type} eq 'b') {
229 # Need to read the spec file to find the tarball. Note that
230 # this also generates most of the shell script required.
231 parse_spec();
232 die "Can't build $pkgdata{main}{name}: build requirements not met.\n"
233 if !checkbuildreq();
234}
235
236if ($cmdopts{type} eq 't') {
237 # Need to unpack the tarball to find the spec file. Sort of the inverse of -b above.
238 # zcat $tarball |tar -t |grep .spec
239 # collect some info about the tarball
240 $specfile = "$topdir/BUILD/". qx { zcat $tarball |tar -t |grep -e '[\.]spec\$' };
241 chomp $specfile;
242 my ($fileonly, $dirname) = ($tarball =~ /(([a-zA-Z0-9._-]+)\.tar\.(?:gz|bz2))$/);
243
244 $tarball = abs_path($tarball);
245 my $unpackcmd = "cd $topdir/BUILD; tar -".
246 ( $tarball =~ /\.tar\.gz$/ ? "z" : "" ).
247 ( $tarball =~ /\.tar\.bz2$/ ? "j" : "" ). "xf $tarball";
248 system "$unpackcmd";
249 system "cp $tarball $topdir/SOURCES/$fileonly";
250 system "cp $specfile $topdir/SPECS/";
251 parse_spec();
252 die "Can't build $pkgdata{main}{name}: build requirements not met.\n"
253 if !checkbuildreq();
254}
255
256# -> srcpkg if -.s
257if ($cmdopts{stage} eq 's') {
258 srcpackage();
259 exit 0;
260}
261
262# Hokay. Need to:
263# -> prep if -.p OR (-.[cilabs] AND !--short-circuit)
264if ($cmdopts{stage} eq 'p' || ($cmdopts{stage} =~ /[cilabs]/ && $cmdopts{short} ne 'y')) {
265 prep();
266}
267# -> build if -.c OR (-.[ilabs] AND !--short-circuit)
268if ($cmdopts{stage} eq 'c' || ($cmdopts{stage} =~ /[ilabs]/ && $cmdopts{short} ne 'y')) {
269 build();
270}
271# -> install if -.[ilabs]
272#if ($cmdopts{stage} eq 'i' || ($cmdopts{stage} =~ /[labs]/ && $cmdopts{short} ne 'y')) {
273if ($cmdopts{stage} =~ /[ilabs]/) {
274 install();
275#foreach my $pkg (@pkglist) {
276# print "files in $pkg:\n ".$filelist{$pkg}."\n";
277#}
278
279}
280# -> binpkg and srcpkg if -.a
281if ($cmdopts{stage} eq 'a') {
282 binpackage();
283 srcpackage();
284 clean();
285}
286# -> binpkg if -.b
287if ($cmdopts{stage} eq 'b') {
288 binpackage();
289 clean();
290}
291
292# Spit out any closing remarks
293print $finalmessages;
294
295# Just in case.
296exit 0;
297
298
299## load_userconfig()
300# Loads user configuration (if any)
301# Currently only handles .debmacros
302# Needs to handle "other files"
303sub load_userconfig {
304 my $homedir = (getpwuid($<))[7];
305 if (-e "$homedir/.debmacros") {
306 open USERMACROS,"<$homedir/.debmacros";
307 while (<USERMACROS>) {
308 # And we also only handle a few macros at the moment.
309 if (/^\%_topdir/) {
310 my (undef,$tmp) = split /\s+/, $_;
311 $topdir = $tmp;
312 }
313 next if /^\%_/;
314 # Allow arbitrary definitions. Note that we're only doing simple defs here for now.
315 if (/^\%([a-z0-9]+)\s+(.+)$/) {
316 $specglobals{$1} = $2;
317 }
318 }
319 }
320} # end load_userconfig()
321
322
323## parse_cmd()
324# Parses command line into global hash %cmdopts, other globals
325# Options based on rpmbuild's options
326sub parse_cmd {
327 # Don't feel like coding my own option parser...
328 #use Getopt::Long;
329 # ... but I may have to: (OTOH, rpm uses popt, so maybe we can too.)
330 #use Getopt::Popt qw(:all);
331 # Or not. >:( Stupid Debian lack of findable Perl module names in packages.
332
333 # Stuff it.
334 my $prevopt = '';
335 foreach (@ARGV) {
336 chomp;
337
338 # Is it an option?
339 if (/^-/) {
340
341 # Is it a long option?
342 if (/^--/) {
343 if (/^--short-circuit/) {
344 $cmdopts{short} = 'y';
345 } elsif (/^--rebuild/) {
346 $cmdopts{type} = 's';
347 } elsif (/^--showpkgs/) {
348 $cmdopts{type} = 'd'; # d for 'diagnostic' or 'debug' or 'dump'
349 } elsif (/^--define/) {
350 # nothing to do? Can't see anything needed, we handle the actual definition later.
351##fixme
352# add --self-package here
353# deps build-essential pax fakeroot
354 } else {
355 print "Long option $_ not handled\n";
356 }
357 } else {
358 # Not a long option
359 if (/^-[bt]/) {
360 if ($cmdopts{stage} eq 's') {
361 # Mutually exclusive options.
362 die "Can't use $_ with --rebuild\n";
363 } else {
364 # Capture the type (from "bare" files or tarball) and the stage (prep, build, etc)
365 ($cmdopts{stage}) = (/^-[bt]([pcilabs])/);
366 ($cmdopts{type}) = (/^-([bt])[pcilabs]/);
367 }
368 } elsif (/^-v/) {
369 # bump verbosity. Not sure what I'll actually do here...
370 } elsif (/^-i/) {
371 $cmdopts{install} = 1;
372 $prevopt = '-i';
373 } else {
374 die "Bad option $_\n";
375 }
376 }
377
378 } else { # Not an option argument
379
380 # --buildroot is the only option that takes an argument
381 # Therefore, any *other* bare arguments are the spec file,
382 # tarball, or source package we're operating on - depending
383 # on which one we meet.
384 if ($prevopt eq '--buildroot') {
385 $cmdbuildroot = $_;
386 } elsif ($prevopt eq '--define') {
387 my ($macro,$value) = (/([a-z0-9_.-]+)(?:\s+(.+))?/i);
388 if ($value ne '') {
389 $specglobals{$macro} = $value;
390 } else {
391 warn "WARNING: missing value for macro $macro in --define! Ignoring.\n";
392 }
393 } elsif ($prevopt eq '-i') {
394 $srcpkg = $_;
395 } else {
396 if ($cmdopts{type} eq 's') {
397 # Source package
398 if (!/(sdeb|\.src\.rpm)$/) {
399 die "Can't --rebuild with $_\n";
400 }
401 $srcpkg = $_;
402 } elsif ($cmdopts{type} eq 'b' || $cmdopts{type} eq 'd') {
403 # Spec file
404 $specfile = $_;
405 } else {
406 # Tarball build. Need to extract tarball to find spec file. Whee.
407 $tarball = $_;
408 }
409 }
410 }
411 $prevopt = $_;
412 } # foreach @ARGV
413
414 # Some cross-checks. rpmbuild limits --short-circuit to just
415 # the "compile" and "install" targets - with good reason IMO.
416 # Note that --short-circuit with -.p is not really an error, just redundant.
417 # NB - this is NOT fatal, just ignored!
418 if ($cmdopts{short} eq 'y' && $cmdopts{stage} =~ /[labs]/) {
419 warn "Can't use --short-circuit for $targets{$cmdopts{stage}} stage. Ignoring.\n";
420 $cmdopts{short} = 'n';
421 }
422
423 # Valid options, with example arguments (if any):
424# Build from .spec file; mutually exclusive:
425 # -bp
426 # -bc
427 # -bi
428 # -bl
429 # -ba
430 # -bb
431 # -bs
432# Build from tarball; mutually exclusive:
433 # -tp
434 # -tc
435 # -ti
436 # -ta
437 # -tb
438 # -ts
439# Build from .src.(deb|rpm)
440 # --rebuild
441 # --recompile
442
443# General options
444 # --buildroot=DIRECTORY
445 # --clean
446 # --nobuild
447 # --nodeps
448 # --nodirtokens
449 # --rmsource
450 # --rmspec
451 # --short-circuit
452 # --target=CPU-VENDOR-OS
453
454 #my $popt = new Getopt::Popt(argv => \@ARGV, options => \@optionsTable);
455
456} # end parse_cmd()
457
458
459## parse_spec()
460# Parse the .spec file.
461sub parse_spec {
462 die "No .spec file specified! Exiting.\n" if !$specfile;
463 open SPECFILE,"<$specfile" or die "specfile ($specfile) barfed: $!";
464
465 my $iflevel = 0;
466 my $buildarch = $hostarch;
467 $pkgdata{main}{arch} = $hostarch;
468
469 my $stage = 'preamble';
470 my $subname = 'main';
471 my $scriptlet;
472
473# Basic algorithm:
474# For each line
475# if it's a member of an %if construct, branch and see which segment of the
476# spec file we need to parse and which one gets discarded, then
477# short-circuit back to the top of the loop.
478# if it's a %section, bump the stage. Preparse addons to the %section line
479# (eg subpackage) and stuff them in suitable loop-global variables, then
480# short-circuit back to the top of the loop.
481# Otherwise, parse the line according to which section we're supposedly
482# parsing right now
483
484LINE: while (<SPECFILE>) {
485 next if /^#/ && $stage eq 'preamble'; # Ignore comments...
486 next if /^\s*$/ && $stage eq 'preamble'; # ... and blank lines.
487
488# no sense in continuing if we find something we don't grok
489 # Yes, this is really horribly fugly. But it's a cheap crosscheck against invalid
490 # %-tags which also make rpmbuild barf. In theory.
491# notes: some of these are not *entirely* case-sensitive (%ifxxx), but most are.
492 # Extracted from the Maximum RPM online doc via:
493 # grep -h %[a-z] *|perl -e 'while (<>) { /\%([a-z0-9]+)\b/; print "$1|\n"; }'|sort -u
494 if (/^%[a-z]/ &&
495 $_ !~ /^%(?:attr|build|changelog|check|clean|config|configure|defattr|define|description|
496 dir|doc|docdir|else|endif|files|ghost|if|ifarch|ifn|ifnarch|ifnos|ifnxxx|fos|ifxxx|
497 install|package|patch\d+|post|postun|pre|prep|preun|readme|setup|
498 triggerin|triggerpostun|triggerun|verify|verifyscript)\b/x
499 ) {
500 my ($badtag) = (/^%([a-z]+)/i);
501 die "Unknown tag \%$badtag at line $. of $specfile\n";
502 }
503
504# preprocess %define's
505 if (my ($key, $def) = (/^\%define\s+([^\s]+)\s+(.+)$/) ) {
506 $specglobals{$key} = expandmacros($def,'g');
507 }
508
509 if (/^\%if/) {
510 s/^\%if//;
511 chomp;
512 my $expr = expandmacros($_, 'g');
513 $iflevel++;
514
515 if ($expr !~ /^\s*\d+\s*$/) {
516 # gots a logic statement we want to turn into a 1 or a 0. most likely by eval'ing it.
517
518 $expr =~ s/\s+//g;
519
520# For Great w00tness! New and Improved multilayered logic handling.
521
522 my @bits = split /\b/, $expr;
523 $expr = '';
524 foreach my $bit (@bits) {
525 next if $bit eq '"';
526 $bit =~ s/"//g;
527 $expr .= qq("$bit") if $bit =~ /^\w+$/;
528 $expr .= $bit if $bit !~ /^\w+$/;
529 }
530
531 # Done in this order so we don't cascade incorrectly. Yes, those spaces ARE correct in the replacements!
532 $expr =~ s/==/ eq /g;
533 $expr =~ s/!=/ ne /g;
534 $expr =~ s/<=>/ cmp /g;
535 $expr =~ s/<=/ le /g;
536 $expr =~ s/>=/ ge /g;
537 $expr =~ s/</ lt /g;
538 $expr =~ s/>/ gt /g;
539
540 # Turn it into something that eval's to a number. Maybe not needed? O_o
541 #$expr = "( $expr ? 1 : 0 )";
542
543 $expr = eval $expr;
544 }
545
546 next LINE if $expr != 0; # This appears to be the only case we call false.
547 while (<SPECFILE>) {
548 if (/^\%endif/) {
549 $iflevel--;
550 next LINE;
551 } elsif (/^\%else/) {
552 next LINE;
553 }
554 }
555 }
556 if (/^\%else/) {
557 while (<SPECFILE>) {
558 if (/^\%endif/) {
559 $iflevel--;
560 next LINE;
561 }
562 }
563 }
564 if (/^\%endif/) {
565 $iflevel--;
566 next LINE;
567 } # %if/%else/%endif
568
569 if (/^\%{echo:(.+)}/) {
570 my $output = expandmacros($1, 'gp');
571 print "$output\n";
572 }
573
574# now we pick out the sections and set "state" to parse that section. Fugly but I can't see a better way. >:(
575
576 if (/^\%description(?:\s+(?:-n\s+)?(.+))?/) {
577 $stage = 'desc';
578 $subname = "main";
579 if ($1) { # Magic to add entries to the right package
580 my $tmp = expandmacros("$1", 'g');
581 if (/-n/) { $subname = $tmp; } else { $subname = "$pkgdata{main}{name}-$tmp"; }
582 }
583 next LINE;
584 } # %description
585
586 if (/^\%package\s+(?:-n\s+)?(.+)/) {
587 $stage = 'package';
588 if ($1) { # Magic to add entries to the right package
589 my $tmp = expandmacros("$1", 'g');
590 if (/-n/) { $subname = $tmp; } else { $subname = "$pkgdata{main}{name}-$tmp"; }
591 }
592 push @pkglist, $subname;
593 $pkgdata{$subname}{name} = $subname;
594 $pkgdata{$subname}{version} = $pkgdata{main}{version};
595 # Build "same arch as previous package found" by default. Where rpm just picks the
596 # *very* last one, we want to allow arch<native>+arch-all
597 # (eg, Apache is i386, but apache-manual is all)
598 $pkgdata{$subname}{arch} = $buildarch; # Since it's likely subpackages will NOT have a BuildArch line...
599 next LINE;
600 } # %package
601
602 if (/^\%prep/) {
603 $stage = 'prep';
604 # This really should be local-ish, but we need just the filename for the source
605 $pkgdata{main}{source} =~ s|.+/([^/]+)$|$1|;
606 # Replace some core macros
607 $pkgdata{main}{source} = expandmacros($pkgdata{main}{source},'gp');
608 next LINE;
609 } # %prep
610
611 if (/^\%build/) {
612 $stage = 'build';
613 $buildscript .= "cd $tarballdir\n";
614 next LINE;
615 } # %build
616
617 if (/^\%install/) {
618 $stage = 'install';
619 $installscript .= "cd $tarballdir\n";
620 next LINE;
621 } # %install
622
623 if (/^\%clean/) {
624 $stage = 'clean';
625 $cleanscript .= "cd $tarballdir\n";
626 next LINE;
627 } # %clean
628
629 if (/^\%(pre|post|preun|postun)\b(?:\s+(?:-n\s+)?(.+))?/i) {
630 $stage = 'prepost';
631 $scriptlet = lc $1;
632 $subname = 'main';
633 if ($2) { # Magic to add entries to the right package
634 my $tmp = expandmacros("$2", 'g');
635 if (/-n/) { $subname = $tmp; } else { $subname = "$pkgdata{main}{name}-$tmp"; }
636 }
637 next LINE;
638 } # %pre/%post/%preun/%postun
639
640 if (/^\%files(?:\s+(?:-n\s+)?(.+))?/) {
641 $stage = 'files';
642 $subname = 'main';
643 if ($1) { # Magic to add entries to the right list of files
644 my $tmp = expandmacros("$1", 'g');
645 if (/-n/) { $subname = $tmp; } else { $subname = "$pkgdata{main}{name}-$tmp"; }
646 }
647 next LINE;
648 } # %files
649
650 if (/^\%changelog/) {
651 $stage = 'changelog';
652 $pkgdata{main}{changelog} = '';
653 next LINE;
654 }
655
656# now we handle individual lines from the various sections
657
658 if ($stage eq 'desc') {
659 $pkgdata{$subname}{desc} .= " $_";
660 } # description
661
662 if ($stage eq 'package') {
663 # gotta expand %defines here. Whee.
664# Note that we look for the Debian-specific Recommends, Suggests, and Replaces,
665# although they will have to be wrapped in '%if %{_vendor} == "debbuild"' for
666# an rpmbuild-compatible .spec file
667# NB: NOT going to support Pre-Depends, since it's a "Don't Use" (mis)feature, and
668# RPM's support for a similar tag (PreReq) has been recently dropped.
669 if (my ($dname,$dvalue) = (/^(Recommends|Suggests|Replaces|Summary|Group|Version|Requires|Conflicts|Provides|BuildArch(?:itecture)?):\s+(.+)$/i)) {
670 $dname =~ tr/[A-Z]/[a-z]/;
671 if ($dname =~ /^BuildArch/i) {
672 $dvalue =~ s/^noarch/all/ig;
673 $buildarch = $dvalue; # Emulate rpm's behaviour to a degree
674 $dname = 'arch';
675 }
676 $pkgdata{$subname}{$dname} = expandmacros($dvalue, 'gp');
677 }
678 } # package
679
680 if ($stage eq 'prep') {
681 # Actual handling for %prep section. May have %setup macro; may
682 # include %patch tags, may be just a bare shell script.
683 if (/^\%setup/) {
684 # Parse out the %setup macro. Note that we aren't supporting
685 # many of RPM's %setup features.
686 $prepscript .= "cd $topdir/BUILD\n";
687 if ( /\s+-n\s+([^\s]+)\s+/ ) {
688 $tarballdir = $1;
689 }
690 $tarballdir = expandmacros($tarballdir,'gp');
691 $prepscript .= "rm -rf $tarballdir\n";
692 if (/\s+-c\s+/) {
693 $prepscript .= "mkdir $tarballdir\ncd $tarballdir\n";
694 }
695 $prepscript .= "tar -".
696 ( $pkgdata{main}{source} =~ /\.tar\.gz$/ ? "z" : "" ).
697 ( $pkgdata{main}{source} =~ /\.tar\.bz2$/ ? "j" : "" ).
698 ( /\s+-q\s+/ ? '' : 'vv' )."xf ".
699 "$topdir/SOURCES/$pkgdata{main}{source}\n".
700 qq(STATUS=\$?\nif [ \$STATUS -ne 0 ]; then\n exit \$STATUS\nfi\n).
701 "cd $topdir/BUILD/$tarballdir\n".
702 qq([ `/usr/bin/id -u` = '0' ] && /bin/chown -Rhf root .\n).
703 qq([ `/usr/bin/id -u` = '0' ] && /bin/chgrp -Rhf root .\n).
704 qq(/bin/chmod -Rf a+rX,g-w,o-w .\n);
705 } elsif ( my ($patchnum,$patchopts) = (/^\%patch([^\s]+)(\s+.+)?$/) ) {
706 chomp $patchnum;
707 $prepscript .= qq(echo "Patch #$patchnum ($pkgdata{main}{"patch$patchnum"}):"\n).
708 "patch ";
709 # If there are options passed, use'em.
710 # Otherwise, catch a bare %patch and ASS-U-ME it's '-p0'-able.
711 # Will break on options that don't provide -pnn, but what the hell.
712 $prepscript .= $patchopts if $patchopts;
713 $prepscript .= "-p0" if !$patchopts;
714 $prepscript .= " -s <$topdir/SOURCES/".$pkgdata{main}{"patch$patchnum"}."\n";
715 } else {
716 $prepscript .= expandmacros($_,'gp');
717 }
718 next LINE;
719 } # prep
720
721 if ($stage eq 'build') {
722 # %build. This is pretty much just a shell script. There
723 # aren't many local macros to deal with.
724 if (/^\%configure/) {
725 $buildscript .= expandmacros($_,'cgbp');
726 } elsif (/^\%\{__make\}/) {
727 $buildscript .= expandmacros($_,'mgbp');
728 } else {
729 $buildscript .= expandmacros($_,'gp');
730 }
731 next LINE;
732 } # build
733
734 if ($stage eq 'install') {
735 if (/^\%makeinstall/) {
736 $installscript .= expandmacros($_,'igbp');
737 } else {
738 $installscript .= expandmacros($_,'gp');
739 }
740 next LINE;
741 } # install
742
743 if ($stage eq 'clean') {
744 $cleanscript .= expandmacros($_,'gp');
745 next LINE;
746 } # clean
747
748 if ($stage eq 'prepost') {
749 $pkgdata{$subname}{$scriptlet} .= expandmacros($_,'gp');
750 next LINE;
751 } # prepost
752
753 if ($stage eq 'files') {
754 # need to deal with these someday
755 next LINE if /^\%dir/;
756 next LINE if /^\%defattr/;
757 next LINE if /^\%verify/;
758 # dunno what to do with this; not sure if there's space in Debian's package structure for it.
759 next LINE if /^\%ghost/;
760 # Debian dpkg doesn't speak "%docdir". Meh.
761 next LINE if /^\%docdir/;
762# my $singleton = 0; # don't recall what this was for
763
764# create and initialize flags
765 my ($perms, $owner, $group, $conf, $filesline);
766 $perms = $owner = $group = $conf = '-';
767
768 $filesline = $_;
769
770 # strip and flag %attr constructs
771 if ($filesline =~ /\%attr\b/) {
772 # Extract %attr...
773 my ($args) = (/(\%attr\s*\(\s*[\d-]+\s*,\s*["a-zA-Z0-9-]+\s*,\s*["a-zA-Z0-9-]+\s*\))/);
774 $args =~ s/\s+//g;
775 $args =~ s/"//g; # don't think quotes are ever necessary, but they're *allowed*
776 # ... and parse it ...
777 ($perms,$owner,$group) = ($args =~ /\(([\d-]+),([a-zA-Z0-9-]+),([a-zA-Z0-9-]+)/);
778 # ... and wipe it when we're done.
779 $filesline =~ s/\%attr\s*\(\s*[\d-]+\s*,\s*["a-zA-Z0-9-]+\s*,\s*["a-zA-Z0-9-]+\s*\)//;
780 }
781
782 # Conffiles. Note that Debian and RH have similar, but not
783 # *quite* identical ideas of what constitutes a conffile. Nrgh.
784 # Note that dpkg will always ask if you want to replace the file - noreplace
785 # is more or less permanently enabled.
786##fixme
787# also need to handle missingok (file that doesn't exist, but should be removed on uninstall)
788# hmm. not sure if such is **POSSIBLE** with Debian... maybe an addition to %post?
789 if ($filesline =~ /\%config\b(?:\s*\(\s*noreplace\s*\)\s*)?/) {
790 $pkgdata{$subname}{conffiles} = 1; # Flag it for later
791 $conf = 'y';
792 $filesline =~ s/\%config\b(?:\s*\(\s*noreplace\s*\)\s*)?//;
793 }
794
795 # %doc needs extra processing, because it can be a space-separated list, and may
796 # include both full and partial pathnames. The partial pathnames must be fiddled
797 # into place in the %install script, because Debian doesn't really have the concept
798 # of "documentation file" that rpm does. (Debian "documentation files" are files
799 # in /usr/share/doc/<packagename>.)
800##fixme: unhandled case: %doc %defattr. Eeep.
801# don't really know what to do with %defattr, generally. :(
802 if ($filesline =~ /\%doc\b/) {
803 $filesline =~ s/\s*\%doc\s+//;
804
805# this could probably go elsewhere.
806 my $pkgname = $pkgdata{$subname}{name};
807 $pkgname =~ tr/_/-/;
808
809 # have to extract the partial pathnames that %doc installs automagically
810 foreach (split /\s+/, $filesline) {
811 if (! (/^\%/ or m|^/|) ) {
812 $doclist{$subname} .= " $_";
813 my ($element) = m|([^/\s]+/?)$|;
814 $filesline =~ s|$_|\%{_docdir}/$pkgname/$element|;
815 }
816 }
817 } # $filesline =~ /\%doc\b/
818
819 $filesline =~ s/^\s*//; # Just In Case. For, uh, neatness.
820
821# due to Debian's total lack of real permissions-processing in its actual package
822# handling component (dpkg-deb), this can't really be done "properly". We'll have
823# to add chown/chmod commands to the postinst instead. Feh.
824 $pkgdata{$subname}{'post'} .= "chown $owner $filesline\n" if $owner ne '-';
825 $pkgdata{$subname}{'post'} .= "chgrp $group $filesline\n" if $group ne '-';
826 $pkgdata{$subname}{'post'} .= "chmod $perms $filesline\n" if $perms ne '-';
827
828##fixme
829# need hackery to assure only one filespec per %config. NB: "*" is one filespec. <g>
830 push @{$pkgdata{$subname}{conflist}}, $filesline if $conf ne '-';
831
832 # now that we've got the specials out of the way, we can add things to the appropriate list of files.
833 # ... and finally everything else
834 $filelist{$subname} .= " $filesline";
835
836 next LINE;
837 } # files
838
839 if ($stage eq 'changelog') {
840 # this is one of the few places we do NOT generally want to replace macros...
841 $pkgdata{main}{changelog} .= $_;
842 }
843
844 if ($stage eq 'preamble') {
845 if (/^summary:\s+(.+)/i) {
846 $pkgdata{main}{summary} = $1;
847 } elsif (/^name:\s+(.+)/i) {
848 $pkgdata{main}{name} = expandmacros($1,'g');
849 } elsif (/^epoch:\s+(.+)/i) {
850 $pkgdata{main}{epoch} = expandmacros($1,'g');
851 } elsif (/^version:\s+(.+)/i) {
852 $pkgdata{main}{version} = expandmacros($1,'g');
853 } elsif (/^release:\s+(.+)/i) {
854 $pkgdata{main}{release} = expandmacros($1,'g');
855 } elsif (/^group:\s+(.+)/i) {
856 $pkgdata{main}{group} = $1;
857 } elsif (/^copyright:\s+(.+)/i) {
858 $pkgdata{main}{copyright} = $1;
859 } elsif (/^url:\s+(.+)/i) {
860 $pkgdata{main}{url} = $1;
861 } elsif (/^packager:\s+(.+)/i) {
862 $pkgdata{main}{packager} = $1;
863 } elsif (/^buildroot:\s+(.+)/i) {
864 $buildroot = $1;
865 } elsif (/^source0?:\s+(.+)/i) {
866 $pkgdata{main}{source} = $1;
867 die "Unknown tarball format $1\n" if $1 !~ /\.tar\.(?:gz|bz2)$/;
868 } elsif (/^source([0-9]+):\s+(.+)/i) {
869 $pkgdata{sources}{$1} = $2;
870 } elsif (/^patch([^:]+):\s+(.+)$/i) {
871 my $patchname = "patch$1";
872 $pkgdata{main}{$patchname} = $2;
873 if ($pkgdata{main}{$patchname} =~ /\//) {
874 # URL-style patch. Rare but not unheard-of.
875 my @patchbits = split '/', $pkgdata{main}{$patchname};
876 $pkgdata{main}{$patchname} = $patchbits[$#patchbits];
877 }
878 chomp $pkgdata{main}{$patchname};
879 } elsif (/^buildarch(?:itecture)?:\s+(.+)/i) {
880 $pkgdata{main}{arch} = $1;
881 $pkgdata{main}{arch} =~ s/^noarch$/all/;
882 $buildarch = $pkgdata{main}{arch};
883 } elsif (/^buildreq(?:uires)?:\s+(.+)/i) {
884 $buildreq .= ", $1";
885 } elsif (/^requires:\s+(.+)/i) {
886 $pkgdata{main}{requires} .= ", ".expandmacros("$1", 'gp');
887 } elsif (/^provides:\s+(.+)/i) {
888 $pkgdata{main}{provides} .= ", $1";
889 } elsif (/^conflicts:\s+(.+)/i) {
890 $pkgdata{main}{conflicts} .= ", $1";
891 } elsif (/^recommends:\s+(.+)/i) {
892 $pkgdata{main}{recommends} .= ", $1";
893 warn "Warning: Debian-specific 'Recommends:' outside \%if wrapper\n" if $iflevel == 0;
894 } elsif (/^suggests:\s+(.+)/i) {
895 $pkgdata{main}{suggests} .= ", $1";
896 warn "Warning: Debian-specific 'Suggests:' outside \%if wrapper\n" if $iflevel == 0;
897 } elsif (/^replaces:\s+(.+)/i) {
898 $pkgdata{main}{replaces} .= ", $1";
899 warn "Warning: Debian-specific 'Replaces:' outside \%if wrapper\n" if $iflevel == 0;
900 } elsif (/^autoreq(?:prov)?:\s+(.+)/i) {
901 # we don't handle auto-provides (yet)
902 $NoAutoReq = 1 if $1 =~ /(?:no|0)/i;
903 }
904 next LINE;
905 } # preamble
906
907 } # while <SPEC>
908
909 # Parse and replace some more macros. More will be replaced even later.
910
911 # Expand macros as necessary.
912 $scriptletbase = expandmacros($scriptletbase,'gp');
913
914 $cleanscript = expandmacros($cleanscript,'gp');
915
916 $buildroot = $cmdbuildroot if $cmdbuildroot;
917 $buildroot = expandmacros($buildroot,'gp');
918
919 close SPECFILE;
920} # end parse_spec()
921
922
923## prep()
924# Writes and executes the %prep script (mostly) built while reading the spec file.
925sub prep {
926 # Replace some things here just to make sure.
927 $prepscript = expandmacros($prepscript,'gp');
928
929 # create script filename
930 my $prepscriptfile = "$tmpdir/deb-tmp.prep.".int(rand(99998)+1);
931 sysopen(PREPSCRIPT, $prepscriptfile, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW)
932 or die $!;
933 print PREPSCRIPT $scriptletbase;
934 print PREPSCRIPT $prepscript;
935 close PREPSCRIPT;
936
937 # execute
938 print "Calling \%prep script $prepscriptfile...\n";
939 system("/bin/sh -e $prepscriptfile") == 0
940 or die "Can't exec: $!\n";
941
942 # and clean up
943 unlink $prepscriptfile;
944} # end prep()
945
946
947## build()
948# Writes and executes the %build script (mostly) built while reading the spec file.
949sub build {
950 # Expand the macros
951 $buildscript = expandmacros($buildscript,'cgbp');
952
953 # create script filename
954 my $buildscriptfile = "$tmpdir/deb-tmp.build.".int(rand(99998)+1);
955 sysopen(BUILDSCRIPT, $buildscriptfile, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW)
956 or die $!;
957 print BUILDSCRIPT $scriptletbase;
958 print BUILDSCRIPT $buildscript;
959 close BUILDSCRIPT;
960
961 # execute
962 print "Calling \%build script $buildscriptfile...\n";
963 system("/bin/sh -e $buildscriptfile") == 0
964 or die "Can't exec: $!\n";
965
966 # and clean up
967 unlink $buildscriptfile;
968} # end build()
969
970
971## install()
972# Writes and executes the %install script (mostly) built while reading the spec file.
973sub install {
974
975 # munge %doc entries into place
976 # rpm handles this with a separate executed %doc script, we're not going to bother.
977 foreach my $docpkg (keys %doclist) {
978 my $pkgname = $pkgdata{$docpkg}{name};
979 $pkgname =~ s/_/-/g;
980
981 $installscript .= "DOCDIR=\$RPM_BUILD_ROOT\%{_docdir}/$pkgname\nexport DOCDIR\n";
982 $installscript .= "mkdir -p \$DOCDIR\n";
983 $doclist{$docpkg} =~ s/^\s*//;
984 foreach (split(' ',$doclist{$docpkg})) {
985 $installscript .= "cp -pr $_ \$DOCDIR/\n";
986 }
987 }
988
989 # Expand the macros
990 $installscript = expandmacros($installscript,'igbp');
991
992 # create script filename
993 my $installscriptfile = "$tmpdir/deb-tmp.inst.".int(rand(99998)+1);
994 sysopen(INSTSCRIPT, $installscriptfile, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW)
995 or die $!;
996 print INSTSCRIPT $scriptletbase;
997 print INSTSCRIPT $installscript;
998 close INSTSCRIPT;
999
1000 # execute
1001 print "Calling \%install script $installscriptfile...\n";
1002 system("/bin/sh -e $installscriptfile") == 0
1003 or die "Can't exec: $!\n";
1004
1005 # and clean up
1006 unlink $installscriptfile;
1007} # end install()
1008
1009
1010## binpackage()
1011# Creates the binary .deb package from the installed tree in $buildroot.
1012# Writes and executes a shell script to do so.
1013# Creates miscellaneous files required by dpkg-deb to actually build the package file.
1014# Should handle simple subpackages
1015sub binpackage {
1016
1017 foreach my $pkg (@pkglist) {
1018
1019 $pkgdata{$pkg}{arch} = $hostarch if !$pkgdata{$pkg}{arch}; # Just In Case.
1020
1021 # Make sure we have somewhere to write the .deb file
1022 if (!-e "$topdir/DEBS/$pkgdata{$pkg}{arch}") {
1023 mkdir "$topdir/DEBS/$pkgdata{$pkg}{arch}";
1024 }
1025
1026 # Skip building a package if it doesn't actually have any files. NB: This
1027 # differs slightly from rpm's behaviour where a package *will* be built -
1028 # even without any files - if %files is specified anywhere. I can think
1029 # of odd corner cases where that *may* be desireable.
1030 next if (!$filelist{$pkg} or $filelist{$pkg} =~ /^\s*$/);
1031
1032 # Gotta do this first, otherwise we don't have a place to move files from %files
1033 mkdir "$buildroot/$pkg";
1034
1035 # Eliminate any lingering % macros
1036 $filelist{$pkg} = expandmacros $filelist{$pkg}, 'g';
1037
1038 my @pkgfilelist = split ' ', $filelist{$pkg};
1039 foreach my $pkgfile (@pkgfilelist) {
1040 $pkgfile = expandmacros($pkgfile, 'gp');
1041
1042 # Feh. Manpages don't **NEED** to be gzipped, but rpmbuild does, and so shall we.
1043 if ($pkgfile =~ m|/usr/share/man/man|) {
1044 # need to check to see if manpage is gzipped
1045 if (-e "$buildroot$pkgfile") {
1046 if ($pkgfile !~ m|\.gz$|) {
1047 qx { gzip $buildroot$pkgfile };
1048 $pkgfile .= ".gz";
1049 }
1050 } else {
1051 if ($pkgfile !~ m|\.gz$|) {
1052 $pkgfile .= ".gz";
1053 } else {
1054 $pkgfile =~ s/\.gz$//;
1055 qx { gzip $buildroot$pkgfile };
1056 $pkgfile .= ".gz";
1057 }
1058 }
1059 }
1060
1061 my ($fpath,$fname) = ($pkgfile =~ m|(.+?/?)?([^/]+/?)$|); # We don't need $fname now, but we might.
1062 qx { mkdir -p $buildroot/$pkg$fpath }
1063 if $fpath && $fpath ne '';
1064 qx { mv $buildroot$pkgfile $buildroot/$pkg$fpath };
1065 }
1066
1067 # Get the "Depends" (Requires) a la RPM. Ish. We strip the leading
1068 # comma and space here (if needed) in case there were "Requires" specified
1069 # in the spec file - those would precede these.
1070 $pkgdata{$pkg}{requires} .= getreqs("$buildroot/$pkg") if ! $NoAutoReq;
1071
1072 # magic needed to properly version dependencies...
1073 # only provided deps will really be included
1074 $pkgdata{$pkg}{requires} =~ s/^, //; # Still have to do this here.
1075 $pkgdata{$pkg}{requires} =~ s/\s+//g;
1076 my @deps = split /,/, $pkgdata{$pkg}{requires};
1077 my $tmp = '';
1078 foreach my $dep (@deps) {
1079 # Hack up the perl(Class::SubClass) deps into something dpkg can understand.
1080 # May or may not be versioned.
1081 # We do this first so the version rewriter can do its magic next.
1082 if (my ($mod,$ver) = ($dep =~ /^perl\(([A-Za-z0-9\:\-]+)\)([><=]+.+)?/) ) {
1083 $mod =~ s/^perl\(//;
1084 $mod =~ s/\)$//;
1085 $mod =~ s/::/-/g;
1086 $mod =~ tr/A-Z/a-z/;
1087 $mod = "lib$mod-perl";
1088 $mod .= $ver if $ver;
1089 $dep = $mod;
1090 }
1091 if (my ($name,$rel,$value) = ($dep =~ /^([a-zA-Z0-9._-]+)([><=]+)([a-zA-Z0-9._-]+)$/)) {
1092 $tmp .= ", $name ($rel $value)";
1093 } else {
1094 $tmp .= ", $dep";
1095 }
1096 }
1097 ($pkgdata{$pkg}{requires} = $tmp) =~ s/^, //;
1098
1099 # Do this here since we're doing {depends}...
1100 if (defined($pkgdata{$pkg}{provides})) {
1101 $pkgdata{$pkg}{provides} =~ s/^, //;
1102 $pkgdata{$pkg}{provides} = expandmacros($pkgdata{$pkg}{provides},'gp');
1103 }
1104 if (defined($pkgdata{$pkg}{conflicts})) {
1105 $pkgdata{$pkg}{conflicts} =~ s/^, //;
1106 $pkgdata{$pkg}{conflicts} = expandmacros($pkgdata{$pkg}{conflicts},'gp');
1107 }
1108
1109# These are Debian-specific!
1110 if (defined($pkgdata{$pkg}{recommends})) {
1111 $pkgdata{$pkg}{recommends} =~ s/^, //;
1112 $pkgdata{$pkg}{recommends} = expandmacros($pkgdata{$pkg}{recommends},'gp');
1113 }
1114 if (defined($pkgdata{$pkg}{suggests})) {
1115 $pkgdata{$pkg}{suggests} =~ s/^, //;
1116 $pkgdata{$pkg}{suggests} = expandmacros($pkgdata{$pkg}{suggests},'gp');
1117 }
1118 if (defined($pkgdata{$pkg}{replaces})) {
1119 $pkgdata{$pkg}{replaces} =~ s/^, //;
1120 $pkgdata{$pkg}{replaces} = expandmacros($pkgdata{$pkg}{replaces},'gp');
1121 }
1122
1123 # Gotta do this next, otherwise the control file has nowhere to go. >:(
1124 mkdir "$buildroot/$pkg/DEBIAN";
1125
1126 # Hack the filename for the package into a Debian-tool-compatible format. GRRRRRR!!!!!
1127 # Have I mentioned I hate Debian Policy?
1128 $pkgdata{$pkg}{name} =~ tr/_/-/;
1129
1130 # create script filename
1131 my $debscriptfile = "$tmpdir/deb-tmp.pkg.".int(rand(99998)+1);
1132 sysopen(DEBSCRIPT, $debscriptfile, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW)
1133 or die $!;
1134 print DEBSCRIPT $scriptletbase;
1135 print DEBSCRIPT "fakeroot dpkg-deb -b $buildroot/$pkg $topdir/DEBS/$pkgdata{$pkg}{arch}/".
1136 "$pkgdata{$pkg}{name}_".
1137 (defined($pkgdata{main}{epoch}) ? "$pkgdata{main}{epoch}:" : '').
1138 "$pkgdata{$pkg}{version}-$pkgdata{main}{release}_$pkgdata{$pkg}{arch}.deb\n";
1139 # %$&$%@#@@#%@@@ Debian and their horrible ugly package names. >:(
1140 close DEBSCRIPT;
1141
1142 my $control = "Package: $pkgdata{$pkg}{name}\n".
1143 "Version: ".
1144 (defined($pkgdata{main}{epoch}) ? "$pkgdata{main}{epoch}:" : '').
1145 "$pkgdata{$pkg}{version}-$pkgdata{main}{release}\n".
1146 "Section: $pkgdata{$pkg}{group}\n".
1147 "Priority: optional\n".
1148 "Architecture: $pkgdata{$pkg}{arch}\n".
1149 "Maintainer: $pkgdata{main}{packager}\n".
1150 ( $pkgdata{$pkg}{requires} ne '' ? "Depends: $pkgdata{$pkg}{requires}\n" : '' ).
1151 ( defined($pkgdata{$pkg}{provides}) ? "Provides: $pkgdata{$pkg}{provides}\n" : '' ).
1152 ( defined($pkgdata{$pkg}{conflicts}) ? "Conflicts: $pkgdata{$pkg}{conflicts}\n" : '' ).
1153 ( defined($pkgdata{$pkg}{recommends}) ? "Recommends: $pkgdata{$pkg}{recommends}\n" : '' ).
1154 ( defined($pkgdata{$pkg}{suggests}) ? "Suggests: $pkgdata{$pkg}{suggests}\n" : '' ).
1155 ( defined($pkgdata{$pkg}{replaces}) ? "Replaces: $pkgdata{$pkg}{replaces}\n" : '' ).
1156 "Description: $pkgdata{$pkg}{summary}\n";
1157 $control .= "$pkgdata{$pkg}{desc}\n";
1158
1159 open CONTROL, ">$buildroot/$pkg/DEBIAN/control";
1160 print CONTROL $control;
1161 close CONTROL;
1162
1163 # Iff there are conffiles (as specified in the %files list(s), add'em
1164 # in so dpkg-deb can tag them.
1165 if ($pkgdata{$pkg}{conffiles}) {
1166 open CONFLIST, ">$buildroot/$pkg/DEBIAN/conffiles";
1167 foreach my $conffile (@{$pkgdata{$pkg}{conflist}}) {
1168 $conffile = expandmacros($conffile, 'g');
1169 my @tmp = glob "$buildroot/$pkg/$conffile";
1170 foreach (@tmp) {
1171 s|$buildroot/$pkg/||g; # nrgl. gotta be a better way to do this...
1172 s/\s+/\n/g; # Not gonna support spaces in filenames. Ewww.
1173 print CONFLIST "$_\n";
1174 }
1175 }
1176 close CONFLIST;
1177 }
1178
1179 # found the point of scripts on subpackages.
1180 if ($pkgdata{$pkg}{'pre'}) {
1181 $pkgdata{$pkg}{'pre'} = expandmacros($pkgdata{$pkg}{'pre'},'gp');
1182 open PREINST, ">$buildroot/$pkg/DEBIAN/preinst";
1183 print PREINST "#!/bin/sh\nset -e\n\n";
1184 print PREINST $pkgdata{$pkg}{'pre'};
1185 close PREINST;
1186 `chmod 0755 $buildroot/$pkg/DEBIAN/preinst`;
1187 }
1188 if ($pkgdata{$pkg}{'post'}) {
1189 $pkgdata{$pkg}{'post'} = expandmacros($pkgdata{$pkg}{'post'},'gp');
1190 open PREINST, ">$buildroot/$pkg/DEBIAN/postinst";
1191 print PREINST "#!/bin/sh\nset -e\n\n";
1192 print PREINST $pkgdata{$pkg}{'post'};
1193 close PREINST;
1194 `chmod 0755 $buildroot/$pkg/DEBIAN/postinst`;
1195 }
1196 if ($pkgdata{$pkg}{'preun'}) {
1197 $pkgdata{$pkg}{'pre'} = expandmacros($pkgdata{$pkg}{'preun'},'gp');
1198 open PREINST, ">$buildroot/$pkg/DEBIAN/prerm";
1199 print PREINST "#!/bin/sh\nset -e\n\n";
1200 print PREINST $pkgdata{$pkg}{'preun'};
1201 close PREINST;
1202 `chmod 0755 $buildroot/$pkg/DEBIAN/prerm`;
1203 }
1204 if ($pkgdata{$pkg}{'postun'}) {
1205 $pkgdata{$pkg}{'postun'} = expandmacros($pkgdata{$pkg}{'postun'},'gp');
1206 open PREINST, ">$buildroot/$pkg/DEBIAN/postrm";
1207 print PREINST "#!/bin/sh\nset -e\n\n";
1208 print PREINST $pkgdata{$pkg}{'postun'};
1209 close PREINST;
1210 `chmod 0755 $buildroot/$pkg/DEBIAN/postrm`;
1211 }
1212
1213 # execute
1214 print "Calling package creation script $debscriptfile for $pkgdata{$pkg}{name}...\n";
1215 system("/bin/sh -e $debscriptfile") == 0
1216 or die "Can't exec: $!\n";
1217
1218 $finalmessages .= "Wrote binary package ".
1219 "$pkgdata{$pkg}{name}_".
1220 (defined($pkgdata{main}{epoch}) ? "$pkgdata{main}{epoch}:" : '').
1221 "$pkgdata{$pkg}{version}-$pkgdata{main}{release}_$pkgdata{$pkg}{arch}.deb".
1222 " in $topdir/DEBS/$pkgdata{$pkg}{arch}\n";
1223 # and clean up
1224 unlink $debscriptfile;
1225
1226 } # subpackage loop
1227
1228} # end binpackage()
1229
1230
1231## srcpackage()
1232# Builds a .src.deb source package. Note that Debian's idea of
1233# a "source package" is seriously flawed IMO, because you can't
1234# easily copy it as-is.
1235# Not quite identical to RPM, but Good Enough (TM).
1236sub srcpackage {
1237 # In case we were called with -bs.
1238 $pkgdata{main}{name} =~ tr/_/-/;
1239 my $pkgsrcname = "$pkgdata{main}{name}-".
1240 (defined($pkgdata{main}{epoch}) ? "$pkgdata{main}{epoch}:" : '').
1241 "$pkgdata{main}{version}-$pkgdata{main}{release}.sdeb";
1242
1243 my $paxcmd;
1244
1245 # We'll definitely need this later, and *may* need it sooner.
1246 (my $barespec = $specfile) =~ s|.+/([^/]+)$|$1|;
1247
1248 # Copy the specfile to the build tree, but only if it's not there already.
1249##buglet: need to deal with silly case where silly user has put the spec
1250# file in a subdir of %{_topdir}/SPECS. Ewww. Silly user!
1251 if (abs_path($specfile) !~ /^$topdir\/SPECS/) {
1252 $paxcmd .= "cp $specfile %{_topdir}/SPECS/; \n"
1253 }
1254
1255 # use pax -w [file] [file] ... >outfile.sdeb
1256 $paxcmd = "cd $topdir; pax -w ";
1257
1258# tweak source entry into usable form. Need it locally somewhere along the line.
1259 (my $pkgsrc = $pkgdata{main}{source}) =~ s|.+/([^/]+)$|$1|;
1260 $paxcmd .= "SOURCES/$pkgsrc ";
1261
1262 # create file list: Source[nn], Patch[nn]
1263 foreach my $specbit (keys %{$pkgdata{main}} ) {
1264 next if $specbit eq 'source';
1265 $paxcmd .= "SOURCES/$pkgdata{main}{$specbit} " if $specbit =~ /^patch/;
1266##buglet: need to deal with case where patches are listed as URLs?
1267# or other extended pathnames? Silly !@$%^&!%%!%!! user!
1268 }
1269
1270 foreach my $source (keys %{$pkgdata{sources}}) {
1271 $paxcmd .= "SOURCES/$pkgdata{sources}{$source} ";
1272 }
1273
1274 # add the spec file, source package destination, and cd back where we came from.
1275 $paxcmd .= "SPECS/$barespec > $topdir/SDEBS/$pkgsrcname; cd -";
1276
1277 # In case of %-macros...
1278 $paxcmd = expandmacros($paxcmd,'gp');
1279
1280 system "$paxcmd";
1281 $finalmessages .= "Wrote source package $pkgsrcname in $topdir/SDEBS.\n";
1282} # end srcpackage()
1283
1284
1285## clean()
1286# Writes and executes the %clean script (mostly) built while reading the spec file.
1287sub clean {
1288 # Replace some things here just to make sure.
1289 $cleanscript = expandmacros($cleanscript,'gp');
1290
1291 # create script filename
1292 my $cleanscriptfile = "$tmpdir/deb-tmp.clean.".int(rand(99998)+1);
1293 sysopen(CLEANSCRIPT, $cleanscriptfile, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW)
1294 or die $!;
1295 print CLEANSCRIPT $scriptletbase;
1296 print CLEANSCRIPT $cleanscript;
1297 close CLEANSCRIPT;
1298
1299 # execute
1300 print "Calling \%clean script $cleanscriptfile...\n";
1301 system("/bin/sh -e $cleanscriptfile") == 0
1302 or die "Can't exec: $!\n";
1303
1304 # and clean up
1305 unlink $cleanscriptfile;
1306} # end clean()
1307
1308
1309## checkbuildreq()
1310# Checks the build requirements (if any)
1311# Spits out a rude warning and returns a true-false error if any
1312# requirements are not met.
1313sub checkbuildreq {
1314 return 1 if $buildreq eq ''; # No use doing extra work.
1315
1316 if ( ! -e "/usr/bin/dpkg-query" ) {
1317 print "**WARNING** dpkg-query not found. Can't check build-deps.\n".
1318 " Required for sucessful build:\n".$buildreq."\n".
1319 " Continuing anyway.\n";
1320 return 1;
1321 }
1322
1323 my $reqflag = 1; # unset iff a buildreq is missing
1324
1325 $buildreq =~ s/^, //; # Strip the leading comma and space
1326 my @reqlist = split /,\s+/, $buildreq;
1327
1328 foreach my $req (@reqlist) {
1329 my ($pkg,$rel,$ver);
1330
1331 # We have two classes of requirements - versioned and unversioned.
1332 if ($req =~ /[><=]/) {
1333 # Pick up the details of versioned buildreqs
1334 ($pkg,$rel,$ver) = ($req =~ /([a-z0-9._-]+)\s+([><=]+)\s+([a-z0-9._-]+)/);
1335 } else {
1336 # And the unversioned ones.
1337 $pkg = $req;
1338 $rel = '>=';
1339 $ver = 0;
1340 }
1341
1342 my @pkglist = qx { dpkg-query --showformat '\${status}\t\${version}\n' -W $pkg };
1343# need to check if no lines returned - means a bad buildreq
1344 my ($reqstat,undef,undef,$reqver) = split /\s+/, $pkglist[0];
1345 if ($reqstat !~ /install/) {
1346 print " * Missing build-dependency $pkg!\n";
1347 $reqflag = 0;
1348 } else {
1349# gotta be a better way to do this... :/
1350 if ($rel eq '>=' && !($reqver ge $ver)) {
1351 print " * Buildreq $pkg is installed, but wrong version ($reqver): Need $ver\n";
1352 $reqflag = 0;
1353 }
1354 if ($rel eq '>' && !($reqver gt $ver)) {
1355 print " * Buildreq $pkg is installed, but wrong version ($reqver): Need $ver\n";
1356 $reqflag = 0;
1357 }
1358 if ($rel eq '<=' && !($reqver le $ver)) {
1359 print " * Buildreq $pkg is installed, but wrong version ($reqver): Need $ver\n";
1360 $reqflag = 0;
1361 }
1362 if ($rel eq '<' && !($reqver lt $ver)) {
1363 print " * Buildreq $pkg is installed, but wrong version ($reqver): Need $ver\n";
1364 $reqflag = 0;
1365 }
1366 if ($rel eq '=' && !($reqver eq $ver)) {
1367 print " * Buildreq $pkg is installed, but wrong version ($reqver): Need $ver\n";
1368 $reqflag = 0;
1369 }
1370 } # end not installed/installed check
1371 } # end req loop
1372
1373 return $reqflag;
1374} # end checkbuildreq()
1375
1376
1377## getreqs()
1378# Find out which libraries/packages are required for any
1379# executables and libs in a given file tree.
1380# (Debian doesn't have soname-level deps; just package-level)
1381# Returns an empty string if the tree contains no binaries.
1382# Doesn't work well on shell scripts. but those *should* be
1383# fine anyway. (Yeah, right...)
1384sub getreqs() {
1385 my $pkgtree = $_[0];
1386
1387 print "Checking library requirements...\n";
1388 my @binlist = qx { find $pkgtree -type f -perm 755 };
1389
1390 if (scalar(@binlist) == 0) {
1391 return '';
1392 }
1393
1394 my @reqlist;
1395 foreach (@binlist) {
1396 push @reqlist, qx { ldd $_ };
1397 }
1398
1399 # Get the list of libs provided by this package. Still doesn't
1400 # handle the case where the lib gets stuffed into a subpackage. :/
1401 my @intprovlist = qx { find $pkgtree -type f -name "*.so*" };
1402 my $provlist = '';
1403 foreach (@intprovlist) {
1404 s/$pkgtree//;
1405 $provlist .= "$_";
1406 }
1407
1408 my %reqs;
1409 my $reqlibs = '';
1410
1411 foreach (@reqlist) {
1412 next if /^$pkgtree/;
1413 next if /not a dynamic executable/;
1414 next if m|/lib/ld-linux.so|; # Hack! Hack! PTHBTT! (libc suxx0rz)
1415 next if /linux-gate.so/; # Kernel hackery for teh W1n!!1!1eleventy-one!1 (Don't ask. Feh.)
1416
1417 my ($req) = (/^\s+([a-z0-9._-]+)/); # dig out the actual library (so)name
1418
1419 # Ignore libs provided by this package. Note that we don't match
1420 # on word-boundary at the *end* of the lib we're looking for, as the
1421 # looked-for lib may not have the full soname version. (ie, it may
1422 # "just" point to one of the symlinks that get created somewhere.)
1423 next if $provlist =~ /\b$req/;
1424
1425 $reqlibs .= " $req";
1426 }
1427
1428 if ($reqlibs ne '') {
1429 foreach (qx { dpkg -S $reqlibs }) {
1430 my ($libpkg,undef) = split /:\s+/;
1431 $reqs{$libpkg} = 1;
1432 }
1433 }
1434
1435 my $deplist = '';
1436 foreach (keys %reqs) {
1437 $deplist .= ", $_";
1438 }
1439
1440# For now, we're done. We're not going to meddle with versions yet.
1441# Among other things, it's messier than handling "simple" yes/no "do
1442# we have this lib?" deps. >:(
1443
1444 return $deplist;
1445} # end getreqs()
1446
1447
1448## install_sdeb()
1449# Extracts .sdeb contents to %_topdir as appropriate
1450sub install_sdeb {
1451 $srcpkg = abs_path($srcpkg);
1452
1453 my $paxcmd = "cd $topdir; pax -r <$srcpkg; cd -";
1454
1455 # In case of %-macros...
1456 $paxcmd = expandmacros($paxcmd,'gp');
1457
1458 system "$paxcmd";
1459 print "Extracted source package $srcpkg to $topdir.\n";
1460} # end install_sdeb()
1461
1462
1463## expandmacros()
1464# Expands all %{blah} macros in the passed string
1465# Split up a bit with some sections so we don't spend time trying to
1466# expand macros that are only used in a few specific places.
1467sub expandmacros {
1468 my $macrostring = shift;
1469 my $section = shift;
1470
1471 # To allow the FHS-ish %configure and %makeinstall to work The Right Way.
1472 # (Without clobbering the global $buildroot.)
1473 my $prefix = '';
1474
1475 if ($section =~ /c/) {
1476 # %configure macro
1477# Don't know what it's for, don't have a useful default replacement
1478# --program-prefix=%{_program_prefix} \
1479 $macrostring =~ s'%configure'./configure --host=$DEB_HOST_GNU_TYPE \
1480 --build=$DEB_BUILD_GNU_TYPE \
1481 --prefix=%{_prefix} \
1482 --exec-prefix=%{_exec_prefix} \
1483 --bindir=%{_bindir} \
1484 --sbindir=%{_sbindir} \
1485 --sysconfdir=%{_sysconfdir} \
1486 --datadir=%{_datadir} \
1487 --includedir=%{_includedir} \
1488 --libdir=%{_libdir} \
1489 --libexecdir=%{_libexecdir} \
1490 --localstatedir=%{_localstatedir} \
1491 --sharedstatedir=%{_sharedstatedir} \
1492 --mandir=%{_mandir} \
1493 --infodir=%{_infodir} ';
1494 } # done %configure
1495
1496 if ($section =~ /m/) {
1497 $macrostring =~ s'%{__make}'make ';
1498 } # done make
1499
1500 if ($section =~ /i/) {
1501 # This is where we need to mangle $prefix.
1502 $macrostring =~ s'%makeinstall'make %{fhs} install';
1503 $prefix = $buildroot;
1504 } # done %install and/or %makeinstall
1505
1506 # Build data
1507 # Note that these are processed in reverse order to get the substitution order right
1508 if ($section =~ /b/) {
1509# $macrostring =~ s'%{fhs}'host=$DEB_HOST_GNU_TYPE \
1510# build=$DEB_BUILD_GNU_TYPE \
1511 $macrostring =~ s'%{fhs}'prefix=%{_prefix} \
1512 exec-prefix=%{_exec_prefix} \
1513 bindir=%{_bindir} \
1514 sbindir=%{_sbindir} \
1515 sysconfdir=%{_sysconfdir} \
1516 datadir=%{_datadir} \
1517 includedir=%{_includedir} \
1518 libdir=%{_libdir} \
1519 libexecdir=%{_libexecdir} \
1520 localstatedir=%{_localstatedir} \
1521 sharedstatedir=%{_sharedstatedir} \
1522 mandir=%{_mandir} \
1523 infodir=%{_infodir} \
1524';
1525
1526 # Note that the above regex terminates with the extra space
1527 # "Just In Case" of user additions, which will then get neatly
1528 # tagged on the end where they take precedence (supposedly)
1529 # over the "default" ones.
1530
1531 # Now we cascade the macros introduced above. >_<
1532 # Wot ot to go theah:
1533 $macrostring =~ s|%{_mandir}|%{_datadir}/man|g; #/usr/share/man
1534 $macrostring =~ s|%{_infodir}|%{_datadir}/info|g; #/usr/share/info
1535 $macrostring =~ s|%{_oldincludedir}|/usr/include|g; #/usr/include
1536 $macrostring =~ s|%{_includedir}|%{_prefix}/include|g; #/usr/include
1537 $macrostring =~ s|%{_libdir}|%{_exec_prefix}/%{_lib}|g; #/usr/lib
1538 $macrostring =~ s|%{_lib}|lib|g; #?
1539 $macrostring =~ s|%{_localstatedir}|/var|g; #/var
1540 $macrostring =~ s|%{_sharedstatedir}|%{_prefix}/com|g; #/usr/com WTF?
1541 $macrostring =~ s|%{_sysconfdir}|/etc|g; #/etc
1542 $macrostring =~ s|%{_datadir}|%{_prefix}/share|g; #/usr/share
1543 $macrostring =~ s|%{_libexecdir}|%{_exec_prefix}/libexec|g; #/usr/libexec
1544 $macrostring =~ s|%{_sbindir}|%{_exec_prefix}/sbin|g; #/usr/sbin
1545 $macrostring =~ s|%{_bindir}|%{_exec_prefix}/bin|g; #/usr/bin
1546 $macrostring =~ s|%{_exec_prefix}|%{_prefix}|g; #/usr
1547 $macrostring =~ s|%{_prefix}|/usr|g; #/usr
1548 } # done with config section
1549
1550 # Package data
1551 if ($section =~ /p/) {
1552 $macrostring =~ s/\%\{buildroot\}/$buildroot/gi;
1553 foreach my $source (keys %{$pkgdata{sources}}) {
1554 $macrostring =~ s/\%\{source$source\}/$topdir\/SOURCES\/$pkgdata{sources}{$source}/gi;
1555 }
1556 $macrostring =~ s/\%\{name\}/$pkgdata{main}{name}/gi;
1557 $macrostring =~ s/\%\{version\}/$pkgdata{main}{version}/gi;
1558 $macrostring =~ s/\%\{release\}/$pkgdata{main}{release}/gi;
1559 }
1560
1561 # Globals, and not-so-globals
1562 if ($section =~ /g/) {
1563
1564 $macrostring =~ s|%{_builddir}|%{_topdir}/BUILD|g;
1565 $macrostring =~ s|%{_topdir}|$topdir|g;
1566 $macrostring =~ s|%{_tmppath}|$tmpdir|g;
1567 $macrostring =~ s'%{_docdir}'%{_datadir}/doc'g;
1568
1569 # Standard FHS locations. More or less.
1570 $macrostring =~ s'%{_bindir}'/usr/bin'g;
1571 $macrostring =~ s'%{_sbindir}'/usr/sbin'g;
1572 $macrostring =~ s'%{_mandir}'%{_datadir}/man'g;
1573 $macrostring =~ s'%{_includedir}'/usr/include'g;
1574 $macrostring =~ s'%{_libdir}'/usr/lib'g;
1575 $macrostring =~ s'%{_sysconfdir}'/etc'g;
1576 $macrostring =~ s'%{_localstatedir}'/var'g;
1577
1578 # FHS-ish locations that aren't quite actually FHS-specified.
1579 $macrostring =~ s'%{_datadir}'/usr/share'g;
1580
1581 # special %define's. Handle the general case where we eval anything.
1582 # Even more general: %(...) is a spec-parse-time shell code wrapper.
1583 # Prime example:
1584 #%define perl_vendorlib %(eval "`perl -V:installvendorlib`"; echo $installvendorlib)
1585 if ($macrostring =~ /\%\((.+)\)/) {
1586 my $shellstr = $1;
1587 # Oy vey this gets silly for the perl bits. Executing a shell to
1588 # call Perl to get the vendorlib/sitelib/whatever "core" globals.
1589 # This can do more, but... eww.
1590 $shellstr = qx { /bin/sh -c '$shellstr' }; # Yay! ' characters apparently get properly exscapededed.
1591 $macrostring =~ s/\%\(.+\)/$shellstr/;
1592 }
1593
1594 # support for **some** %if constructs. Note that this breaks somewhat if
1595 # there's no value specified... but so does rpm.
1596my $tmpcount = 0;
1597 while ($macrostring =~ /\%\{(!\?|\?!|\?)([a-z0-9_.-]+)(?:\:([a-z0-9_.-]+))?\}/g) { #Whew....
1598 my $qex = $1;
1599 my $macro = $2;
1600 my $value = $3;
1601
1602 my $neg = '1' if $qex =~ /\!/;
1603 if ($specglobals{$macro}) {
1604 $value = '' if $neg;
1605 } else {
1606 $value = '' if !$neg;
1607 }
1608 $macrostring =~ s/\%\{!?\?\!?[a-z0-9_.-]+(?:\:[a-z0-9_.-]+)?\}/$value/;
1609
1610# not certain about this, but I don't want to run away. It *can* happen if planned carefully. :/
1611$tmpcount++;
1612die "excessive recursive macro replacement; dying.\n" if $tmpcount > 6;
1613
1614 } # while()
1615
1616 # Misc expansions
1617 $macrostring =~ s|%{_arch}|$hostarch|g;
1618 $macrostring =~ s|%{optflags}|$optflags{$hostarch}|g;
1619 $macrostring =~ s|%{_vendor}|$specglobals{'_vendor'}|g;
1620
1621# should probably stick a "no runaway" flag in here... Just In Case...
1622 # %define's
1623 while (my ($key) = ($macrostring =~ /%{([a-z0-9]+)}/i) ) {
1624# hrm. This needs thinking.
1625#die "A horrible death! \%{$key}, '$macrostring'\n" if !$specglobals{$key};
1626 $macrostring =~ s|%{$key}|$specglobals{$key}|g;
1627 # wanna limit this to "... if $specglobals{$key}", but need more magic
1628 }
1629
1630 # system programs. RPM uses a global config file for these; we'll just
1631 # ASS-U-ME and make life a little simpler.
1632 if ($macrostring =~ /\%\{\_\_([a-z0-9_-]+)\}/) {
1633 $macrostring =~ s|%{__([a-z0-9_-]+)}|$1|g;
1634 }
1635
1636 # Perl @INC/...lib locations, and other related bits.
1637 $macrostring =~ s|%{perl_archlib}|$Config{installarchlib}|g;
1638 $macrostring =~ s|%{perl_sitelib}|$Config{installsitelib}|g;
1639 $macrostring =~ s|%{perl_sitearch}|$Config{installsitearch}|g;
1640 $macrostring =~ s|%{perl_vendorlib}|$Config{installvendorlib}|g;
1641 $macrostring =~ s|%{perl_vendorarch}|$Config{installvendorarch}|g;
1642
1643 } # done with globals section
1644
1645 return $macrostring;
1646} # end expandmacros()
1647
1648
1649
1650__END__
1651
1652
1653
1654=head1 NAME
1655
1656debbuild - Build Debian-compatible packages from RPM spec files
1657
1658=head1 SYNOPSIS
1659
1660 debbuild {-ba|-bb|-bp|-bc|-bi|-bl|-bs} [build-options] file.spec
1661
1662 debbuild {-ta|-tb|-tp|-tc|-ti|-tl|-ts} [build-options] file.tar.{gz|bz2}
1663
1664 debbuild --rebuild file.{src.rpm|sdeb}
1665
1666 debbuild --showpkgs
1667
1668=head1 DESCRIPTION
1669
1670This script attempts to build Debian-friendly semi-native packages from RPM spec files,
1671RPM-friendly tarballs, and RPM source packages (.src.rpm files). It accepts I<most> of the
1672options rpmbuild does, and should be able to interpret most spec files usefully. Perl
1673modules should be handled via CPAN+dh-make-perl instead; Debian's conventions for such
1674things do not lend themselves to automated conversion.
1675
1676As far as possible, the command-line options are identical to those from rpmbuild, although
1677several rpmbuild options are not supported:
1678
1679 --recompile
1680 --showrc
1681 --buildroot
1682 --clean
1683 --nobuild
1684 --rmsource
1685 --rmspec
1686 --sign
1687 --target
1688
1689Some of these could probably be trivially added. Feel free to send me a patch. ;)
1690
1691Complex spec files will most likely not work well, if at all. Rewrite them from scratch -
1692you'll have to make heavy modifications anyway.
1693
1694If you see something you don't like, mail me. Send a patch if you feel inspired. I don't
1695promise I'll do anything other than say "Yup, that's broken" or "Got your message".
1696
1697=head1 ASSUMPTIONS
1698
1699As with rpmbuild, debbuild makes some assumptions about your system.
1700
1701=over 4
1702
1703=item *
1704
1705Either you have rights to do as you please under /usr/src/debian, or you have created a file
1706~/.debmacros containing a suitable %_topdir definition.
1707
1708Both rpmbuild and debbuild require the directories %_topdir/{BUILD,SOURCES,SPECS}. However,
1709where rpmbuild requires the %_topdir/{RPMS,SRPMS} directories, debbuild
1710requires %_topdir/{DEBS,SDEBS} instead. Create them in advance;
1711some subdirectories are created automatically as needed, but most are not.
1712
1713=item *
1714
1715/var/tmp must allow script execution - rpmbuild and debbuild both rely on creating and
1716executing shell scripts for much of their functionality. By default, debbuild also creates
1717install trees under /var/tmp - however this is (almost) entirely under the control of the
1718package's .spec file.
1719
1720=item *
1721
1722If you wish to --rebuild a .src.rpm, your %_topdir for both debbuild and rpmbuild must either
1723match, or be suitably symlinked one direction or another so that both programs are effectively
1724working in the same tree. (Or you could just manually wrestle files around your system.)
1725
1726You could symlink ~/.rpmmacros to ~/.debmacros (or vice versa) and save yourself some hassle
1727if you need to rebuild .src.rpm packages on a regular basis. Currently debbuild only uses the
1728%_topdir macro definition, although there are many more things that rpmbuild can use from
1729~/.rpmmacros.
1730
1731=back
1732
1733=head1 ERRATA
1734
1735debbuild deliberately does a few things differently from rpm.
1736
1737=head2 BuildArch or BuildArchitecture
1738
1739rpm takes the last BuildArch entry it finds in the .spec file, whatever it is, and runs with
1740that for all packages. Debian's repository system is fairly heavily designed around the
1741assumption that a single source package may generate small binary (executable) packages
1742for each arch, and large binary arch-all packages containing shared data.
1743
1744debbuild allows this by using the architecture specified by (in order of preference):
1745
1746=over 4
1747
1748=item * Host architecture
1749
1750=item * BuildArch specified in .spec file preamble
1751
1752=item * "Last specified" BuildArch for packages with several subpackages
1753
1754=item * BuildArch specified in the %package section for that subpackage
1755
1756=back
1757
1758=head2 Finding out what packages should be built (--showpkgs)
1759
1760rpmbuild does not include any convenient method I know of to list the packages a spec file
1761will produce. Since I needed this ability for another tool, I added it.
1762
1763It requires the .spec file for the package, and produces a list of full package filenames
1764(without path data) that would be generated by one of --rebuild, -ta, -tb, -ba, or -bb.
1765This includes the .sdeb source package.
1766
1767=head1 AUTHOR
1768
1769debbuild was written by Kris Deugau <kdeugau@deepnet.cx>. A version that approximates
1770current is available at http://www.deepnet.cx/debbuild/.
1771
1772=head1 BUGS
1773
1774Funky Things Happen if you forget a command-line option or two. I've been too lazy to bother
1775fixing this.
1776
1777Many macro expansions are unsupported or incompletely supported.
1778
1779The generated scriptlets don't quite match those from rpmbuild exactly. There are extra
1780environment variables and preprocessing that I haven't needed (yet).
1781
1782Dcumentation, such as it is, will likely remain perpetually out of date.
1783
1784%_topdir and the five "working" directories under %_topdir could arguably be created by
1785debbuild. However, rpmbuild doesn't create these directories either.
1786
1787=head1 SEE ALSO
1788
1789rpm(8), rpmbuild(8), and pretty much any document describing how to write a .spec file.
1790
1791=cut
Note: See TracBrowser for help on using the repository browser.