source: trunk/debbuild@ 84

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

/trunk

Fix %files glitch with macro expansion by pedanticising several macros
and adding %{_datadir} expansion to the general macros section

  • 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 20:03:21 +0000 (Thu, 22 Mar 2007) $
9# SVN revision $Rev: 84 $
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 } # done %file section
632
633 if (/^\%changelog/) {
634 $pkgdata{main}{changelog} = '';
635 while (<SPECFILE>) {
636 redo LINE if /^\%/;
637 $pkgdata{main}{changelog} .= $_;
638 }
639 }
640
641 } else { # Data from the spec file "header"
642
643 if (/^summary:\s+(.+)/i) {
644 $pkgdata{main}{summary} = $1;
645 } elsif (/^name:\s+(.+)/i) {
646 $pkgdata{main}{name} = expandmacros($1,'g');
647 } elsif (/^version:\s+(.+)/i) {
648 $pkgdata{main}{version} = expandmacros($1,'g');
649 } elsif (/^release:\s+(.+)/i) {
650 $pkgdata{main}{release} = expandmacros($1,'g');
651 } elsif (/^group:\s+(.+)/i) {
652 $pkgdata{main}{group} = $1;
653 } elsif (/^copyright:\s+(.+)/i) {
654 $pkgdata{main}{copyright} = $1;
655 } elsif (/^url:\s+(.+)/i) {
656 $pkgdata{main}{url} = $1;
657 } elsif (/^packager:\s+(.+)/i) {
658 $pkgdata{main}{packager} = $1;
659 } elsif (/^buildroot:\s+(.+)/i) {
660 $buildroot = $1;
661 } elsif (/^source0?:\s+(.+)/i) {
662 $pkgdata{main}{source} = $1;
663 die "Unknown tarball format $1\n" if $1 !~ /\.tar\.(?:gz|bz2)$/;
664 } elsif (/^source([0-9]+):\s+(.+)/i) {
665 $pkgdata{sources}{$1} = $2;
666 } elsif (/^patch([^:]+):\s+(.+)$/i) {
667 my $patchname = "patch$1";
668 $pkgdata{main}{$patchname} = $2;
669 if ($pkgdata{main}{$patchname} =~ /\//) {
670 # URL-style patch. Rare but not unheard-of.
671 my @patchbits = split '/', $pkgdata{main}{$patchname};
672 $pkgdata{main}{$patchname} = $patchbits[$#patchbits];
673 }
674 chomp $pkgdata{main}{$patchname};
675 } elsif (/^buildreq(?:uires)?:\s+(.+)/i) {
676 $buildreq .= ", $1";
677 } elsif (/^requires:\s+(.+)/i) {
678 $pkgdata{main}{requires} .= ", ".expandmacros("$1", 'gp');
679 } elsif (/^provides:\s+(.+)/i) {
680 $pkgdata{main}{provides} .= ", $1";
681 } elsif (/^conflicts:\s+(.+)/i) {
682 $pkgdata{main}{conflicts} .= ", $1";
683 }
684#Name: suwrap
685#Version: 0.04
686#Release: 3
687#Group: Applications/System
688#Copyright: WebHart internal ONLY. :(
689#BuildArchitectures: i386
690#BuildRoot: /tmp/%{name}-%{version}
691#Url: http://virtual.webhart.net
692#Packager: Kris Deugau <kdeugau@deepnet.cx>
693#Source: ftp://virtual.webhart.net/%{name}-%{version}.tar.gz
694
695 }
696 }
697
698 # Parse and replace some more macros. More will be replaced even later.
699
700 # Expand macros as necessary.
701 $scriptletbase = expandmacros($scriptletbase,'gp');
702
703 $buildroot = $cmdbuildroot if $cmdbuildroot;
704 $buildroot = expandmacros($buildroot,'gp');
705
706 close SPECFILE;
707} # end parse_spec()
708
709
710## prep()
711# Writes and executes the %prep script (mostly) built while reading the spec file.
712sub prep {
713 # Replace some things here just to make sure.
714 $prepscript = expandmacros($prepscript,'gp');
715
716#print $prepscript; exit 0;
717
718 # create script filename
719 my $prepscriptfile = "$tmpdir/deb-tmp.prep.".int(rand(99998)+1);
720 sysopen(PREPSCRIPT, $prepscriptfile, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW)
721 or die $!;
722 print PREPSCRIPT $scriptletbase;
723 print PREPSCRIPT $prepscript;
724 close PREPSCRIPT;
725
726 # execute
727 print "Calling \%prep script $prepscriptfile...\n";
728 system("/bin/sh -e $prepscriptfile") == 0
729 or die "Can't exec: $!\n";
730
731 # and clean up
732 unlink $prepscriptfile;
733} # end prep()
734
735
736## build()
737# Writes and executes the %build script (mostly) built while reading the spec file.
738sub build {
739 # Expand the macros
740 $buildscript = expandmacros($buildscript,'cgbp');
741
742 # create script filename
743 my $buildscriptfile = "$tmpdir/deb-tmp.build.".int(rand(99998)+1);
744 sysopen(BUILDSCRIPT, $buildscriptfile, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW)
745 or die $!;
746 print BUILDSCRIPT $scriptletbase;
747 print BUILDSCRIPT $buildscript;
748 close BUILDSCRIPT;
749
750 # execute
751 print "Calling \%build script $buildscriptfile...\n";
752 system("/bin/sh -e $buildscriptfile") == 0
753 or die "Can't exec: $!\n";
754
755 # and clean up
756 unlink $buildscriptfile;
757} # end build()
758
759
760## install()
761# Writes and executes the %install script (mostly) built while reading the spec file.
762sub install {
763 # Expand the macros
764 $installscript = expandmacros($installscript,'igbp');
765
766 # create script filename
767 my $installscriptfile = "$tmpdir/deb-tmp.inst.".int(rand(99998)+1);
768 sysopen(INSTSCRIPT, $installscriptfile, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW)
769 or die $!;
770 print INSTSCRIPT $scriptletbase;
771# print INSTSCRIPT $cleanscript; # Clean up our install target before installing into it.
772 print INSTSCRIPT $installscript;
773 close INSTSCRIPT;
774
775 # execute
776 print "Calling \%install script $installscriptfile...\n";
777 system("/bin/sh -e $installscriptfile") == 0
778 or die "Can't exec: $!\n";
779
780 # and clean up
781 unlink $installscriptfile;
782} # end install()
783
784
785## binpackage()
786# Creates the binary .deb package from the installed tree in $buildroot.
787# Writes and executes a shell script to do so.
788# Creates miscellaneous files required by dpkg-deb to actually build the package file.
789# Should handle simple subpackages
790sub binpackage {
791 # Make sure we have somewhere to write the .deb file
792 if (!-e "$topdir/DEBS/i386") {
793 mkdir "$topdir/DEBS/i386";
794 }
795
796 foreach my $pkg (@pkglist) {
797
798 # Skip building a package if it doesn't actually have any files. NB: This
799 # differs slightly from rpm's behaviour where a package *will* be built -
800 # even without any files - if %files is specified anywhere. I can think
801 # of odd corner cases where that *may* be desireable.
802 next if (!$filelist{$pkg} or $filelist{$pkg} =~ /^\s*$/);
803
804 # Gotta do this first, otherwise we don't have a place to move files from %files
805 mkdir "$buildroot/$pkg";
806
807 # Eliminate any lingering % macros
808 $filelist{$pkg} = expandmacros $filelist{$pkg}, 'g';
809
810 my @pkgfilelist = split ' ', $filelist{$pkg};
811 foreach my $pkgfile (@pkgfilelist) {
812 $pkgfile = expandmacros($pkgfile, 'gp');
813 my ($fpath,$fname) = ($pkgfile =~ m|(.+?/?)?([^/]+)$|); # We don't need $fname now, but we might.
814 qx { mkdir -p $buildroot/$pkg$fpath }
815 if $fpath && $fpath ne '';
816 qx { mv $buildroot$pkgfile $buildroot/$pkg$fpath };
817 }
818
819 # Get the "Depends" (Requires) a la RPM. Ish. We strip the leading
820 # comma and space here (if needed) in case there were "Requires" specified
821 # in the spec file - those would precede these.
822 $pkgdata{$pkg}{requires} .= getreqs("$buildroot/$pkg");
823
824 # magic needed to properly version dependencies...
825 # only provided deps will really be included
826 $pkgdata{$pkg}{requires} =~ s/^, //; # Still have to do this here.
827 $pkgdata{$pkg}{requires} =~ s/\s+//g;
828 my @deps = split /,/, $pkgdata{$pkg}{requires};
829 my $tmp = '';
830 foreach my $dep (@deps) {
831 # Hack up the perl(Class::SubClass) deps into something dpkg can understand.
832 # May or may not be versioned.
833 # We do this first so the version rewriter can do its magic next.
834 if (my ($mod,$ver) = ($dep =~ /^perl\(([A-Za-z0-9\:\-]+)\)([><=]+.+)?/) ) {
835 $mod =~ s/^perl\(//;
836 $mod =~ s/\)$//;
837 $mod =~ s/::/-/g;
838 $mod =~ tr/A-Z/a-z/;
839 $mod = "lib$mod-perl";
840 $mod .= $ver if $ver;
841 $dep = $mod;
842 }
843 if (my ($name,$rel,$value) = ($dep =~ /^([a-zA-Z0-9._-]+)([><=]+)([a-zA-Z0-9._-]+)$/)) {
844 $tmp .= ", $name ($rel $value)";
845 } else {
846 $tmp .= ", $dep";
847 }
848 }
849 ($pkgdata{$pkg}{requires} = $tmp) =~ s/^, //;
850
851 # Do this here since we're doing {depends}...
852 if (defined($pkgdata{$pkg}{provides})) {
853 $pkgdata{$pkg}{provides} =~ s/^, //;
854 $pkgdata{$pkg}{provides} = expandmacros($pkgdata{$pkg}{provides},'gp');
855 }
856 if (defined($pkgdata{$pkg}{conflicts})) {
857 $pkgdata{$pkg}{conflicts} =~ s/^, //;
858 $pkgdata{$pkg}{conflicts} = expandmacros($pkgdata{$pkg}{conflicts},'gp');
859 }
860
861 # Gotta do this next, otherwise the control file has nowhere to go. >:(
862 mkdir "$buildroot/$pkg/DEBIAN";
863
864 # Hack the filename for the package into a Debian-tool-compatible format. GRRRRRR!!!!!
865 # Have I mentioned I hate Debian Policy?
866 $pkgdata{$pkg}{name} =~ tr/_/-/;
867
868 # create script filename
869 my $debscriptfile = "$tmpdir/deb-tmp.pkg.".int(rand(99998)+1);
870 sysopen(DEBSCRIPT, $debscriptfile, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW)
871 or die $!;
872 print DEBSCRIPT $scriptletbase;
873 print DEBSCRIPT "fakeroot dpkg-deb -b $buildroot/$pkg $topdir/DEBS/i386/".
874 "$pkgdata{$pkg}{name}_$pkgdata{$pkg}{version}-$pkgdata{main}{release}_i386.deb\n";
875 # %$&$%@#@@#%@@@ Debian and their horrible ugly package names. >:(
876 close DEBSCRIPT;
877
878 my $control = "Package: $pkgdata{$pkg}{name}\n".
879 "Version: $pkgdata{$pkg}{version}-$pkgdata{main}{release}\n".
880 "Section: $pkgdata{$pkg}{group}\n".
881 "Priority: optional\n".
882 "Architecture: i386\n".
883 "Maintainer: $pkgdata{main}{packager}\n".
884 ( $pkgdata{$pkg}{requires} ne '' ? "Depends: $pkgdata{$pkg}{requires}\n" : '' ).
885 ( defined($pkgdata{$pkg}{provides}) ? "Provides: $pkgdata{$pkg}{provides}\n" : '' ).
886 ( defined($pkgdata{$pkg}{conflicts}) ? "Conflicts: $pkgdata{$pkg}{conflicts}\n" : '' ).
887 "Description: $pkgdata{$pkg}{summary}\n";
888 $control .= "$pkgdata{$pkg}{desc}\n";
889
890 open CONTROL, ">$buildroot/$pkg/DEBIAN/control";
891 print CONTROL $control;
892 close CONTROL;
893
894 # Iff there are conffiles (as specified in the %files list(s), add'em
895 # in so dpkg-deb can tag them.
896 if ($pkgdata{$pkg}{conffiles}) {
897 open CONFLIST, ">$buildroot/$pkg/DEBIAN/conffiles";
898 foreach my $conffile (@{$pkgdata{$pkg}{conflist}}) {
899 print CONFLIST "$conffile\n";
900 }
901 close CONFLIST;
902 }
903
904 # found the point of scripts on subpackages.
905 if ($pkgdata{$pkg}{'pre'}) {
906 $pkgdata{$pkg}{'pre'} = expandmacros($pkgdata{$pkg}{'pre'},'gp');
907 open PREINST, ">$buildroot/$pkg/DEBIAN/preinst";
908 print PREINST "#!/bin/sh\nset -e\n\n";
909 print PREINST $pkgdata{$pkg}{'pre'};
910 close PREINST;
911 `chmod 0755 $buildroot/$pkg/DEBIAN/preinst`;
912 }
913 if ($pkgdata{$pkg}{'post'}) {
914 $pkgdata{$pkg}{'post'} = expandmacros($pkgdata{$pkg}{'post'},'gp');
915 open PREINST, ">$buildroot/$pkg/DEBIAN/postinst";
916 print PREINST "#!/bin/sh\nset -e\n\n";
917 print PREINST $pkgdata{$pkg}{'post'};
918 close PREINST;
919 `chmod 0755 $buildroot/$pkg/DEBIAN/postinst`;
920 }
921 if ($pkgdata{$pkg}{'preun'}) {
922 $pkgdata{$pkg}{'pre'} = expandmacros($pkgdata{$pkg}{'preun'},'gp');
923 open PREINST, ">$buildroot/$pkg/DEBIAN/prerm";
924 print PREINST "#!/bin/sh\nset -e\n\n";
925 print PREINST $pkgdata{$pkg}{'preun'};
926 close PREINST;
927 `chmod 0755 $buildroot/$pkg/DEBIAN/prerm`;
928 }
929 if ($pkgdata{$pkg}{'postun'}) {
930 $pkgdata{$pkg}{'postun'} = expandmacros($pkgdata{$pkg}{'postun'},'gp');
931 open PREINST, ">$buildroot/$pkg/DEBIAN/postrm";
932 print PREINST "#!/bin/sh\nset -e\n\n";
933 print PREINST $pkgdata{$pkg}{'postun'};
934 close PREINST;
935 `chmod 0755 $buildroot/$pkg/DEBIAN/postrm`;
936 }
937
938 # execute
939 print "Calling package creation script $debscriptfile for $pkgdata{$pkg}{name}...\n";
940 system("/bin/sh -e $debscriptfile") == 0
941 or die "Can't exec: $!\n";
942
943 $finalmessages .= "Wrote binary package ".
944 "$pkgdata{$pkg}{name}_$pkgdata{$pkg}{version}-$pkgdata{main}{release}_i386.deb".
945 " in $topdir/DEBS/i386\n";
946 # and clean up
947 unlink $debscriptfile;
948
949 } # subpackage loop
950
951} # end binpackage()
952
953
954## srcpackage()
955# Builds a .src.deb source package. Note that Debian's idea of
956# a "source package" is seriously flawed IMO, because you can't
957# easily copy it as-is.
958# Not quite identical to RPM, but Good Enough (TM).
959sub srcpackage {
960 # In case we were called with -bs.
961 $pkgdata{main}{name} =~ tr/_/-/;
962 my $pkgsrcname = "$pkgdata{main}{name}-$pkgdata{main}{version}-$pkgdata{main}{release}.sdeb";
963
964 my $paxcmd;
965
966 # We'll definitely need this later, and *may* need it sooner.
967 (my $barespec = $specfile) =~ s|.+/([^/]+)$|$1|;
968
969 # Copy the specfile to the build tree, but only if it's not there already.
970##buglet: need to deal with silly case where silly user has put the spec
971# file in a subdir of %{_topdir}/SPECS. Ewww. Silly user!
972 if (abs_path($specfile) !~ /^$topdir\/SPECS/) {
973 $paxcmd .= "cp $specfile %{_topdir}/SPECS/; \n"
974 }
975
976 # use pax -w [file] [file] ... >outfile.sdeb
977 $paxcmd = "cd $topdir; pax -w ";
978
979# tweak source entry into usable form. Need it locally somewhere along the line.
980 (my $pkgsrc = $pkgdata{main}{source}) =~ s|.+/([^/]+)$|$1|;
981 $paxcmd .= "SOURCES/$pkgsrc ";
982
983 # create file list: Source[nn], Patch[nn]
984 foreach my $specbit (keys %{$pkgdata{main}} ) {
985 next if $specbit eq 'source';
986 $paxcmd .= "SOURCES/$pkgdata{main}{$specbit} " if $specbit =~ /^patch/;
987##buglet: need to deal with case where patches are listed as URLs?
988# or other extended pathnames? Silly !@$%^&!%%!%!! user!
989 }
990
991 foreach my $source (keys %{$pkgdata{sources}}) {
992 $paxcmd .= "SOURCES/$pkgdata{sources}{$source} ";
993 }
994
995 # add the spec file, source package destination, and cd back where we came from.
996 $paxcmd .= "SPECS/$barespec > $topdir/SDEBS/$pkgsrcname; cd -";
997
998 # In case of %-macros...
999 $paxcmd = expandmacros($paxcmd,'gp');
1000
1001 system "$paxcmd";
1002 $finalmessages .= "Wrote source package $pkgsrcname in $topdir/SDEBS.\n";
1003}
1004
1005
1006## checkbuildreq()
1007# Checks the build requirements (if any)
1008# Spits out a rude warning and returns a true-false error if any
1009# requirements are not met.
1010sub checkbuildreq {
1011 return 1 if $buildreq eq ''; # No use doing extra work.
1012
1013 if ( ! -e "/usr/bin/dpkg-query" ) {
1014 print "**WARNING** dpkg-query not found. Can't check build-deps.\n".
1015 " Required for sucessful build:\n".$buildreq."\n".
1016 " Continuing anyway.\n";
1017 return 1;
1018 }
1019
1020 my $reqflag = 1; # unset iff a buildreq is missing
1021
1022 $buildreq =~ s/^, //; # Strip the leading comma and space
1023 my @reqlist = split /,\s+/, $buildreq;
1024
1025 foreach my $req (@reqlist) {
1026 my ($pkg,$rel,$ver);
1027
1028 # We have two classes of requirements - versioned and unversioned.
1029 if ($req =~ /[><=]/) {
1030 # Pick up the details of versioned buildreqs
1031 ($pkg,$rel,$ver) = ($req =~ /([a-z0-9._-]+)\s+([><=]+)\s+([a-z0-9._-]+)/);
1032 } else {
1033 # And the unversioned ones.
1034 $pkg = $req;
1035 $rel = '>=';
1036 $ver = 0;
1037 }
1038
1039 my @pkglist = qx { dpkg-query --showformat '\${status}\t\${version}\n' -W $pkg };
1040# need to check if no lines returned - means a bad buildreq
1041 my ($reqstat,undef,undef,$reqver) = split /\s+/, $pkglist[0];
1042 if ($reqstat !~ /install/) {
1043 print " * Missing build-dependency $pkg!\n";
1044 $reqflag = 0;
1045 } else {
1046# gotta be a better way to do this... :/
1047 if ($rel eq '>=' && !($reqver ge $ver)) {
1048 print " * Buildreq $pkg is installed, but wrong version ($reqver): Need $ver\n";
1049 $reqflag = 0;
1050 }
1051 if ($rel eq '>' && !($reqver gt $ver)) {
1052 print " * Buildreq $pkg is installed, but wrong version ($reqver): Need $ver\n";
1053 $reqflag = 0;
1054 }
1055 if ($rel eq '<=' && !($reqver le $ver)) {
1056 print " * Buildreq $pkg is installed, but wrong version ($reqver): Need $ver\n";
1057 $reqflag = 0;
1058 }
1059 if ($rel eq '<' && !($reqver lt $ver)) {
1060 print " * Buildreq $pkg is installed, but wrong version ($reqver): Need $ver\n";
1061 $reqflag = 0;
1062 }
1063 if ($rel eq '=' && !($reqver eq $ver)) {
1064 print " * Buildreq $pkg is installed, but wrong version ($reqver): Need $ver\n";
1065 $reqflag = 0;
1066 }
1067 } # end not installed/installed check
1068 } # end req loop
1069
1070 return $reqflag;
1071} # end checkbuildreq()
1072
1073
1074## getreqs()
1075# Find out which libraries/packages are required for any
1076# executables and libs in a given file tree.
1077# (Debian doesn't have soname-level deps; just package-level)
1078# Returns an empty string if the tree contains no binaries.
1079# Doesn't work well on shell scripts. but those *should* be
1080# fine anyway. (Yeah, right...)
1081sub getreqs() {
1082 my $pkgtree = $_[0];
1083
1084 print "Checking library requirements...\n";
1085 my @binlist = qx { find $pkgtree -type f -perm 755 };
1086
1087 if (scalar(@binlist) == 0) {
1088 return '';
1089 }
1090
1091 my @reqlist;
1092 foreach (@binlist) {
1093 push @reqlist, qx { ldd $_ };
1094 }
1095
1096 # Get the list of libs provided by this package. Still doesn't
1097 # handle the case where the lib gets stuffed into a subpackage. :/
1098 my @intprovlist = qx { find $pkgtree -type f -name "*.so*" };
1099 my $provlist = '';
1100 foreach (@intprovlist) {
1101 s/$pkgtree//;
1102 $provlist .= "$_";
1103 }
1104
1105 my %reqs;
1106 my $reqlibs = '';
1107
1108 foreach (@reqlist) {
1109 next if /^$pkgtree/;
1110 next if /not a dynamic executable/;
1111 next if m|/lib/ld-linux.so|; # Hack! Hack! PTHBTT! (libc suxx0rz)
1112
1113 my ($req) = (/^\s+([a-z0-9._-]+)/); # dig out the actual library (so)name
1114
1115 # Ignore libs provided by this package. Note that we don't match
1116 # on word-boundary at the *end* of the lib we're looking for, as the
1117 # looked-for lib may not have the full soname version. (ie, it may
1118 # "just" point to one of the symlinks that get created somewhere.)
1119 next if $provlist =~ /\b$req/;
1120
1121 $reqlibs .= " $req";
1122 }
1123
1124 if ($reqlibs ne '') {
1125 foreach (qx { dpkg -S $reqlibs }) {
1126 my ($libpkg,undef) = split /:\s+/;
1127 $reqs{$libpkg} = 1;
1128 }
1129 }
1130
1131 my $deplist = '';
1132 foreach (keys %reqs) {
1133 $deplist .= ", $_";
1134 }
1135
1136# For now, we're done. We're not going to meddle with versions yet.
1137# Among other things, it's messier than handling "simple" yes/no "do
1138# we have this lib?" deps. >:(
1139
1140 return $deplist;
1141} # end getreqs()
1142
1143
1144## install_sdeb()
1145# Extracts .sdeb contents to %_topdir as appropriate
1146sub install_sdeb {
1147 my $paxcmd = "cd $topdir; pax -r <$srcpkg; cd -";
1148
1149 # In case of %-macros...
1150 $paxcmd = expandmacros($paxcmd,'gp');
1151
1152 system "$paxcmd";
1153 print "Extracted source package $srcpkg to $topdir.\n";
1154} # end install_sdeb()
1155
1156
1157## expandmacros()
1158# Expands all %{blah} macros in the passed string
1159# Split up a bit with some sections so we don't spend time trying to
1160# expand macros that are only used in a few specific places.
1161sub expandmacros {
1162 my $macrostring = shift;
1163 my $section = shift;
1164
1165 # To allow the FHS-ish %configure and %makeinstall to work The Right Way.
1166 # (Without clobbering the global $buildroot.)
1167 my $prefix = '';
1168
1169 if ($section =~ /c/) {
1170 # %configure macro
1171# Don't know what it's for, don't have a useful default replacement
1172# --program-prefix=%{_program_prefix} \
1173 $macrostring =~ s'%configure'./configure --host=$DEB_HOST_GNU_TYPE \
1174 --build=$DEB_BUILD_GNU_TYPE \
1175 --prefix=%{_prefix} \
1176 --exec-prefix=%{_exec_prefix} \
1177 --bindir=%{_bindir} \
1178 --sbindir=%{_sbindir} \
1179 --sysconfdir=%{_sysconfdir} \
1180 --datadir=%{_datadir} \
1181 --includedir=%{_includedir} \
1182 --libdir=%{_libdir} \
1183 --libexecdir=%{_libexecdir} \
1184 --localstatedir=%{_localstatedir} \
1185 --sharedstatedir=%{_sharedstatedir} \
1186 --mandir=%{_mandir} \
1187 --infodir=%{_infodir} ';
1188 } # done %configure
1189
1190 if ($section =~ /m/) {
1191 $macrostring =~ s'%{__make}'make ';
1192 } # done make
1193
1194 if ($section =~ /i/) {
1195 # This is where we need to mangle $prefix.
1196 $macrostring =~ s'%makeinstall'make %{fhs} install';
1197 $prefix = $buildroot;
1198 } # done %install and/or %makeinstall
1199
1200 # Build data
1201 # Note that these are processed in reverse order to get the substitution order right
1202 if ($section =~ /b/) {
1203# $macrostring =~ s'%{fhs}'host=$DEB_HOST_GNU_TYPE \
1204# build=$DEB_BUILD_GNU_TYPE \
1205 $macrostring =~ s'%{fhs}'prefix=%{_prefix} \
1206 exec-prefix=%{_exec_prefix} \
1207 bindir=%{_bindir} \
1208 sbindir=%{_sbindir} \
1209 sysconfdir=%{_sysconfdir} \
1210 datadir=%{_datadir} \
1211 includedir=%{_includedir} \
1212 libdir=%{_libdir} \
1213 libexecdir=%{_libexecdir} \
1214 localstatedir=%{_localstatedir} \
1215 sharedstatedir=%{_sharedstatedir} \
1216 mandir=%{_mandir} \
1217 infodir=%{_infodir} \
1218';
1219
1220 # Note that the above regex terminates with the extra space
1221 # "Just In Case" of user additions, which will then get neatly
1222 # tagged on the end where they take precedence (supposedly)
1223 # over the "default" ones.
1224
1225 # Now we cascade the macros introduced above. >_<
1226 # Wot ot to go theah:
1227 $macrostring =~ s|%{_mandir}|%{_datadir}/man|g; #/usr/share/man
1228 $macrostring =~ s|%{_infodir}|%{_datadir}/info|g; #/usr/share/info
1229 $macrostring =~ s|%{_oldincludedir}|/usr/include|g; #/usr/include
1230 $macrostring =~ s|%{_includedir}|%{_prefix}/include|g; #/usr/include
1231 $macrostring =~ s|%{_libdir}|%{_exec_prefix}/%{_lib}|g; #/usr/lib
1232 $macrostring =~ s|%{_lib}|lib|g; #?
1233 $macrostring =~ s|%{_localstatedir}|/var|g; #/var
1234 $macrostring =~ s|%{_sharedstatedir}|%{_prefix}/com|g; #/usr/com WTF?
1235 $macrostring =~ s|%{_sysconfdir}|/etc|g; #/etc
1236 $macrostring =~ s|%{_datadir}|%{_prefix}/share|g; #/usr/share
1237 $macrostring =~ s|%{_libexecdir}|%{_exec_prefix}/libexec|g; #/usr/libexec
1238 $macrostring =~ s|%{_sbindir}|%{_exec_prefix}/sbin|g; #/usr/sbin
1239 $macrostring =~ s|%{_bindir}|%{_exec_prefix}/bin|g; #/usr/bin
1240 $macrostring =~ s|%{_exec_prefix}|%{_prefix}|g; #/usr
1241 $macrostring =~ s|%{_prefix}|/usr|g; #/usr
1242 } # done with config section
1243
1244 # Package data
1245 if ($section =~ /p/) {
1246 $macrostring =~ s/\%\{buildroot\}/$buildroot/gi;
1247 foreach my $source (keys %{$pkgdata{sources}}) {
1248 $macrostring =~ s/\%\{source$source\}/$topdir\/SOURCES\/$pkgdata{sources}{$source}/gi;
1249 }
1250 $macrostring =~ s/\%\{name\}/$pkgdata{main}{name}/gi;
1251 $macrostring =~ s/\%\{version\}/$pkgdata{main}{version}/gi;
1252 $macrostring =~ s/\%\{release\}/$pkgdata{main}{release}/gi;
1253 }
1254
1255 # Globals, and not-so-globals
1256 if ($section =~ /g/) {
1257
1258 # special %define's. Handle the general case where we eval anything.
1259 # Prime example:
1260 #%define perl_vendorlib %(eval "`perl -V:installvendorlib`"; echo $installvendorlib)
1261 if ($macrostring =~ /^\%\(eval.+\)$/) {
1262 $macrostring =~ s/^\%\(//;
1263 $macrostring =~ s/\)$//;
1264 # Oy vey this gets silly for the perl bits. Executing a shell to
1265 # call Perl to get the vendorlib/sitelib/whatever "core" globals.
1266 # This can do more, but... eww.
1267 # Next line is non-optimal - what if $macrostring contains ' characters?
1268 $macrostring = qx { /bin/sh -c '$macrostring' };
1269 }
1270
1271 $macrostring =~ s|%{_builddir}|%{_topdir}/BUILD|g;
1272 $macrostring =~ s|%{_topdir}|$topdir|g;
1273 $macrostring =~ s|%{_tmppath}|$tmpdir|g;
1274 $macrostring =~ s'%{_docdir}'%{_datadir}/doc'g;
1275
1276 # Standard FHS locations. More or less.
1277 $macrostring =~ s'%{_bindir}'/usr/bin'g;
1278 $macrostring =~ s'%{_sbindir}'/usr/sbin'g;
1279 $macrostring =~ s'%{_mandir}'%{_datadir}/man'g;
1280 $macrostring =~ s'%{_includedir}'/usr/include'g;
1281 $macrostring =~ s'%{_libdir}'/usr/lib'g;
1282 $macrostring =~ s'%{_sysconfdir}'/etc'g;
1283 $macrostring =~ s'%{_localstatedir}'/var'g;
1284
1285 # FHS-ish locations that aren't quite actually FHS-specified.
1286 $macrostring =~ s'%{_datadir}'/usr/share'g;
1287
1288 # %define's
1289 foreach my $key (keys %specglobals) {
1290 $macrostring =~ s|%{$key}|$specglobals{$key}|g;
1291 }
1292
1293 # system programs. RPM uses a global config file for these; we'll just
1294 # ASS-U-ME and make life a little simpler.
1295 if ($macrostring =~ /\%\{\_\_([a-z0-9_-]+)\}/) {
1296 $macrostring =~ s|%{__([a-z0-9_-]+)}|$1|g;
1297 }
1298 } # done with globals section
1299
1300 return $macrostring;
1301} # end expandmacros()
1302
1303
1304
1305__END__
1306
1307
1308
1309=head1 NAME
1310
1311debbuild - Build Debian-compatible packages from RPM spec files
1312
1313=head1 SYNOPSIS
1314
1315 debbuild {-ba|-bb|-bp|-bc|-bi|-bl|-bs} [build-options] file.spec
1316
1317 debbuild {-ta|-tb|-tp|-tc|-ti|-tl|-ts} [build-options] file.tar.{gz|bz2}
1318
1319 debbuild --rebuild file.{src.rpm|sdeb}
1320
1321=head1 DESCRIPTION
1322
1323This script attempts to build Debian-friendly semi-native packages from RPM spec files,
1324RPM-friendly tarballs, and RPM source packages (.src.rpm files). It accepts I<most> of the
1325options rpmbuild does, and should be able to interpret most spec files usefully. Perl
1326modules should be handled via CPAN+dh-make-perl instead; Debian's conventions for such
1327things do not lend themselves to automated conversion.
1328
1329As far as possible, the command-line options are identical to those from rpmbuild, although
1330several rpmbuild options are not supported:
1331
1332 --recompile
1333 --showrc
1334 --buildroot
1335 --clean
1336 --nobuild
1337 --rmsource
1338 --rmspec
1339 --sign
1340 --target
1341
1342Some of these could probably be trivially added. Feel free to send me a patch. ;)
1343
1344Complex spec files will most likely not work well, if at all. Rewrite them from scratch -
1345you'll have to make heavy modifications anyway.
1346
1347If you see something you don't like, mail me. Send a patch if you feel inspired. I don't
1348promise I'll do anything other than say "Yup, that's broken" or "Got your message".
1349
1350=head1 ASSUMPTIONS
1351
1352As with rpmbuild, debbuild makes some assumptions about your system.
1353
1354=over 4
1355
1356=item *
1357
1358Either you have rights to do as you please under /usr/src/debian, or you have created a file
1359~/.debmacros containing a suitable %_topdir definition.
1360
1361Both rpmbuild and debbuild require the directories %_topdir/{BUILD,SOURCES,SPECS}. However,
1362where rpmbuild requires the %_topdir/{RPMS,SRPMS} directories, debbuild
1363requires %_topdir/{DEBS,SDEBS} instead. Create them in advance;
1364some subdirectories are created automatically as needed, but most are not.
1365
1366=item *
1367
1368/var/tmp must allow script execution - rpmbuild and debbuild both rely on creating and
1369executing shell scripts for much of their functionality. By default, debbuild also creates
1370install trees under /var/tmp - however this is (almost) entirely under the control of the
1371package's .spec file.
1372
1373=item *
1374
1375If you wish to --rebuild a .src.rpm, your %_topdir for both debbuild and rpmbuild must either
1376match, or be suitably symlinked one direction or another so that both programs are effectively
1377working in the same tree. (Or you could just manually wrestle files around your system.)
1378
1379You could symlink ~/.rpmmacros to ~/.debmacros (or vice versa) and save yourself some hassle
1380if you need to rebuild .src.rpm packages on a regular basis. Currently debbuild only uses the
1381%_topdir macro definition, although there are many more things that rpmbuild can use from
1382~/.rpmmacros.
1383
1384=back
1385
1386=head1 AUTHOR
1387
1388debbuild was written by Kris Deugau <kdeugau@deepnet.cx>. A version that approximates
1389current is available at http://www.deepnet.cx/debbuild/.
1390
1391=head1 BUGS
1392
1393Funky Things Happen if you forget a command-line option or two. I've been too lazy to bother
1394fixing this.
1395
1396Many macro expansions are unsupported or incompletely supported.
1397
1398The generated scriptlets don't quite match those from rpmbuild exactly. There are extra
1399environment variables and preprocessing that I haven't needed (yet).
1400
1401Dcumentation, such as it is, will likely remain perpetually out of date.
1402
1403%_topdir and the five "working" directories under %_topdir could arguably be created by
1404debbuild. However, rpmbuild doesn't create these directories either.
1405
1406=head1 SEE ALSO
1407
1408rpm(8), rpmbuild(8), and pretty much any document describing how to write a .spec file.
1409
1410=cut
Note: See TracBrowser for help on using the repository browser.