source: trunk/debbuild@ 83

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

/trunk

Tweak/bugfix handling of %attr entries in %files to handle case of
no-permissions-with-real-owner.

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