source: trunk/debbuild@ 134

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

/trunk

Convert build-dep version check block to use dpkg --compare-versions.
Drop attempts to allow or'ed deps, because rpm doesn't support them.

  • Property svn:executable set to *
  • Property svn:keywords set to Date Rev Author
File size: 59.6 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-10-31 20:11:53 +0000 (Wed, 31 Oct 2007) $
9# SVN revision $Rev: 134 $
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|makeinstall|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
1008 # final bit: compress manpages if present
1009 # done here cuz I don't grok shell well
1010 # should probably error-check all kinds of things. <g>
1011 if (opendir MANROOT, "$buildroot/usr/share/man") {
1012 my @mansects = readdir MANROOT;
1013 closedir MANROOT;
1014 foreach my $mandir (@mansects) {
1015 next if $mandir !~ /^man/;
1016 opendir MANPAGES, "$buildroot/usr/share/man/$mandir";
1017 my @pagelist = readdir MANPAGES;
1018 closedir MANPAGES; # Slightly safer to to this; no accidental recursion. O_o
1019 foreach my $manpage (@pagelist) {
1020 $manpage = "$buildroot/usr/share/man/$mandir/$manpage";
1021 if ( -f $manpage) {
1022 if ($manpage =~ /^(.+)\.(?:Z|gz|bz2)\n?$/) {
1023 my $newpage = $1;
1024 `gunzip $manpage` if $manpage =~ /\.(?:Z|gz)$/;
1025 `bunzip2 $manpage` if $manpage =~ /\.bz2$/;
1026 $manpage = $newpage;
1027 }
1028 `gzip -9 -n $manpage`;
1029 } elsif ( -l $manpage) {
1030 my $linkdest = readlink $manpage;
1031 $linkdest =~ s/\.(?:Z|gz|bz2)//;
1032 unlink $manpage;
1033 $manpage =~ s/\.(?:Z|gz|bz2)//;
1034 symlink "$linkdest.gz", "$manpage.gz" or print "DEBUG: wibble: symlinking manpage failed: $!\n";
1035 }
1036 }
1037 }
1038 } # if opendir MANROOT
1039} # end install()
1040
1041
1042## binpackage()
1043# Creates the binary .deb package from the installed tree in $buildroot.
1044# Writes and executes a shell script to do so.
1045# Creates miscellaneous files required by dpkg-deb to actually build the package file.
1046# Should handle simple subpackages
1047sub binpackage {
1048
1049 foreach my $pkg (@pkglist) {
1050
1051 $pkgdata{$pkg}{arch} = $hostarch if !$pkgdata{$pkg}{arch}; # Just In Case.
1052
1053 # Make sure we have somewhere to write the .deb file
1054 if (!-e "$topdir/DEBS/$pkgdata{$pkg}{arch}") {
1055 mkdir "$topdir/DEBS/$pkgdata{$pkg}{arch}";
1056 }
1057
1058 # Skip building a package if it doesn't actually have any files. NB: This
1059 # differs slightly from rpm's behaviour where a package *will* be built -
1060 # even without any files - if %files is specified anywhere. I can think
1061 # of odd corner cases where that *may* be desireable.
1062 next if (!$filelist{$pkg} or $filelist{$pkg} =~ /^\s*$/);
1063
1064 # Gotta do this first, otherwise we don't have a place to move files from %files
1065 mkdir "$buildroot/$pkg";
1066
1067 # Eliminate any lingering % macros
1068 $filelist{$pkg} = expandmacros $filelist{$pkg}, 'g';
1069
1070 my @pkgfilelist = split ' ', $filelist{$pkg};
1071 foreach my $pkgfile (@pkgfilelist) {
1072 $pkgfile = expandmacros($pkgfile, 'gp');
1073
1074 # Feh. Manpages don't **NEED** to be gzipped, but rpmbuild does, and so shall we.
1075 if ($pkgfile =~ m|/usr/share/man/man|) {
1076 # need to check to see if manpage is gzipped
1077 if (-e "$buildroot$pkgfile") {
1078 if ($pkgfile !~ m|\.gz$|) {
1079 qx { gzip $buildroot$pkgfile };
1080 $pkgfile .= ".gz";
1081 }
1082 } else {
1083 if ($pkgfile !~ m|\.gz$|) {
1084 $pkgfile .= ".gz";
1085 } else {
1086 $pkgfile =~ s/\.gz$//;
1087 qx { gzip $buildroot$pkgfile };
1088 $pkgfile .= ".gz";
1089 }
1090 }
1091 }
1092
1093 my ($fpath,$fname) = ($pkgfile =~ m|(.+?/?)?([^/]+/?)$|); # We don't need $fname now, but we might.
1094 qx { mkdir -p $buildroot/$pkg$fpath }
1095 if $fpath && $fpath ne '';
1096 qx { mv $buildroot$pkgfile $buildroot/$pkg$fpath };
1097 }
1098
1099 # Get the "Depends" (Requires) a la RPM. Ish. We strip the leading
1100 # comma and space here (if needed) in case there were "Requires" specified
1101 # in the spec file - those would precede these.
1102 $pkgdata{$pkg}{requires} .= getreqs("$buildroot/$pkg") if ! $NoAutoReq;
1103
1104 # magic needed to properly version dependencies...
1105 # only provided deps will really be included
1106 $pkgdata{$pkg}{requires} =~ s/^, //; # Still have to do this here.
1107 $pkgdata{$pkg}{requires} =~ s/\s+//g;
1108 my @deps = split /,/, $pkgdata{$pkg}{requires};
1109 my $tmp = '';
1110 foreach my $dep (@deps) {
1111 # Hack up the perl(Class::SubClass) deps into something dpkg can understand.
1112 # May or may not be versioned.
1113 # We do this first so the version rewriter can do its magic next.
1114 if (my ($mod,$ver) = ($dep =~ /^perl\(([A-Za-z0-9\:\-]+)\)([><=]+.+)?/) ) {
1115 $mod =~ s/^perl\(//;
1116 $mod =~ s/\)$//;
1117 $mod =~ s/::/-/g;
1118 $mod =~ tr/A-Z/a-z/;
1119 $mod = "lib$mod-perl";
1120 $mod .= $ver if $ver;
1121 $dep = $mod;
1122 }
1123 if (my ($name,$rel,$value) = ($dep =~ /^([a-zA-Z0-9._-]+)([><=]+)([a-zA-Z0-9._-]+)$/)) {
1124 $tmp .= ", $name ($rel $value)";
1125 } else {
1126 $tmp .= ", $dep";
1127 }
1128 }
1129 ($pkgdata{$pkg}{requires} = $tmp) =~ s/^, //;
1130
1131 # Do this here since we're doing {depends}...
1132 if (defined($pkgdata{$pkg}{provides})) {
1133 $pkgdata{$pkg}{provides} =~ s/^, //;
1134 $pkgdata{$pkg}{provides} = expandmacros($pkgdata{$pkg}{provides},'gp');
1135 }
1136 if (defined($pkgdata{$pkg}{conflicts})) {
1137 $pkgdata{$pkg}{conflicts} =~ s/^, //;
1138 $pkgdata{$pkg}{conflicts} = expandmacros($pkgdata{$pkg}{conflicts},'gp');
1139 }
1140
1141# These are Debian-specific!
1142 if (defined($pkgdata{$pkg}{recommends})) {
1143 $pkgdata{$pkg}{recommends} =~ s/^, //;
1144 $pkgdata{$pkg}{recommends} = expandmacros($pkgdata{$pkg}{recommends},'gp');
1145 }
1146 if (defined($pkgdata{$pkg}{suggests})) {
1147 $pkgdata{$pkg}{suggests} =~ s/^, //;
1148 $pkgdata{$pkg}{suggests} = expandmacros($pkgdata{$pkg}{suggests},'gp');
1149 }
1150 if (defined($pkgdata{$pkg}{replaces})) {
1151 $pkgdata{$pkg}{replaces} =~ s/^, //;
1152 $pkgdata{$pkg}{replaces} = expandmacros($pkgdata{$pkg}{replaces},'gp');
1153 }
1154
1155 # Gotta do this next, otherwise the control file has nowhere to go. >:(
1156 mkdir "$buildroot/$pkg/DEBIAN";
1157
1158 # Hack the filename for the package into a Debian-tool-compatible format. GRRRRRR!!!!!
1159 # Have I mentioned I hate Debian Policy?
1160 $pkgdata{$pkg}{name} =~ tr/_/-/;
1161
1162 # create script filename
1163 my $debscriptfile = "$tmpdir/deb-tmp.pkg.".int(rand(99998)+1);
1164 sysopen(DEBSCRIPT, $debscriptfile, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW)
1165 or die $!;
1166 print DEBSCRIPT $scriptletbase;
1167 print DEBSCRIPT "fakeroot dpkg-deb -b $buildroot/$pkg $topdir/DEBS/$pkgdata{$pkg}{arch}/".
1168 "$pkgdata{$pkg}{name}_".
1169 (defined($pkgdata{main}{epoch}) ? "$pkgdata{main}{epoch}:" : '').
1170 "$pkgdata{$pkg}{version}-$pkgdata{main}{release}_$pkgdata{$pkg}{arch}.deb\n";
1171 # %$&$%@#@@#%@@@ Debian and their horrible ugly package names. >:(
1172 close DEBSCRIPT;
1173
1174 my $control = "Package: $pkgdata{$pkg}{name}\n".
1175 "Version: ".
1176 (defined($pkgdata{main}{epoch}) ? "$pkgdata{main}{epoch}:" : '').
1177 "$pkgdata{$pkg}{version}-$pkgdata{main}{release}\n".
1178 "Section: $pkgdata{$pkg}{group}\n".
1179 "Priority: optional\n".
1180 "Architecture: $pkgdata{$pkg}{arch}\n".
1181 "Maintainer: $pkgdata{main}{packager}\n".
1182 ( $pkgdata{$pkg}{requires} ne '' ? "Depends: $pkgdata{$pkg}{requires}\n" : '' ).
1183 ( defined($pkgdata{$pkg}{provides}) ? "Provides: $pkgdata{$pkg}{provides}\n" : '' ).
1184 ( defined($pkgdata{$pkg}{conflicts}) ? "Conflicts: $pkgdata{$pkg}{conflicts}\n" : '' ).
1185 ( defined($pkgdata{$pkg}{recommends}) ? "Recommends: $pkgdata{$pkg}{recommends}\n" : '' ).
1186 ( defined($pkgdata{$pkg}{suggests}) ? "Suggests: $pkgdata{$pkg}{suggests}\n" : '' ).
1187 ( defined($pkgdata{$pkg}{replaces}) ? "Replaces: $pkgdata{$pkg}{replaces}\n" : '' ).
1188 "Description: $pkgdata{$pkg}{summary}\n";
1189 $control .= "$pkgdata{$pkg}{desc}\n";
1190
1191 open CONTROL, ">$buildroot/$pkg/DEBIAN/control";
1192 print CONTROL $control;
1193 close CONTROL;
1194
1195 # Iff there are conffiles (as specified in the %files list(s), add'em
1196 # in so dpkg-deb can tag them.
1197 if ($pkgdata{$pkg}{conffiles}) {
1198 open CONFLIST, ">$buildroot/$pkg/DEBIAN/conffiles";
1199 foreach my $conffile (@{$pkgdata{$pkg}{conflist}}) {
1200 $conffile = expandmacros($conffile, 'g');
1201 my @tmp = glob "$buildroot/$pkg/$conffile";
1202 foreach (@tmp) {
1203 s|$buildroot/$pkg/||g; # nrgl. gotta be a better way to do this...
1204 s/\s+/\n/g; # Not gonna support spaces in filenames. Ewww.
1205 print CONFLIST "$_\n";
1206 }
1207 }
1208 close CONFLIST;
1209 }
1210
1211 # found the point of scripts on subpackages.
1212 if ($pkgdata{$pkg}{'pre'}) {
1213 $pkgdata{$pkg}{'pre'} = expandmacros($pkgdata{$pkg}{'pre'},'gp');
1214 open PREINST, ">$buildroot/$pkg/DEBIAN/preinst";
1215 print PREINST "#!/bin/sh\nset -e\n\n";
1216 print PREINST $pkgdata{$pkg}{'pre'};
1217 close PREINST;
1218 chmod 0755, "$buildroot/$pkg/DEBIAN/preinst";
1219 }
1220 if ($pkgdata{$pkg}{'post'}) {
1221 $pkgdata{$pkg}{'post'} = expandmacros($pkgdata{$pkg}{'post'},'gp');
1222 open POSTINST, ">$buildroot/$pkg/DEBIAN/postinst";
1223 print POSTINST "#!/bin/sh\nset -e\n\n";
1224 print POSTINST $pkgdata{$pkg}{'post'};
1225 close POSTINST;
1226 chmod 0755, "$buildroot/$pkg/DEBIAN/postinst";
1227 }
1228 if ($pkgdata{$pkg}{'preun'}) {
1229 $pkgdata{$pkg}{'pre'} = expandmacros($pkgdata{$pkg}{'preun'},'gp');
1230 open PREUNINST, ">$buildroot/$pkg/DEBIAN/prerm";
1231 print PREUNINST "#!/bin/sh\nset -e\n\n";
1232 print PREUNINST $pkgdata{$pkg}{'preun'};
1233 close PREUNINST;
1234 chmod 0755, "$buildroot/$pkg/DEBIAN/prerm";
1235 }
1236 if ($pkgdata{$pkg}{'postun'}) {
1237 $pkgdata{$pkg}{'postun'} = expandmacros($pkgdata{$pkg}{'postun'},'gp');
1238 open POSTUNINST, ">$buildroot/$pkg/DEBIAN/postrm";
1239 print POSTUNINST "#!/bin/sh\nset -e\n\n";
1240 print POSTUNINST $pkgdata{$pkg}{'postun'};
1241 close POSTUNINST;
1242 chmod 0755, "$buildroot/$pkg/DEBIAN/postrm";
1243 }
1244
1245 # execute
1246 print "Calling package creation script $debscriptfile for $pkgdata{$pkg}{name}...\n";
1247 system("/bin/sh -e $debscriptfile") == 0
1248 or die "Can't exec: $!\n";
1249
1250 $finalmessages .= "Wrote binary package ".
1251 "$pkgdata{$pkg}{name}_".
1252 (defined($pkgdata{main}{epoch}) ? "$pkgdata{main}{epoch}:" : '').
1253 "$pkgdata{$pkg}{version}-$pkgdata{main}{release}_$pkgdata{$pkg}{arch}.deb".
1254 " in $topdir/DEBS/$pkgdata{$pkg}{arch}\n";
1255 # and clean up
1256 unlink $debscriptfile;
1257
1258 } # subpackage loop
1259
1260} # end binpackage()
1261
1262
1263## srcpackage()
1264# Builds a .src.deb source package. Note that Debian's idea of
1265# a "source package" is seriously flawed IMO, because you can't
1266# easily copy it as-is.
1267# Not quite identical to RPM, but Good Enough (TM).
1268sub srcpackage {
1269 # In case we were called with -bs.
1270 $pkgdata{main}{name} =~ tr/_/-/;
1271 my $pkgsrcname = "$pkgdata{main}{name}-".
1272 (defined($pkgdata{main}{epoch}) ? "$pkgdata{main}{epoch}:" : '').
1273 "$pkgdata{main}{version}-$pkgdata{main}{release}.sdeb";
1274
1275 my $paxcmd;
1276
1277 # We'll definitely need this later, and *may* need it sooner.
1278 (my $barespec = $specfile) =~ s|.+/([^/]+)$|$1|;
1279
1280 # Copy the specfile to the build tree, but only if it's not there already.
1281##buglet: need to deal with silly case where silly user has put the spec
1282# file in a subdir of %{_topdir}/SPECS. Ewww. Silly user!
1283 if (abs_path($specfile) !~ /^$topdir\/SPECS/) {
1284 $paxcmd .= "cp $specfile %{_topdir}/SPECS/; \n"
1285 }
1286
1287 # use pax -w [file] [file] ... >outfile.sdeb
1288 $paxcmd = "cd $topdir; pax -w ";
1289
1290# tweak source entry into usable form. Need it locally somewhere along the line.
1291 (my $pkgsrc = $pkgdata{main}{source}) =~ s|.+/([^/]+)$|$1|;
1292 $paxcmd .= "SOURCES/$pkgsrc ";
1293
1294 # create file list: Source[nn], Patch[nn]
1295 foreach my $specbit (keys %{$pkgdata{main}} ) {
1296 next if $specbit eq 'source';
1297 $paxcmd .= "SOURCES/$pkgdata{main}{$specbit} " if $specbit =~ /^patch/;
1298##buglet: need to deal with case where patches are listed as URLs?
1299# or other extended pathnames? Silly !@$%^&!%%!%!! user!
1300 }
1301
1302 foreach my $source (keys %{$pkgdata{sources}}) {
1303 $paxcmd .= "SOURCES/$pkgdata{sources}{$source} ";
1304 }
1305
1306 # add the spec file, source package destination, and cd back where we came from.
1307 $paxcmd .= "SPECS/$barespec > $topdir/SDEBS/$pkgsrcname; cd -";
1308
1309 # In case of %-macros...
1310 $paxcmd = expandmacros($paxcmd,'gp');
1311
1312 system "$paxcmd";
1313 $finalmessages .= "Wrote source package $pkgsrcname in $topdir/SDEBS.\n";
1314} # end srcpackage()
1315
1316
1317## clean()
1318# Writes and executes the %clean script (mostly) built while reading the spec file.
1319sub clean {
1320 # Replace some things here just to make sure.
1321 $cleanscript = expandmacros($cleanscript,'gp');
1322
1323 # create script filename
1324 my $cleanscriptfile = "$tmpdir/deb-tmp.clean.".int(rand(99998)+1);
1325 sysopen(CLEANSCRIPT, $cleanscriptfile, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW)
1326 or die $!;
1327 print CLEANSCRIPT $scriptletbase;
1328 print CLEANSCRIPT $cleanscript;
1329 close CLEANSCRIPT;
1330
1331 # execute
1332 print "Calling \%clean script $cleanscriptfile...\n";
1333 system("/bin/sh -e $cleanscriptfile") == 0
1334 or die "Can't exec: $!\n";
1335
1336 # and clean up
1337 unlink $cleanscriptfile;
1338} # end clean()
1339
1340
1341## checkbuildreq()
1342# Checks the build requirements (if any)
1343# Spits out a rude warning and returns a true-false error if any
1344# requirements are not met.
1345sub checkbuildreq {
1346 return 1 if $buildreq eq ''; # No use doing extra work.
1347
1348 if ( ! -e "/usr/bin/dpkg-query" ) {
1349 print "**WARNING** dpkg-query not found. Can't check build-deps.\n".
1350 " Required for sucessful build:\n".$buildreq."\n".
1351 " Continuing anyway.\n";
1352 return 1;
1353 }
1354
1355 my $reqflag = 1; # unset iff a buildreq is missing
1356
1357 $buildreq =~ s/^, //; # Strip the leading comma and space
1358 my @reqlist = split /,\s+/, $buildreq;
1359
1360 foreach my $req (@reqlist) {
1361 my ($pkg,$rel,$ver);
1362
1363 # We have two classes of requirements - versioned and unversioned.
1364 if ($req =~ /[><=]/) {
1365 # Pick up the details of versioned buildreqs
1366 ($pkg,$rel,$ver) = ($req =~ /([a-z0-9._-]+)\s+([><=]+)\s+([a-z0-9._-]+)/);
1367 } else {
1368 # And the unversioned ones.
1369 $pkg = $req;
1370 $rel = '>=';
1371 $ver = 0;
1372 }
1373
1374 my @pkglist = qx { dpkg-query --showformat '\${status}\t\${version}\n' -W $pkg };
1375# need to check if no lines returned - means a bad buildreq
1376 my ($reqstat,undef,undef,$reqver) = split /\s+/, $pkglist[0];
1377 if ($reqstat !~ /install/) {
1378 print " * Missing build-dependency $pkg!\n";
1379 $reqflag = 0;
1380 } else {
1381 my ($resp) = qx { dpkg --compare-versions $reqver '$rel' $ver && echo "ok" };
1382 if ($resp !~ /^ok/) {
1383 $reqflag = 0;
1384 print " * Buildreq $pkg is installed, but wrong version ($reqver): Need $ver\n"
1385 }
1386 } # end not installed/installed check
1387 } # end req loop
1388
1389 return $reqflag;
1390} # end checkbuildreq()
1391
1392
1393## getreqs()
1394# Find out which libraries/packages are required for any
1395# executables and libs in a given file tree.
1396# (Debian doesn't have soname-level deps; just package-level)
1397# Returns an empty string if the tree contains no binaries.
1398# Doesn't work well on shell scripts. but those *should* be
1399# fine anyway. (Yeah, right...)
1400sub getreqs() {
1401 my $pkgtree = $_[0];
1402
1403 print "Checking library requirements...\n";
1404 my @binlist = qx { find $pkgtree -type f -perm 755 };
1405
1406 if (scalar(@binlist) == 0) {
1407 return '';
1408 }
1409
1410 my @reqlist;
1411 foreach (@binlist) {
1412 push @reqlist, qx { ldd $_ };
1413 }
1414
1415 # Get the list of libs provided by this package. Still doesn't
1416 # handle the case where the lib gets stuffed into a subpackage. :/
1417 my @intprovlist = qx { find $pkgtree -type f -name "*.so*" };
1418 my $provlist = '';
1419 foreach (@intprovlist) {
1420 s/$pkgtree//;
1421 $provlist .= "$_";
1422 }
1423
1424 my %reqs;
1425 my $reqlibs = '';
1426
1427 foreach (@reqlist) {
1428 next if /^$pkgtree/;
1429 next if /not a dynamic executable/;
1430 next if m|/lib/ld-linux.so|; # Hack! Hack! PTHBTT! (libc suxx0rz)
1431 next if /linux-gate.so/; # Kernel hackery for teh W1n!!1!1eleventy-one!1 (Don't ask. Feh.)
1432
1433 my ($req) = (/^\s+([a-z0-9._-]+)/); # dig out the actual library (so)name
1434
1435 # Ignore libs provided by this package. Note that we don't match
1436 # on word-boundary at the *end* of the lib we're looking for, as the
1437 # looked-for lib may not have the full soname version. (ie, it may
1438 # "just" point to one of the symlinks that get created somewhere.)
1439 next if $provlist =~ /\b$req/;
1440
1441 $reqlibs .= " $req";
1442 }
1443
1444 if ($reqlibs ne '') {
1445 foreach (qx { dpkg -S $reqlibs }) {
1446 my ($libpkg,undef) = split /:\s+/;
1447 $reqs{$libpkg} = 1;
1448 }
1449 }
1450
1451 my $deplist = '';
1452 foreach (keys %reqs) {
1453 $deplist .= ", $_";
1454 }
1455
1456# For now, we're done. We're not going to meddle with versions yet.
1457# Among other things, it's messier than handling "simple" yes/no "do
1458# we have this lib?" deps. >:(
1459
1460 return $deplist;
1461} # end getreqs()
1462
1463
1464## install_sdeb()
1465# Extracts .sdeb contents to %_topdir as appropriate
1466sub install_sdeb {
1467 $srcpkg = abs_path($srcpkg);
1468
1469 my $paxcmd = "cd $topdir; pax -r <$srcpkg; cd -";
1470
1471 # In case of %-macros...
1472 $paxcmd = expandmacros($paxcmd,'gp');
1473
1474 system "$paxcmd";
1475 print "Extracted source package $srcpkg to $topdir.\n";
1476} # end install_sdeb()
1477
1478
1479## expandmacros()
1480# Expands all %{blah} macros in the passed string
1481# Split up a bit with some sections so we don't spend time trying to
1482# expand macros that are only used in a few specific places.
1483sub expandmacros {
1484 my $macrostring = shift;
1485 my $section = shift;
1486
1487 # To allow the FHS-ish %configure and %makeinstall to work The Right Way.
1488 # (Without clobbering the global $buildroot.)
1489 my $prefix = '';
1490
1491 if ($section =~ /c/) {
1492 # %configure macro
1493# Don't know what it's for, don't have a useful default replacement
1494# --program-prefix=%{_program_prefix} \
1495 $macrostring =~ s'%configure'./configure --host=$DEB_HOST_GNU_TYPE \
1496 --build=$DEB_BUILD_GNU_TYPE \
1497 --prefix=%{_prefix} \
1498 --exec-prefix=%{_exec_prefix} \
1499 --bindir=%{_bindir} \
1500 --sbindir=%{_sbindir} \
1501 --sysconfdir=%{_sysconfdir} \
1502 --datadir=%{_datadir} \
1503 --includedir=%{_includedir} \
1504 --libdir=%{_libdir} \
1505 --libexecdir=%{_libexecdir} \
1506 --localstatedir=%{_localstatedir} \
1507 --sharedstatedir=%{_sharedstatedir} \
1508 --mandir=%{_mandir} \
1509 --infodir=%{_infodir} ';
1510 } # done %configure
1511
1512 if ($section =~ /m/) {
1513 $macrostring =~ s'%{__make}'make ';
1514 } # done make
1515
1516 if ($section =~ /i/) {
1517 # This is where we need to mangle $prefix.
1518 $macrostring =~ s'%makeinstall'make %{fhs} install';
1519 $prefix = $buildroot;
1520 } # done %install and/or %makeinstall
1521
1522 # Build data
1523 # Note that these are processed in reverse order to get the substitution order right
1524 if ($section =~ /b/) {
1525# $macrostring =~ s'%{fhs}'host=$DEB_HOST_GNU_TYPE \
1526# build=$DEB_BUILD_GNU_TYPE \
1527 $macrostring =~ s'%{fhs}'prefix=%{_prefix} \
1528 exec-prefix=%{_exec_prefix} \
1529 bindir=%{_bindir} \
1530 sbindir=%{_sbindir} \
1531 sysconfdir=%{_sysconfdir} \
1532 datadir=%{_datadir} \
1533 includedir=%{_includedir} \
1534 libdir=%{_libdir} \
1535 libexecdir=%{_libexecdir} \
1536 localstatedir=%{_localstatedir} \
1537 sharedstatedir=%{_sharedstatedir} \
1538 mandir=%{_mandir} \
1539 infodir=%{_infodir} \
1540';
1541
1542 # Note that the above regex terminates with the extra space
1543 # "Just In Case" of user additions, which will then get neatly
1544 # tagged on the end where they take precedence (supposedly)
1545 # over the "default" ones.
1546
1547 # Now we cascade the macros introduced above. >_<
1548 # Wot ot to go theah:
1549 $macrostring =~ s|%{_mandir}|%{_datadir}/man|g; #/usr/share/man
1550 $macrostring =~ s|%{_infodir}|%{_datadir}/info|g; #/usr/share/info
1551 $macrostring =~ s|%{_oldincludedir}|/usr/include|g; #/usr/include
1552 $macrostring =~ s|%{_includedir}|%{_prefix}/include|g; #/usr/include
1553 $macrostring =~ s|%{_libdir}|%{_exec_prefix}/%{_lib}|g; #/usr/lib
1554 $macrostring =~ s|%{_lib}|lib|g; #?
1555 $macrostring =~ s|%{_localstatedir}|/var|g; #/var
1556 $macrostring =~ s|%{_sharedstatedir}|%{_prefix}/com|g; #/usr/com WTF?
1557 $macrostring =~ s|%{_sysconfdir}|/etc|g; #/etc
1558 $macrostring =~ s|%{_datadir}|%{_prefix}/share|g; #/usr/share
1559 $macrostring =~ s|%{_libexecdir}|%{_exec_prefix}/libexec|g; #/usr/libexec
1560 $macrostring =~ s|%{_sbindir}|%{_exec_prefix}/sbin|g; #/usr/sbin
1561 $macrostring =~ s|%{_bindir}|%{_exec_prefix}/bin|g; #/usr/bin
1562 $macrostring =~ s|%{_exec_prefix}|%{_prefix}|g; #/usr
1563 $macrostring =~ s|%{_prefix}|/usr|g; #/usr
1564 } # done with config section
1565
1566 # Package data
1567 if ($section =~ /p/) {
1568 $macrostring =~ s/\%\{buildroot\}/$buildroot/gi;
1569 foreach my $source (keys %{$pkgdata{sources}}) {
1570 $macrostring =~ s/\%\{source$source\}/$topdir\/SOURCES\/$pkgdata{sources}{$source}/gi;
1571 }
1572 $macrostring =~ s/\%\{name\}/$pkgdata{main}{name}/gi;
1573 $macrostring =~ s/\%\{version\}/$pkgdata{main}{version}/gi;
1574 $macrostring =~ s/\%\{release\}/$pkgdata{main}{release}/gi;
1575 }
1576
1577 # Globals, and not-so-globals
1578 if ($section =~ /g/) {
1579
1580 $macrostring =~ s|%{_builddir}|%{_topdir}/BUILD|g;
1581 $macrostring =~ s|%{_topdir}|$topdir|g;
1582 $macrostring =~ s|%{_tmppath}|$tmpdir|g;
1583 $macrostring =~ s'%{_docdir}'%{_datadir}/doc'g;
1584
1585 # Standard FHS locations. More or less.
1586 $macrostring =~ s'%{_bindir}'/usr/bin'g;
1587 $macrostring =~ s'%{_sbindir}'/usr/sbin'g;
1588 $macrostring =~ s'%{_mandir}'%{_datadir}/man'g;
1589 $macrostring =~ s'%{_includedir}'/usr/include'g;
1590 $macrostring =~ s'%{_libdir}'/usr/lib'g;
1591 $macrostring =~ s'%{_sysconfdir}'/etc'g;
1592 $macrostring =~ s'%{_localstatedir}'/var'g;
1593
1594 # FHS-ish locations that aren't quite actually FHS-specified.
1595 $macrostring =~ s'%{_datadir}'/usr/share'g;
1596
1597 # special %define's. Handle the general case where we eval anything.
1598 # Even more general: %(...) is a spec-parse-time shell code wrapper.
1599 # Prime example:
1600 #%define perl_vendorlib %(eval "`perl -V:installvendorlib`"; echo $installvendorlib)
1601 if ($macrostring =~ /\%\((.+)\)/) {
1602 my $shellstr = $1;
1603 # Oy vey this gets silly for the perl bits. Executing a shell to
1604 # call Perl to get the vendorlib/sitelib/whatever "core" globals.
1605 # This can do more, but... eww.
1606 $shellstr = qx { /bin/sh -c '$shellstr' }; # Yay! ' characters apparently get properly exscapededed.
1607 $macrostring =~ s/\%\(.+\)/$shellstr/;
1608 }
1609
1610 # support for **some** %if constructs. Note that this breaks somewhat if
1611 # there's no value specified... but so does rpm.
1612my $tmpcount = 0;
1613 while ($macrostring =~ /\%\{(!\?|\?!|\?)([a-z0-9_.-]+)(?:\:([a-z0-9_.-]+))?\}/g) { #Whew....
1614 my $qex = $1;
1615 my $macro = $2;
1616 my $value = $3;
1617
1618 my $neg = '1' if $qex =~ /\!/;
1619 if ($specglobals{$macro}) {
1620 $value = '' if $neg;
1621 } else {
1622 $value = '' if !$neg;
1623 }
1624 $macrostring =~ s/\%\{!?\?\!?[a-z0-9_.-]+(?:\:[a-z0-9_.-]+)?\}/$value/;
1625
1626# not certain about this, but I don't want to run away. It *can* happen if planned carefully. :/
1627$tmpcount++;
1628die "excessive recursive macro replacement; dying.\n" if $tmpcount > 6;
1629
1630 } # while()
1631
1632 # Misc expansions
1633 $macrostring =~ s|%{_arch}|$hostarch|g;
1634 $macrostring =~ s|%{optflags}|$optflags{$hostarch}|g;
1635 $macrostring =~ s|%{_vendor}|$specglobals{'_vendor'}|g;
1636
1637# should probably stick a "no runaway" flag in here... Just In Case...
1638 # %define's
1639 while (my ($key) = ($macrostring =~ /%{([a-z0-9]+)}/i) ) {
1640# hrm. This needs thinking.
1641#die "A horrible death! \%{$key}, '$macrostring'\n" if !$specglobals{$key};
1642 $macrostring =~ s|%{$key}|$specglobals{$key}|g;
1643 # wanna limit this to "... if $specglobals{$key}", but need more magic
1644 }
1645
1646 # system programs. RPM uses a global config file for these; we'll just
1647 # ASS-U-ME and make life a little simpler.
1648 if ($macrostring =~ /\%\{\_\_([a-z0-9_-]+)\}/) {
1649 $macrostring =~ s|%{__([a-z0-9_-]+)}|$1|g;
1650 }
1651
1652 # Perl @INC/...lib locations, and other related bits.
1653 $macrostring =~ s|%{perl_archlib}|$Config{installarchlib}|g;
1654 $macrostring =~ s|%{perl_sitelib}|$Config{installsitelib}|g;
1655 $macrostring =~ s|%{perl_sitearch}|$Config{installsitearch}|g;
1656 $macrostring =~ s|%{perl_vendorlib}|$Config{installvendorlib}|g;
1657 $macrostring =~ s|%{perl_vendorarch}|$Config{installvendorarch}|g;
1658
1659 } # done with globals section
1660
1661 return $macrostring;
1662} # end expandmacros()
1663
1664
1665
1666__END__
1667
1668
1669
1670=head1 NAME
1671
1672debbuild - Build Debian-compatible packages from RPM spec files
1673
1674=head1 SYNOPSIS
1675
1676 debbuild {-ba|-bb|-bp|-bc|-bi|-bl|-bs} [build-options] file.spec
1677
1678 debbuild {-ta|-tb|-tp|-tc|-ti|-tl|-ts} [build-options] file.tar.{gz|bz2}
1679
1680 debbuild --rebuild file.{src.rpm|sdeb}
1681
1682 debbuild --showpkgs
1683
1684=head1 DESCRIPTION
1685
1686This script attempts to build Debian-friendly semi-native packages from RPM spec files,
1687RPM-friendly tarballs, and RPM source packages (.src.rpm files). It accepts I<most> of the
1688options rpmbuild does, and should be able to interpret most spec files usefully. Perl
1689modules should be handled via CPAN+dh-make-perl instead; Debian's conventions for such
1690things do not lend themselves to automated conversion.
1691
1692As far as possible, the command-line options are identical to those from rpmbuild, although
1693several rpmbuild options are not supported:
1694
1695 --recompile
1696 --showrc
1697 --buildroot
1698 --clean
1699 --nobuild
1700 --rmsource
1701 --rmspec
1702 --sign
1703 --target
1704
1705Some of these could probably be trivially added. Feel free to send me a patch. ;)
1706
1707Complex spec files will most likely not work well, if at all. Rewrite them from scratch -
1708you'll have to make heavy modifications anyway.
1709
1710If you see something you don't like, mail me. Send a patch if you feel inspired. I don't
1711promise I'll do anything other than say "Yup, that's broken" or "Got your message".
1712
1713=head1 ASSUMPTIONS
1714
1715As with rpmbuild, debbuild makes some assumptions about your system.
1716
1717=over 4
1718
1719=item *
1720
1721Either you have rights to do as you please under /usr/src/debian, or you have created a file
1722~/.debmacros containing a suitable %_topdir definition.
1723
1724Both rpmbuild and debbuild require the directories %_topdir/{BUILD,SOURCES,SPECS}. However,
1725where rpmbuild requires the %_topdir/{RPMS,SRPMS} directories, debbuild
1726requires %_topdir/{DEBS,SDEBS} instead. Create them in advance;
1727some subdirectories are created automatically as needed, but most are not.
1728
1729=item *
1730
1731/var/tmp must allow script execution - rpmbuild and debbuild both rely on creating and
1732executing shell scripts for much of their functionality. By default, debbuild also creates
1733install trees under /var/tmp - however this is (almost) entirely under the control of the
1734package's .spec file.
1735
1736=item *
1737
1738If you wish to --rebuild a .src.rpm, your %_topdir for both debbuild and rpmbuild must either
1739match, or be suitably symlinked one direction or another so that both programs are effectively
1740working in the same tree. (Or you could just manually wrestle files around your system.)
1741
1742You could symlink ~/.rpmmacros to ~/.debmacros (or vice versa) and save yourself some hassle
1743if you need to rebuild .src.rpm packages on a regular basis. Currently debbuild only uses the
1744%_topdir macro definition, although there are many more things that rpmbuild can use from
1745~/.rpmmacros.
1746
1747=back
1748
1749=head1 ERRATA
1750
1751debbuild deliberately does a few things differently from rpm.
1752
1753=head2 BuildArch or BuildArchitecture
1754
1755rpm takes the last BuildArch entry it finds in the .spec file, whatever it is, and runs with
1756that for all packages. Debian's repository system is fairly heavily designed around the
1757assumption that a single source package may generate small binary (executable) packages
1758for each arch, and large binary arch-all packages containing shared data.
1759
1760debbuild allows this by using the architecture specified by (in order of preference):
1761
1762=over 4
1763
1764=item * Host architecture
1765
1766=item * BuildArch specified in .spec file preamble
1767
1768=item * "Last specified" BuildArch for packages with several subpackages
1769
1770=item * BuildArch specified in the %package section for that subpackage
1771
1772=back
1773
1774=head2 Finding out what packages should be built (--showpkgs)
1775
1776rpmbuild does not include any convenient method I know of to list the packages a spec file
1777will produce. Since I needed this ability for another tool, I added it.
1778
1779It requires the .spec file for the package, and produces a list of full package filenames
1780(without path data) that would be generated by one of --rebuild, -ta, -tb, -ba, or -bb.
1781This includes the .sdeb source package.
1782
1783=head1 AUTHOR
1784
1785debbuild was written by Kris Deugau <kdeugau@deepnet.cx>. A version that approximates
1786current is available at http://www.deepnet.cx/debbuild/.
1787
1788=head1 BUGS
1789
1790Funky Things Happen if you forget a command-line option or two. I've been too lazy to bother
1791fixing this.
1792
1793Many macro expansions are unsupported or incompletely supported.
1794
1795The generated scriptlets don't quite match those from rpmbuild exactly. There are extra
1796environment variables and preprocessing that I haven't needed (yet).
1797
1798Dcumentation, such as it is, will likely remain perpetually out of date.
1799
1800%_topdir and the five "working" directories under %_topdir could arguably be created by
1801debbuild. However, rpmbuild doesn't create these directories either.
1802
1803=head1 SEE ALSO
1804
1805rpm(8), rpmbuild(8), and pretty much any document describing how to write a .spec file.
1806
1807=cut
Note: See TracBrowser for help on using the repository browser.