source: trunk/debbuild@ 28

Last change on this file since 28 was 28, checked in by kdeugau, 18 years ago

/trunk

Checkpoint
Tweaks to %files handling, cruft cleanup

  • Property svn:executable set to *
  • Property svn:keywords set to Date Rev Author
File size: 24.8 KB
RevLine 
[2]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: 2005-12-12 23:10:42 +0000 (Mon, 12 Dec 2005) $
9# SVN revision $Rev: 28 $
10# Last update by $Author: kdeugau $
11###
12
[5]13use strict;
[6]14use warnings;
[7]15use Fcntl; # for sysopen flags
[5]16
[10]17# regex debugger
18#use re "debug";
19
[3]20# Program flow:
21# -> Parse/execute "system" config/macros (if any - should be rare)
22# -> Parse/execute "user" config/macros (if any - *my* requirement is %_topdir)
23# -> Parse command line for options, spec file/tarball/.src.deb (NB - also accept .src.rpm)
24
[2]25# User's prefs for dirs, environment, etc,etc,etc.
26# config file ~/.debmacros
27# Default ordered search paths for config/macros:
28# /usr/lib/rpm/rpmrc /usr/lib/rpm/redhat/rpmrc /etc/rpmrc ~/.rpmrc
29# /usr/lib/rpm/macros /usr/lib/rpm/redhat/macros /etc/rpm/macros ~/.rpmmacros
30# **NOTE: May be possible to (ab)use bits of debhelper
31
32# Build tree
33# default is /usr/src/debian/{BUILD,SOURCES,SPECS,DEBS,SDEBS}
34
[3]35# Globals
36my $specfile;
37my $tarball;
38my $srcpkg;
[7]39my $cmdbuildroot;
40my $tarballdir; # This should really be initialized, but the coding makes it, um, ugly.
[23]41my %specglobals; # For %define's in specfile, among other things.
[6]42
43# Initialized globals
[3]44my $verbosity = 0;
[4]45my %cmdopts = (type => '',
46 stage => 'a',
47 short => 'n'
48 );
[6]49my $topdir = "/usr/src/debian";
[13]50my $buildroot = "%{_tmppath}/%{name}-%{version}-%{release}.root".int(rand(99998)+1);
[6]51
52# "Constants"
[4]53my %targets = ('p' => 'Prep',
54 'c' => 'Compile',
55 'i' => 'Install',
56 'l' => 'Verify %files',
57 'a' => 'Build binary and source',
58 'b' => 'Build binary',
59 's' => 'Build source'
60 );
[6]61my $scriptletbase =
62q(#!/bin/sh
[3]63
[6]64 RPM_SOURCE_DIR="%{_topdir}/SOURCES"
65 RPM_BUILD_DIR="%{_topdir}/BUILD"
66 RPM_OPT_FLAGS="-O2 -g -march=i386 -mcpu=i686"
67 RPM_ARCH="i386"
68 RPM_OS="linux"
69 export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_ARCH RPM_OS
70 RPM_DOC_DIR="/usr/share/doc"
71 export RPM_DOC_DIR
72 RPM_PACKAGE_NAME="%{name}"
73 RPM_PACKAGE_VERSION="%{version}"
74 RPM_PACKAGE_RELEASE="%{release}"
75 export RPM_PACKAGE_NAME RPM_PACKAGE_VERSION RPM_PACKAGE_RELEASE
76 RPM_BUILD_ROOT="%{buildroot}"
77 export RPM_BUILD_ROOT
[10]78);
79foreach (`dpkg-architecture`) {
80 s/=(.+)/="$1"/;
81 $scriptletbase .= " $_";
82}
83$scriptletbase .=
84q(
[6]85 set -x
86 umask 022
87 cd %{_topdir}/BUILD
88);
89
[5]90# Package data
91# This is the form of $pkgdata{pkgname}{meta}
92# meta includes Summary, Name, Version, Release, Group, Copyright,
93# Source, URL, Packager, BuildRoot, Description
[6]94# 10/31/2005 Maybe this should be flatter? -kgd
[5]95my %pkgdata;
[27]96my @pkglist = ('main'); #sigh
[23]97# Files listing. Embedding this in %pkgdata would be, um, messy.
98my %filelist;
[5]99
[6]100# Scriptlets
101my $prepscript;
102my $buildscript;
[23]103# %install doesn't need the full treatment from %clean; just an empty place to install to.
104# NB - rpm doesn't do this; is it really necessary?
105my $installscript = '[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT'."\n";
[7]106my $cleanscript;
[16]107# pre/post (un)install scripts. Note that these will likely barf as-is. :/
108my $preinstscript = '';
109my $postinstscript = '';
110my $preuninstscript = '';
111my $postuninstscript = '';
[6]112
[5]113die "Not enough arguments\n" if #$argv == 0;
114
[13]115# Snag some environment data
116my $tmpdir;
117if (defined $ENV{TMP} && $ENV{TMP} =~ /^(\/var)?\/tmp$/) {
118 $tmpdir = $ENV{TMP};
119} else {
120 $tmpdir = "/var/tmp";
121}
122
[7]123##main
124
[4]125load_userconfig();
[3]126parse_cmd();
127
[7]128if ($cmdopts{type} eq 'b') {
129 # Need to read the spec file to find the tarball. Note that
130 # this also generates most of the shell script required.
131 parse_spec();
132}
133
[4]134# Hokay. Need to:
[14]135# -> prep if -.p OR (-.[cilabs] AND !--short-circuit)
[7]136if ($cmdopts{stage} eq 'p' || ($cmdopts{stage} =~ /[cilabs]/ && $cmdopts{short} ne 'y')) {
137 prep();
138}
[14]139# -> build if -.c OR (-.[ilabs] AND !--short-circuit)
[7]140if ($cmdopts{stage} eq 'c' || ($cmdopts{stage} =~ /[ilabs]/ && $cmdopts{short} ne 'y')) {
141 build();
142}
[14]143# -> install if -.[ilabs]
[28]144#if ($cmdopts{stage} eq 'i' || ($cmdopts{stage} =~ /[labs]/ && $cmdopts{short} ne 'y')) {
145if ($cmdopts{stage} =~ /[ilabs]/) {
[7]146 install();
147}
[14]148# -> binpkg and srcpkg if -.a
[7]149if ($cmdopts{stage} eq 'a') {
[4]150 binpackage();
[7]151 srcpackage();
[4]152}
[14]153# -> binpkg if -.b
[7]154if ($cmdopts{stage} eq 'b') {
155 binpackage();
156}
[14]157# -> srcpkg if -.s
[7]158if ($cmdopts{stage} eq 's') {
159 srcpackage();
160}
[4]161
162# Just in case.
163exit 0;
164
165
166## load_userconfig()
167# Loads user configuration (if any)
168# Currently only handles .debmacros
169# Needs to handle "other files"
170sub load_userconfig {
[5]171 my (undef,undef,undef,undef,undef,undef,undef,$homedir,undef) = getpwuid($<);
[4]172 if (-e "$homedir/.debmacros") {
173 open USERMACROS,"<$homedir/.debmacros";
174 while (<USERMACROS>) {
[7]175 # And we also only handle a few macros at the moment.
[4]176 if (/^\%_topdir/) {
[5]177 my (undef,$tmp) = split /\s+/, $_;
178 $topdir = $tmp;
[4]179 }
180 }
181 }
182} # end load_userconfig()
183
184
[3]185## parse_cmd()
[4]186# Parses command line into global hash %cmdopts, other globals
[3]187# Options based on rpmbuild's options
188sub parse_cmd {
189 # Don't feel like coding my own option parser...
190 #use Getopt::Long;
191 # ... but I may have to: (OTOH, rpm uses popt, so maybe we can too.)
192 #use Getopt::Popt qw(:all);
[4]193 # Or not. >:( Stupid Debian lack of findable Perl module names in packages.
[3]194
195 # Stuff it.
[4]196 my $prevopt = '';
[3]197 foreach (@ARGV) {
198 chomp;
[7]199
[3]200 # Is it an option?
201 if (/^-/) {
[7]202
[3]203 # Is it a long option?
204 if (/^--/) {
[4]205 if (/^--short-circuit/) {
206 $cmdopts{short} = 'y';
[5]207 } elsif (/^--rebuild/) {
208 $cmdopts{type} = 's';
[4]209 } else {
210 print "Long opt $_\n";
211 }
[3]212 } else {
[14]213 # Not a long option
[5]214 if (/^-[bt]/) {
215 if ($cmdopts{stage} eq 's') {
216 # Mutually exclusive options.
217 die "Can't use $_ with --rebuild\n";
218 } else {
[14]219 # Capture the type (from "bare" files or tarball) and the stage (prep, build, etc)
[5]220 ($cmdopts{stage}) = (/^-[bt]([pcilabs])/);
221 ($cmdopts{type}) = (/^-([bt])[pcilabs]/);
222 }
[4]223 } elsif (/^-v/) {
224 # bump verbosity. Not sure what I'll actually do here...
225 } else {
226 die "Bad option $_\n";
227 }
[3]228 }
[14]229
230 } else { # Not an option argument
231
[5]232 # --buildroot is the only option that takes an argument
233 # Therefore, any *other* bare arguments are the spec file,
234 # tarball, or source package we're operating on - depending
235 # on which one we meet.
236 if ($prevopt eq '--buildroot') {
[7]237 $cmdbuildroot = $_;
[5]238 } else {
239 if ($cmdopts{type} eq 's') {
240 # Source package
[7]241 if (!/\.src\.(deb|rpm)$/) {
[5]242 die "Can't --rebuild with $_\n";
243 }
244 } elsif ($cmdopts{type} eq 'b') {
245 $specfile = $_;
246 # Spec file
247 } else {
248 # Tarball
249 }
250 }
[3]251 }
[7]252 $prevopt = $_;
253 } # foreach @ARGV
[4]254
255 # Some cross-checks. rpmbuild limits --short-circuit to just
256 # the "compile" and "install" targets - with good reason IMO.
[14]257 # Note that --short-circuit with -.p is not really an error, just redundant.
[4]258 # NB - this is NOT fatal, just ignored!
[10]259 if ($cmdopts{short} eq 'y' && $cmdopts{stage} =~ /[labs]/) {
[4]260 warn "Can't use --short-circuit for $targets{$cmdopts{stage}} stage. Ignoring.\n";
[28]261 $cmdopts{short} = 'n';
[4]262 }
[14]263
[3]264 # Valid options, with example arguments (if any):
265# Build from .spec file; mutually exclusive:
266 # -bp
267 # -bc
268 # -bi
269 # -bl
270 # -ba
271 # -bb
272 # -bs
273# Build from tarball; mutually exclusive:
274 # -tp
275 # -tc
276 # -ti
277 # -ta
278 # -tb
279 # -ts
280# Build from .src.(deb|rpm)
281 # --rebuild
282 # --recompile
283
284# General options
285 # --buildroot=DIRECTORY
286 # --clean
287 # --nobuild
288 # --nodeps
289 # --nodirtokens
290 # --rmsource
291 # --rmspec
292 # --short-circuit
293 # --target=CPU-VENDOR-OS
294
295 #my $popt = new Getopt::Popt(argv => \@ARGV, options => \@optionsTable);
296
297} # end parse_cmd()
298
[4]299
[5]300## parse_spec()
[14]301# Parse the .spec file.
[5]302sub parse_spec {
303 open SPECFILE,"<$specfile";
304
[6]305LINE: while (<SPECFILE>) {
[14]306 next if /^#/; # Ignore comments...
307 next if /^\s+$/; # ... and blank lines.
308
[5]309 if (/^\%/) {
310 # A macro that needs further processing.
[14]311
[23]312 if (/^\%define\s+([^\s]+)\s+([^\s]+)/) {
313 $specglobals{$1} = expandmacros($2,'g');
314 }
315
[27]316 if (/^\%description(?:\s+(?:-n\s+)?([a-zA-Z0-9_.-]+))?/) {
317 my $subname = "main";
318 if ($1) {
319 if (/-n/) { $subname = $1; } else { $subname = "$pkgdata{main}{name}-$1"; }
320 }
[8]321 while (<SPECFILE>) {
322 redo LINE if /^\%/;
[27]323 $pkgdata{$subname}{desc} .= " $_";
[8]324 }
[18]325 }
[27]326 if (/^\%package\s+(?:-n\s+)?([a-zA-Z0-9_.-]+)/) {
327 my $subname;
328 if (/-n/) { $subname = $1; } else { $subname = "$pkgdata{main}{name}-$1"; }
329 push @pkglist, $subname;
330 $pkgdata{$subname}{name} = $subname;
331 $pkgdata{$subname}{version} = $pkgdata{main}{version};
332 while (<SPECFILE>) {
333 redo LINE if /^\%/;
334 if (my ($dname,$dvalue) = (/^(Summary|Group|Version):\s+(.+)$/i)) {
335 $dname =~ tr/[A-Z]/[a-z]/;
336 $pkgdata{$subname}{$dname} = $dvalue;
337 }
338 }
339 }
[8]340
[6]341 if (/^\%prep/) {
342 # %prep section. May have %setup macro; may include %patch tags,
343 # may be just a bare shell script.
344
345 # This really should be local-ish, but we need just the filename for the source
346 $pkgdata{main}{source} =~ s|.+/([^/]+)$|$1|;
347
348 # Replace some core macros
[14]349 $pkgdata{main}{source} = expandmacros($pkgdata{main}{source},'gp');
[6]350
351PREPSCRIPT: while (<SPECFILE>) {
352 if (/^\%setup/) {
353 # Parse out the %setup macro. Note that we aren't supporting
[14]354 # many of RPM's %setup features.
[7]355 $prepscript .= "cd $topdir/BUILD\n";
356 if ( /\s+-n\s+([^\s]+)\s+/ ) {
357 $tarballdir = $1;
358 } else {
359 $tarballdir = "$pkgdata{main}{name}-$pkgdata{main}{version}";
360 }
[21]361 $prepscript .= "rm -rf $tarballdir\ntar -".
[6]362 ( $pkgdata{main}{source} =~ /\.tar\.gz$/ ? "z" : "" ).
363 ( $pkgdata{main}{source} =~ /\.tar\.bz2$/ ? "j" : "" ).
[21]364 ( /\s+-q\s+/ ? '' : 'vv' )."xf ".
365 "$topdir/SOURCES/$pkgdata{main}{source}\n".
[6]366 qq(STATUS=\$?\nif [ \$STATUS -ne 0 ]; then\n exit \$STATUS\nfi\n).
367 ( /\s+-n\s+([^\s]+)\s+/ ?
368 "cd $1\n" : "cd $pkgdata{main}{name}-$pkgdata{main}{version}\n" ).
369 qq([ `/usr/bin/id -u` = '0' ] && /bin/chown -Rhf root .\n).
370 qq([ `/usr/bin/id -u` = '0' ] && /bin/chgrp -Rhf root .\n).
371 qq(/bin/chmod -Rf a+rX,g-w,o-w .\n);
[10]372 } elsif (/^\%patch([^:]+)\s+(.+)$/) {
373 $prepscript .= "patch $2 <$topdir/SOURCES/".$pkgdata{main}{"patch$1"}."\n";
[6]374 } else {
375 last PREPSCRIPT if /^\%/;
376 $prepscript .= $_;
377 }
378 }
379 redo LINE;
380 }
[12]381 if (/^\%build/) {
[6]382 # %build. This is pretty much just a shell script. There
383 # *are* a few macros, but we're not going to deal with them yet.
[7]384 $buildscript .= "cd $tarballdir\n";
[10]385BUILDSCRIPT: while (<SPECFILE>) {
386 if (/^\%configure/) {
[12]387 $buildscript .= expandmacros($_,'cgbp');
[25]388 } elsif (/^\%\{__make\}/) {
[12]389 $buildscript .= expandmacros($_,'mgbp');
[10]390 } else {
[24]391 last BUILDSCRIPT if /^\%[^{]/;
[10]392 $buildscript .= $_;
393 }
[6]394 }
[10]395 redo LINE;
[5]396 }
[6]397 if (/^\%install/) {
[7]398 $installscript .= "cd $tarballdir\n";
[12]399INSTALLSCRIPT: while (<SPECFILE>) {
400 if (/^\%makeinstall/) {
401 $installscript .= expandmacros($_,'igbp');
402 } else {
403 last INSTALLSCRIPT if /^\%/;
404 $installscript .= $_;
405 }
406 }
407 redo LINE;
[6]408 }
409 if (/^\%clean/) {
[7]410 while (<SPECFILE>) {
411 redo LINE if /^\%/;
412 $cleanscript .= $_;
413 }
[23]414print "before:\n$cleanscript\n";
[12]415 $cleanscript = expandmacros($cleanscript,'gp');
[23]416print "\nafter:\n$cleanscript\n";
417exit 0;
[6]418 }
[16]419 # pre/post (un)install scripts
420 if (/^\%pre\b/) {
421 while (<SPECFILE>) {
422 redo LINE if /^\%/;
423 $preinstscript .= $_;
424 }
[6]425 }
[16]426 if (/^\%post\b/) {
427 while (<SPECFILE>) {
428 redo LINE if /^\%/;
429 $postinstscript .= $_;
430 }
[6]431 }
[16]432 if (/^\%preun\b/) {
433 while (<SPECFILE>) {
434 redo LINE if /^\%/;
435 $preuninstscript .= $_;
436 }
437 }
438 if (/^\%postun\b/) {
439 while (<SPECFILE>) {
440 redo LINE if /^\%/;
441 $postuninstscript .= $_;
442 }
443 }
[23]444 if (/^\%files(?:\s+(?:-n\s+)?([a-zA-z0-9]+))?/) {
445 my $pkgname = 'main';
446 if ($1) {
[24]447 if (/-n/) { $pkgname = $1; } else { $pkgname = "$pkgdata{main}{name}-$1"; }
[23]448 }
[27]449 # subpackage not based on "main" package
450#print "$pkgname\n";
451 while (<SPECFILE>) {
452 # need to update this to deal with %dir, %attr, etc
453 redo LINE if /^\%/;
454chomp;
455#print; print "\n";
456 $filelist{$pkgname} .= " $_";
457#print $pkgdata{$pkgname}{files}; print "\n";
458 }
[23]459 # do we replace \n's with \s in $filelist{$pkgname}?
[6]460 # Danger! Danger!
461 }
[18]462 if (/^\%changelog/) {
463 $pkgdata{main}{changelog} = '';
464 while (<SPECFILE>) {
465 redo LINE if /^\%/;
466 $pkgdata{main}{changelog} .= $_;
467 }
468 }
[14]469
470 } else { # Data from the spec file "header"
471
[5]472 if (/^summary:\s+(.+)/i) {
473 $pkgdata{main}{summary} = $1;
474 } elsif (/^name:\s+(.+)/i) {
[24]475 $pkgdata{main}{name} = expandmacros($1,'g');
[5]476 } elsif (/^version:\s+(.+)/i) {
[24]477 $pkgdata{main}{version} = expandmacros($1,'g');
[5]478 } elsif (/^release:\s+(.+)/i) {
[24]479 $pkgdata{main}{release} = expandmacros($1,'g');
[5]480 } elsif (/^group:\s+(.+)/i) {
481 $pkgdata{main}{group} = $1;
482 } elsif (/^copyright:\s+(.+)/i) {
483 $pkgdata{main}{copyright} = $1;
484 } elsif (/^url:\s+(.+)/i) {
485 $pkgdata{main}{url} = $1;
486 } elsif (/^packager:\s+(.+)/i) {
487 $pkgdata{main}{packager} = $1;
[7]488 } elsif (/^buildroot:\s+(.+)/i) {
489 $buildroot = $1;
[5]490 } elsif (/^source:\s+(.+)/i) {
491 $pkgdata{main}{source} = $1;
[6]492 die "Unknown tarball format $1\n" if $1 !~ /\.tar\.(?:gz|bz2)$/;
[15]493 } elsif (/^source([0-9]+):\s+(.+)/i) {
494 $pkgdata{sources}{$1} = $2;
[10]495 } elsif (/^patch([^:]+):\s+(.+)$/i) {
[26]496 my $patchname = "patch$1";
497 $pkgdata{main}{$patchname} = $2;
498 if ($pkgdata{main}{$patchname} =~ /\//) {
499 # URL-style patch. Rare but not unheard-of.
500 my @patchbits = split '/', $pkgdata{main}{$patchname};
501 $pkgdata{main}{$patchname} = $patchbits[$#patchbits];
502 }
[5]503 }
504#Name: suwrap
505#Version: 0.04
506#Release: 3
507#Group: Applications/System
508#Copyright: WebHart internal ONLY. :(
509#BuildArchitectures: i386
510#BuildRoot: /tmp/%{name}-%{version}
511#Url: http://virtual.webhart.net
512#Packager: Kris Deugau <kdeugau@deepnet.cx>
513#Source: ftp://virtual.webhart.net/%{name}-%{version}.tar.gz
514
515 }
516 }
[7]517
[14]518 # Parse and replace some more macros. More will be replaced even later.
519
[10]520 # Expand macros as necessary.
[12]521 $scriptletbase = expandmacros($scriptletbase,'gp');
[7]522
523 $buildroot = $cmdbuildroot if $cmdbuildroot;
[12]524 $buildroot = expandmacros($buildroot,'gp');
[7]525
[16]526 close SPECFILE;
[5]527} # end parse_spec()
528
529
[7]530## prep()
[14]531# Writes and executes the %prep script (mostly) built while reading the spec file.
[7]532sub prep {
[10]533 # Replace some things here just to make sure.
[12]534 $prepscript = expandmacros($prepscript,'gp');
[10]535
[24]536#print $prepscript; exit 0;
[23]537
[10]538 # create script filename
[13]539 my $prepscriptfile = "$tmpdir/deb-tmp.prep.".int(rand(99998)+1);
[10]540 sysopen(PREPSCRIPT, $prepscriptfile, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW)
[7]541 or die $!;
[10]542 print PREPSCRIPT $scriptletbase;
543 print PREPSCRIPT $prepscript;
544 close PREPSCRIPT;
[7]545
[10]546 # execute
547 print "Calling \%prep script $prepscriptfile...\n";
548 system("/bin/sh -e $prepscriptfile") == 0
[14]549 or die "Can't exec: $!\n";
[7]550
[10]551 # and clean up
552 unlink $prepscriptfile;
[7]553} # end prep()
554
555
[5]556## build()
[14]557# Writes and executes the %build script (mostly) built while reading the spec file.
[5]558sub build {
[12]559 # Expand the macros
560 $buildscript = expandmacros($buildscript,'cgbp');
561
[7]562 # create script filename
[13]563 my $buildscriptfile = "$tmpdir/deb-tmp.build.".int(rand(99998)+1);
[7]564 sysopen(BUILDSCRIPT, $buildscriptfile, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW)
565 or die $!;
566 print BUILDSCRIPT $scriptletbase;
567 print BUILDSCRIPT $buildscript;
568 close BUILDSCRIPT;
569
570 # execute
571 print "Calling \%build script $buildscriptfile...\n";
572 system("/bin/sh -e $buildscriptfile") == 0
[14]573 or die "Can't exec: $!\n";
[7]574
575 # and clean up
576 unlink $buildscriptfile;
[5]577} # end build()
578
579
[7]580## install()
[14]581# Writes and executes the %install script (mostly) built while reading the spec file.
[7]582sub install {
[12]583 # Expand the macros
584 $installscript = expandmacros($installscript,'igbp');
585
[7]586 # create script filename
[13]587 my $installscriptfile = "$tmpdir/deb-tmp.inst.".int(rand(99998)+1);
[7]588 sysopen(INSTSCRIPT, $installscriptfile, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW)
589 or die $!;
590 print INSTSCRIPT $scriptletbase;
[23]591# print INSTSCRIPT $cleanscript; # Clean up our install target before installing into it.
[7]592 print INSTSCRIPT $installscript;
593 close INSTSCRIPT;
594
595 # execute
596 print "Calling \%install script $installscriptfile...\n";
597 system("/bin/sh -e $installscriptfile") == 0
[14]598 or die "Can't exec: $!\n";
[7]599
600 # and clean up
601 unlink $installscriptfile;
602} # end install()
603
604
[8]605## binpackage()
606# Creates the binary .deb package from the installed tree in $buildroot.
[14]607# Writes and executes a shell script to do so.
608# Creates miscellaneous files required by dpkg-deb to actually build the package file.
[27]609# Should handle simple subpackages
[8]610sub binpackage {
[14]611 # Make sure we have somewhere to write the .deb file
[9]612 if (!-e "$topdir/DEBS/i386") {
613# "if [ -e $topdir/DEBS/i386 ]; then\n\tmkdir $topdir/DEBS/i386\nfi\n".
614 mkdir "$topdir/DEBS/i386";
615 }
[14]616
[27]617##work
618 foreach my $pkg (@pkglist) {
[8]619
[27]620 # Gotta do this first, otherwise we don't have a place to move files from %files
621 mkdir "$buildroot/$pkg";
[28]622
[27]623 my @pkgfilelist = split ' ', $filelist{$pkg};
624 foreach my $pkgfile (@pkgfilelist) {
625 my @filepath = ($pkgfile =~ /(.+)\/([a-zA-Z0-9_\.\+\-]+)$/);
626 qx { mkdir -p $buildroot/$pkg$filepath[0] }
627 if $filepath[0] ne '';
628 qx { mv $buildroot$pkgfile $buildroot/$pkg$filepath[0] };
629 }
[28]630
[27]631 # Gotta do this next, otherwise the control file has nowhere to go. >:(
632 mkdir "$buildroot/$pkg/DEBIAN";
633
634 # create script filename
635 my $debscriptfile = "$tmpdir/deb-tmp.pkg.".int(rand(99998)+1);
636 sysopen(DEBSCRIPT, $debscriptfile, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW)
[8]637 or die $!;
[27]638 print DEBSCRIPT $scriptletbase;
639 print DEBSCRIPT "fakeroot dpkg-deb -b $buildroot/$pkg $topdir/DEBS/i386/".
640 "$pkgdata{$pkg}{name}_$pkgdata{$pkg}{version}-$pkgdata{main}{release}_i386.deb\n";
641 # %$&$%@#@@#%@@@ Debian and their horrible ugly package names. >:(
642 close DEBSCRIPT;
[8]643
[27]644 my $control = "Package: $pkgdata{$pkg}{name}\n".
645 "Version: $pkgdata{$pkg}{version}-$pkgdata{main}{release}\n".
646 "Section: $pkgdata{$pkg}{group}\n".
[8]647 "Priority: optional\n".
648 "Architecture: i386\n".
649 "Maintainer: $pkgdata{main}{packager}\n".
[27]650 "Description: $pkgdata{$pkg}{summary}\n";
651 $control .= "$pkgdata{$pkg}{desc}\n";
[8]652
[27]653 open CONTROL, ">$buildroot/$pkg/DEBIAN/control";
654 print CONTROL $control;
655 close CONTROL;
[8]656
[27]657 if ($preinstscript ne '') {
658 open PREINST, ">$buildroot/$pkg/DEBIAN/preinst";
659 print PREINST "#!/bin/sh\nset -e\n\n";
660 print PREINST $preinstscript;
661 close PREINST;
662 `chmod 0755 $buildroot/$pkg/DEBIAN/preinst`;
663 }
664 if ($postinstscript ne '') {
665 open POSTINST, ">$buildroot/$pkg/DEBIAN/postinst";
666 print POSTINST "#!/bin/sh\nset -e\n\n";
667 print POSTINST $postinstscript;
668 close POSTINST;
669 `chmod 0755 $buildroot/$pkg/DEBIAN/postinst`;
670 }
671 if ($preuninstscript ne '') {
672 open PREUNINST, ">$buildroot/$pkg/DEBIAN/prerm";
673 print PREUNINST "#!/bin/sh\nset -e\n\n";
674 print PREUNINST $preuninstscript;
675 close PREUNINST;
676 `chmod 0755 $buildroot/$pkg/DEBIAN/prerm`;
677 }
678 if ($postuninstscript ne '') {
679 open POSTUNINST, ">$buildroot/$pkg/DEBIAN/postrm";
680 print POSTUNINST "#!/bin/sh\nset -e\n\n";
681 print POSTUNINST $postuninstscript;
682 close POSTUNINST;
683 `chmod 0755 $buildroot/$pkg/DEBIAN/postrm`;
684 }
[16]685
[27]686#print `ls -l $buildroot/DEBIAN`;
[16]687
[8]688#Package: httpd
689#Version: 2.0.54-7via
690#Section: unknown
691#Priority: optional
692#Architecture: i386
693#Depends: libc6 (>= 2.3.2.ds1-21), libdb4.2, libexpat1 (>= 1.95.8), libssl0.9.7, libapr0
694#Replaces: apache2
695#Installed-Size: 3076
696#Maintainer: Kris Deugau <kdeugau@vianet.ca>
697#Description: apache2 for ViaNet
698# apache2 for ViaNet. Includes per-vhost setuid patches from
699# http://home.samfundet.no/~sesse/mpm-itk/.
700
[27]701 # execute
702 print "Calling package creation script $debscriptfile for $pkgdata{$pkg}{name}...\n";
703 system("/bin/sh -e $debscriptfile") == 0
[14]704 or die "Can't exec: $!\n";
[8]705
[27]706 # and clean up
707 unlink $debscriptfile;
708
709 } # subpackage loop
710
[8]711} # end binpackage()
712
713
[4]714sub srcpackage {}
[10]715
716
717## expandmacros()
718# Expands all %{blah} macros in the passed string
[14]719# Split up a bit with some sections so we don't spend time trying to
720# expand macros that are only used in a few specific places.
[10]721sub expandmacros {
722 my $macrostring = shift;
[14]723 my $section = shift;
[10]724
[25]725 # To allow the FHS-ish %configure and %makeinstall to work The Right Way.
[12]726 # (Without clobbering the global $buildroot.)
727 my $prefix = '';
728
[11]729 if ($section =~ /c/) {
[12]730 # %configure macro
[17]731# Don't know what it's for, don't have a useful default replacement
732# --program-prefix=%{_program_prefix} \
733 $macrostring =~ s'%configure'./configure --host=$DEB_HOST_GNU_TYPE \
734 --build=$DEB_BUILD_GNU_TYPE \
735 --prefix=%{_prefix} \
736 --exec-prefix=%{_exec_prefix} \
737 --bindir=%{_bindir} \
738 --sbindir=%{_sbindir} \
739 --sysconfdir=%{_sysconfdir} \
740 --datadir=%{_datadir} \
741 --includedir=%{_includedir} \
742 --libdir=%{_libdir} \
743 --libexecdir=%{_libexecdir} \
744 --localstatedir=%{_localstatedir} \
745 --sharedstatedir=%{_sharedstatedir} \
746 --mandir=%{_mandir} \
747 --infodir=%{_infodir} ';
[12]748 } # done %configure
749
750 if ($section =~ /m/) {
751 $macrostring =~ s'%{__make}'make ';
[25]752 } # done make
[12]753
754 if ($section =~ /i/) {
755 # This is where we need to mangle $prefix.
[24]756 $macrostring =~ s'%makeinstall'make %{fhs} install';
[12]757 $prefix = $buildroot;
758 } # done %install and/or %makeinstall
759
760 # Build data
761 # Note that these are processed in reverse order to get the substitution order right
762 if ($section =~ /b/) {
[24]763# $macrostring =~ s'%{fhs}'host=$DEB_HOST_GNU_TYPE \
764# build=$DEB_BUILD_GNU_TYPE \
765 $macrostring =~ s'%{fhs}'prefix=%{_prefix} \
[17]766 exec-prefix=%{_exec_prefix} \
767 bindir=%{_bindir} \
768 sbindir=%{_sbindir} \
769 sysconfdir=%{_sysconfdir} \
770 datadir=%{_datadir} \
771 includedir=%{_includedir} \
772 libdir=%{_libdir} \
773 libexecdir=%{_libexecdir} \
774 localstatedir=%{_localstatedir} \
775 sharedstatedir=%{_sharedstatedir} \
776 mandir=%{_mandir} \
777 infodir=%{_infodir} \
778';
[10]779
780 # Note that the above regex terminates with the extra space
[12]781 # "Just In Case" of user additions, which will then get neatly
782 # tagged on the end where they take precedence (supposedly)
783 # over the "default" ones.
[10]784
[14]785 # Now we cascade the macros introduced above. >_<
786 # Wot ot to go theah:
787 $macrostring =~ s|%{_mandir}|%{_datadir}/man|g; #/usr/share/man
788 $macrostring =~ s|%{_infodir}|%{_datadir}/info|g; #/usr/share/info
[25]789 $macrostring =~ s|%{_oldincludedir}|/usr/include|g; #/usr/include
790 $macrostring =~ s|%{_includedir}|%{_prefix\}/include|g; #/usr/include
791 $macrostring =~ s|%{_libdir}|%{_exec_prefix}/%{_lib}|g; #/usr/lib
[14]792 $macrostring =~ s|%{_lib}|lib|g; #?
[25]793 $macrostring =~ s|%{_localstatedir}|/var|g; #/var
794 $macrostring =~ s|%{_sharedstatedir}|%{_prefix}/com|g; #/usr/com WTF?
795 $macrostring =~ s|%{_sysconfdir}|/etc|g; #/etc
796 $macrostring =~ s|%{_datadir}|%{_prefix}/share|g; #/usr/share
797 $macrostring =~ s|%{_libexecdir}|%{_exec_prefix}/libexec|g; #/usr/libexec
798 $macrostring =~ s|%{_sbindir}|%{_exec_prefix}/sbin|g; #/usr/sbin
799 $macrostring =~ s|%{_bindir}|%{_exec_prefix}/bin|g; #/usr/bin
800 $macrostring =~ s|%{_exec_prefix}|%{_prefix}|g; #/usr
[14]801 $macrostring =~ s|%{_prefix}|/usr|g; #/usr
[10]802 } # done with config section
803
[12]804 # Package data
805 if ($section =~ /p/) {
[15]806 $macrostring =~ s/\%\{buildroot\}/$buildroot/gi;
807 foreach my $source (keys %{$pkgdata{sources}}) {
808 $macrostring =~ s/\%\{source$source\}/$topdir\/SOURCES\/$pkgdata{sources}{$source}/gi;
809 }
810 $macrostring =~ s/\%\{name\}/$pkgdata{main}{name}/gi;
811 $macrostring =~ s/\%\{version\}/$pkgdata{main}{version}/gi;
812 $macrostring =~ s/\%\{release\}/$pkgdata{main}{release}/gi;
[12]813 }
814
815 # Globals, and not-so-globals
816 if ($section =~ /g/) {
817 $macrostring =~ s/\%\{_topdir\}/$topdir/g;
[13]818 $macrostring =~ s|%{_tmppath}|$tmpdir|g;
[12]819 $macrostring =~ s'%{_docdir}'/usr/share/doc'g;
[23]820
821 # %define's
822 foreach my $key (keys %specglobals) {
823 $macrostring =~ s|%{$key}|$specglobals{$key}|g;
824 }
825
826 # system programs. RPM uses a global config file for these; we'll just
827 # ASS-U-ME and make life a little simpler.
828 if ($macrostring =~ /\%\{\_\_([a-z0-9_-]+)\}/) {
829 $macrostring =~ s|%{__([a-z0-9_-]+)}|$1|g;
830 }
[10]831 } # done with globals section
832
833 return $macrostring;
834} # end expandmacros()
[22]835
836
837
838=head1 NAME
839
840debbuild - Build Debian-compatible packages from RPM spec files
841
842=head1 SYNOPSIS
843
844 debbuild {-ba|-bb|-bp|-bc|-bi|-bl|-bs} [build-options] file.spec
845
846 debbuild {-ta|-tb|-tp|-tc|-ti|-tl|-ts} [build-options] file.tar.{gz|bz2}
847
848 debbuild --rebuild file.src.{rpm|deb}
849
850=head1 DESCRIPTION
851
852This script attempts to build Debian-friendly semi-native packages
853from RPM spec files, RPM-friendly tarballs, and RPM source packages
854(.src.rpm). It accepts I<most> of the options rpmbuild does, and
855should be able to interpret most spec files usefully. Perl modules
856should be handled via CPAN+dh-make-perl instead; Debian's conventions
857for such things do not lend themselves to automated conversion.
858
859As far as possible, the command-line options are identical to those
860from rpmbuild, although several rpmbuild options are not supported.
861
862=cut
Note: See TracBrowser for help on using the repository browser.