source: trunk/debbuild@ 132

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

/trunk

Fiddle manpages into the correct format from whatever the upstream
install does.

RPM does info pages and several other bits; while this should be
simple to hack into supporting info pages I'm not so sure about
the other bits.

  • Property svn:executable set to *
  • Property svn:keywords set to Date Rev Author
File size: 60.2 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-09-28 18:39:47 +0000 (Fri, 28 Sep 2007) $
9# SVN revision $Rev: 132 $
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
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# gotta be a better way to do this... :/
1382 if ($rel eq '>=' && !($reqver ge $ver)) {
1383 print " * Buildreq $pkg is installed, but wrong version ($reqver): Need $ver\n";
1384 $reqflag = 0;
1385 }
1386 if ($rel eq '>' && !($reqver gt $ver)) {
1387 print " * Buildreq $pkg is installed, but wrong version ($reqver): Need $ver\n";
1388 $reqflag = 0;
1389 }
1390 if ($rel eq '<=' && !($reqver le $ver)) {
1391 print " * Buildreq $pkg is installed, but wrong version ($reqver): Need $ver\n";
1392 $reqflag = 0;
1393 }
1394 if ($rel eq '<' && !($reqver lt $ver)) {
1395 print " * Buildreq $pkg is installed, but wrong version ($reqver): Need $ver\n";
1396 $reqflag = 0;
1397 }
1398 if ($rel eq '=' && !($reqver eq $ver)) {
1399 print " * Buildreq $pkg is installed, but wrong version ($reqver): Need $ver\n";
1400 $reqflag = 0;
1401 }
1402 } # end not installed/installed check
1403 } # end req loop
1404
1405 return $reqflag;
1406} # end checkbuildreq()
1407
1408
1409## getreqs()
1410# Find out which libraries/packages are required for any
1411# executables and libs in a given file tree.
1412# (Debian doesn't have soname-level deps; just package-level)
1413# Returns an empty string if the tree contains no binaries.
1414# Doesn't work well on shell scripts. but those *should* be
1415# fine anyway. (Yeah, right...)
1416sub getreqs() {
1417 my $pkgtree = $_[0];
1418
1419 print "Checking library requirements...\n";
1420 my @binlist = qx { find $pkgtree -type f -perm 755 };
1421
1422 if (scalar(@binlist) == 0) {
1423 return '';
1424 }
1425
1426 my @reqlist;
1427 foreach (@binlist) {
1428 push @reqlist, qx { ldd $_ };
1429 }
1430
1431 # Get the list of libs provided by this package. Still doesn't
1432 # handle the case where the lib gets stuffed into a subpackage. :/
1433 my @intprovlist = qx { find $pkgtree -type f -name "*.so*" };
1434 my $provlist = '';
1435 foreach (@intprovlist) {
1436 s/$pkgtree//;
1437 $provlist .= "$_";
1438 }
1439
1440 my %reqs;
1441 my $reqlibs = '';
1442
1443 foreach (@reqlist) {
1444 next if /^$pkgtree/;
1445 next if /not a dynamic executable/;
1446 next if m|/lib/ld-linux.so|; # Hack! Hack! PTHBTT! (libc suxx0rz)
1447 next if /linux-gate.so/; # Kernel hackery for teh W1n!!1!1eleventy-one!1 (Don't ask. Feh.)
1448
1449 my ($req) = (/^\s+([a-z0-9._-]+)/); # dig out the actual library (so)name
1450
1451 # Ignore libs provided by this package. Note that we don't match
1452 # on word-boundary at the *end* of the lib we're looking for, as the
1453 # looked-for lib may not have the full soname version. (ie, it may
1454 # "just" point to one of the symlinks that get created somewhere.)
1455 next if $provlist =~ /\b$req/;
1456
1457 $reqlibs .= " $req";
1458 }
1459
1460 if ($reqlibs ne '') {
1461 foreach (qx { dpkg -S $reqlibs }) {
1462 my ($libpkg,undef) = split /:\s+/;
1463 $reqs{$libpkg} = 1;
1464 }
1465 }
1466
1467 my $deplist = '';
1468 foreach (keys %reqs) {
1469 $deplist .= ", $_";
1470 }
1471
1472# For now, we're done. We're not going to meddle with versions yet.
1473# Among other things, it's messier than handling "simple" yes/no "do
1474# we have this lib?" deps. >:(
1475
1476 return $deplist;
1477} # end getreqs()
1478
1479
1480## install_sdeb()
1481# Extracts .sdeb contents to %_topdir as appropriate
1482sub install_sdeb {
1483 $srcpkg = abs_path($srcpkg);
1484
1485 my $paxcmd = "cd $topdir; pax -r <$srcpkg; cd -";
1486
1487 # In case of %-macros...
1488 $paxcmd = expandmacros($paxcmd,'gp');
1489
1490 system "$paxcmd";
1491 print "Extracted source package $srcpkg to $topdir.\n";
1492} # end install_sdeb()
1493
1494
1495## expandmacros()
1496# Expands all %{blah} macros in the passed string
1497# Split up a bit with some sections so we don't spend time trying to
1498# expand macros that are only used in a few specific places.
1499sub expandmacros {
1500 my $macrostring = shift;
1501 my $section = shift;
1502
1503 # To allow the FHS-ish %configure and %makeinstall to work The Right Way.
1504 # (Without clobbering the global $buildroot.)
1505 my $prefix = '';
1506
1507 if ($section =~ /c/) {
1508 # %configure macro
1509# Don't know what it's for, don't have a useful default replacement
1510# --program-prefix=%{_program_prefix} \
1511 $macrostring =~ s'%configure'./configure --host=$DEB_HOST_GNU_TYPE \
1512 --build=$DEB_BUILD_GNU_TYPE \
1513 --prefix=%{_prefix} \
1514 --exec-prefix=%{_exec_prefix} \
1515 --bindir=%{_bindir} \
1516 --sbindir=%{_sbindir} \
1517 --sysconfdir=%{_sysconfdir} \
1518 --datadir=%{_datadir} \
1519 --includedir=%{_includedir} \
1520 --libdir=%{_libdir} \
1521 --libexecdir=%{_libexecdir} \
1522 --localstatedir=%{_localstatedir} \
1523 --sharedstatedir=%{_sharedstatedir} \
1524 --mandir=%{_mandir} \
1525 --infodir=%{_infodir} ';
1526 } # done %configure
1527
1528 if ($section =~ /m/) {
1529 $macrostring =~ s'%{__make}'make ';
1530 } # done make
1531
1532 if ($section =~ /i/) {
1533 # This is where we need to mangle $prefix.
1534 $macrostring =~ s'%makeinstall'make %{fhs} install';
1535 $prefix = $buildroot;
1536 } # done %install and/or %makeinstall
1537
1538 # Build data
1539 # Note that these are processed in reverse order to get the substitution order right
1540 if ($section =~ /b/) {
1541# $macrostring =~ s'%{fhs}'host=$DEB_HOST_GNU_TYPE \
1542# build=$DEB_BUILD_GNU_TYPE \
1543 $macrostring =~ s'%{fhs}'prefix=%{_prefix} \
1544 exec-prefix=%{_exec_prefix} \
1545 bindir=%{_bindir} \
1546 sbindir=%{_sbindir} \
1547 sysconfdir=%{_sysconfdir} \
1548 datadir=%{_datadir} \
1549 includedir=%{_includedir} \
1550 libdir=%{_libdir} \
1551 libexecdir=%{_libexecdir} \
1552 localstatedir=%{_localstatedir} \
1553 sharedstatedir=%{_sharedstatedir} \
1554 mandir=%{_mandir} \
1555 infodir=%{_infodir} \
1556';
1557
1558 # Note that the above regex terminates with the extra space
1559 # "Just In Case" of user additions, which will then get neatly
1560 # tagged on the end where they take precedence (supposedly)
1561 # over the "default" ones.
1562
1563 # Now we cascade the macros introduced above. >_<
1564 # Wot ot to go theah:
1565 $macrostring =~ s|%{_mandir}|%{_datadir}/man|g; #/usr/share/man
1566 $macrostring =~ s|%{_infodir}|%{_datadir}/info|g; #/usr/share/info
1567 $macrostring =~ s|%{_oldincludedir}|/usr/include|g; #/usr/include
1568 $macrostring =~ s|%{_includedir}|%{_prefix}/include|g; #/usr/include
1569 $macrostring =~ s|%{_libdir}|%{_exec_prefix}/%{_lib}|g; #/usr/lib
1570 $macrostring =~ s|%{_lib}|lib|g; #?
1571 $macrostring =~ s|%{_localstatedir}|/var|g; #/var
1572 $macrostring =~ s|%{_sharedstatedir}|%{_prefix}/com|g; #/usr/com WTF?
1573 $macrostring =~ s|%{_sysconfdir}|/etc|g; #/etc
1574 $macrostring =~ s|%{_datadir}|%{_prefix}/share|g; #/usr/share
1575 $macrostring =~ s|%{_libexecdir}|%{_exec_prefix}/libexec|g; #/usr/libexec
1576 $macrostring =~ s|%{_sbindir}|%{_exec_prefix}/sbin|g; #/usr/sbin
1577 $macrostring =~ s|%{_bindir}|%{_exec_prefix}/bin|g; #/usr/bin
1578 $macrostring =~ s|%{_exec_prefix}|%{_prefix}|g; #/usr
1579 $macrostring =~ s|%{_prefix}|/usr|g; #/usr
1580 } # done with config section
1581
1582 # Package data
1583 if ($section =~ /p/) {
1584 $macrostring =~ s/\%\{buildroot\}/$buildroot/gi;
1585 foreach my $source (keys %{$pkgdata{sources}}) {
1586 $macrostring =~ s/\%\{source$source\}/$topdir\/SOURCES\/$pkgdata{sources}{$source}/gi;
1587 }
1588 $macrostring =~ s/\%\{name\}/$pkgdata{main}{name}/gi;
1589 $macrostring =~ s/\%\{version\}/$pkgdata{main}{version}/gi;
1590 $macrostring =~ s/\%\{release\}/$pkgdata{main}{release}/gi;
1591 }
1592
1593 # Globals, and not-so-globals
1594 if ($section =~ /g/) {
1595
1596 $macrostring =~ s|%{_builddir}|%{_topdir}/BUILD|g;
1597 $macrostring =~ s|%{_topdir}|$topdir|g;
1598 $macrostring =~ s|%{_tmppath}|$tmpdir|g;
1599 $macrostring =~ s'%{_docdir}'%{_datadir}/doc'g;
1600
1601 # Standard FHS locations. More or less.
1602 $macrostring =~ s'%{_bindir}'/usr/bin'g;
1603 $macrostring =~ s'%{_sbindir}'/usr/sbin'g;
1604 $macrostring =~ s'%{_mandir}'%{_datadir}/man'g;
1605 $macrostring =~ s'%{_includedir}'/usr/include'g;
1606 $macrostring =~ s'%{_libdir}'/usr/lib'g;
1607 $macrostring =~ s'%{_sysconfdir}'/etc'g;
1608 $macrostring =~ s'%{_localstatedir}'/var'g;
1609
1610 # FHS-ish locations that aren't quite actually FHS-specified.
1611 $macrostring =~ s'%{_datadir}'/usr/share'g;
1612
1613 # special %define's. Handle the general case where we eval anything.
1614 # Even more general: %(...) is a spec-parse-time shell code wrapper.
1615 # Prime example:
1616 #%define perl_vendorlib %(eval "`perl -V:installvendorlib`"; echo $installvendorlib)
1617 if ($macrostring =~ /\%\((.+)\)/) {
1618 my $shellstr = $1;
1619 # Oy vey this gets silly for the perl bits. Executing a shell to
1620 # call Perl to get the vendorlib/sitelib/whatever "core" globals.
1621 # This can do more, but... eww.
1622 $shellstr = qx { /bin/sh -c '$shellstr' }; # Yay! ' characters apparently get properly exscapededed.
1623 $macrostring =~ s/\%\(.+\)/$shellstr/;
1624 }
1625
1626 # support for **some** %if constructs. Note that this breaks somewhat if
1627 # there's no value specified... but so does rpm.
1628my $tmpcount = 0;
1629 while ($macrostring =~ /\%\{(!\?|\?!|\?)([a-z0-9_.-]+)(?:\:([a-z0-9_.-]+))?\}/g) { #Whew....
1630 my $qex = $1;
1631 my $macro = $2;
1632 my $value = $3;
1633
1634 my $neg = '1' if $qex =~ /\!/;
1635 if ($specglobals{$macro}) {
1636 $value = '' if $neg;
1637 } else {
1638 $value = '' if !$neg;
1639 }
1640 $macrostring =~ s/\%\{!?\?\!?[a-z0-9_.-]+(?:\:[a-z0-9_.-]+)?\}/$value/;
1641
1642# not certain about this, but I don't want to run away. It *can* happen if planned carefully. :/
1643$tmpcount++;
1644die "excessive recursive macro replacement; dying.\n" if $tmpcount > 6;
1645
1646 } # while()
1647
1648 # Misc expansions
1649 $macrostring =~ s|%{_arch}|$hostarch|g;
1650 $macrostring =~ s|%{optflags}|$optflags{$hostarch}|g;
1651 $macrostring =~ s|%{_vendor}|$specglobals{'_vendor'}|g;
1652
1653# should probably stick a "no runaway" flag in here... Just In Case...
1654 # %define's
1655 while (my ($key) = ($macrostring =~ /%{([a-z0-9]+)}/i) ) {
1656# hrm. This needs thinking.
1657#die "A horrible death! \%{$key}, '$macrostring'\n" if !$specglobals{$key};
1658 $macrostring =~ s|%{$key}|$specglobals{$key}|g;
1659 # wanna limit this to "... if $specglobals{$key}", but need more magic
1660 }
1661
1662 # system programs. RPM uses a global config file for these; we'll just
1663 # ASS-U-ME and make life a little simpler.
1664 if ($macrostring =~ /\%\{\_\_([a-z0-9_-]+)\}/) {
1665 $macrostring =~ s|%{__([a-z0-9_-]+)}|$1|g;
1666 }
1667
1668 # Perl @INC/...lib locations, and other related bits.
1669 $macrostring =~ s|%{perl_archlib}|$Config{installarchlib}|g;
1670 $macrostring =~ s|%{perl_sitelib}|$Config{installsitelib}|g;
1671 $macrostring =~ s|%{perl_sitearch}|$Config{installsitearch}|g;
1672 $macrostring =~ s|%{perl_vendorlib}|$Config{installvendorlib}|g;
1673 $macrostring =~ s|%{perl_vendorarch}|$Config{installvendorarch}|g;
1674
1675 } # done with globals section
1676
1677 return $macrostring;
1678} # end expandmacros()
1679
1680
1681
1682__END__
1683
1684
1685
1686=head1 NAME
1687
1688debbuild - Build Debian-compatible packages from RPM spec files
1689
1690=head1 SYNOPSIS
1691
1692 debbuild {-ba|-bb|-bp|-bc|-bi|-bl|-bs} [build-options] file.spec
1693
1694 debbuild {-ta|-tb|-tp|-tc|-ti|-tl|-ts} [build-options] file.tar.{gz|bz2}
1695
1696 debbuild --rebuild file.{src.rpm|sdeb}
1697
1698 debbuild --showpkgs
1699
1700=head1 DESCRIPTION
1701
1702This script attempts to build Debian-friendly semi-native packages from RPM spec files,
1703RPM-friendly tarballs, and RPM source packages (.src.rpm files). It accepts I<most> of the
1704options rpmbuild does, and should be able to interpret most spec files usefully. Perl
1705modules should be handled via CPAN+dh-make-perl instead; Debian's conventions for such
1706things do not lend themselves to automated conversion.
1707
1708As far as possible, the command-line options are identical to those from rpmbuild, although
1709several rpmbuild options are not supported:
1710
1711 --recompile
1712 --showrc
1713 --buildroot
1714 --clean
1715 --nobuild
1716 --rmsource
1717 --rmspec
1718 --sign
1719 --target
1720
1721Some of these could probably be trivially added. Feel free to send me a patch. ;)
1722
1723Complex spec files will most likely not work well, if at all. Rewrite them from scratch -
1724you'll have to make heavy modifications anyway.
1725
1726If you see something you don't like, mail me. Send a patch if you feel inspired. I don't
1727promise I'll do anything other than say "Yup, that's broken" or "Got your message".
1728
1729=head1 ASSUMPTIONS
1730
1731As with rpmbuild, debbuild makes some assumptions about your system.
1732
1733=over 4
1734
1735=item *
1736
1737Either you have rights to do as you please under /usr/src/debian, or you have created a file
1738~/.debmacros containing a suitable %_topdir definition.
1739
1740Both rpmbuild and debbuild require the directories %_topdir/{BUILD,SOURCES,SPECS}. However,
1741where rpmbuild requires the %_topdir/{RPMS,SRPMS} directories, debbuild
1742requires %_topdir/{DEBS,SDEBS} instead. Create them in advance;
1743some subdirectories are created automatically as needed, but most are not.
1744
1745=item *
1746
1747/var/tmp must allow script execution - rpmbuild and debbuild both rely on creating and
1748executing shell scripts for much of their functionality. By default, debbuild also creates
1749install trees under /var/tmp - however this is (almost) entirely under the control of the
1750package's .spec file.
1751
1752=item *
1753
1754If you wish to --rebuild a .src.rpm, your %_topdir for both debbuild and rpmbuild must either
1755match, or be suitably symlinked one direction or another so that both programs are effectively
1756working in the same tree. (Or you could just manually wrestle files around your system.)
1757
1758You could symlink ~/.rpmmacros to ~/.debmacros (or vice versa) and save yourself some hassle
1759if you need to rebuild .src.rpm packages on a regular basis. Currently debbuild only uses the
1760%_topdir macro definition, although there are many more things that rpmbuild can use from
1761~/.rpmmacros.
1762
1763=back
1764
1765=head1 ERRATA
1766
1767debbuild deliberately does a few things differently from rpm.
1768
1769=head2 BuildArch or BuildArchitecture
1770
1771rpm takes the last BuildArch entry it finds in the .spec file, whatever it is, and runs with
1772that for all packages. Debian's repository system is fairly heavily designed around the
1773assumption that a single source package may generate small binary (executable) packages
1774for each arch, and large binary arch-all packages containing shared data.
1775
1776debbuild allows this by using the architecture specified by (in order of preference):
1777
1778=over 4
1779
1780=item * Host architecture
1781
1782=item * BuildArch specified in .spec file preamble
1783
1784=item * "Last specified" BuildArch for packages with several subpackages
1785
1786=item * BuildArch specified in the %package section for that subpackage
1787
1788=back
1789
1790=head2 Finding out what packages should be built (--showpkgs)
1791
1792rpmbuild does not include any convenient method I know of to list the packages a spec file
1793will produce. Since I needed this ability for another tool, I added it.
1794
1795It requires the .spec file for the package, and produces a list of full package filenames
1796(without path data) that would be generated by one of --rebuild, -ta, -tb, -ba, or -bb.
1797This includes the .sdeb source package.
1798
1799=head1 AUTHOR
1800
1801debbuild was written by Kris Deugau <kdeugau@deepnet.cx>. A version that approximates
1802current is available at http://www.deepnet.cx/debbuild/.
1803
1804=head1 BUGS
1805
1806Funky Things Happen if you forget a command-line option or two. I've been too lazy to bother
1807fixing this.
1808
1809Many macro expansions are unsupported or incompletely supported.
1810
1811The generated scriptlets don't quite match those from rpmbuild exactly. There are extra
1812environment variables and preprocessing that I haven't needed (yet).
1813
1814Dcumentation, such as it is, will likely remain perpetually out of date.
1815
1816%_topdir and the five "working" directories under %_topdir could arguably be created by
1817debbuild. However, rpmbuild doesn't create these directories either.
1818
1819=head1 SEE ALSO
1820
1821rpm(8), rpmbuild(8), and pretty much any document describing how to write a .spec file.
1822
1823=cut
Note: See TracBrowser for help on using the repository browser.