source: trunk/debbuild@ 79

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

/trunk

Add source package to --showpkgs output.

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