source: trunk/debbuild@ 29

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

/trunk

Checkpoint

  • Property svn:executable set to *
  • Property svn:keywords set to Date Rev Author
File size: 25.0 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-14 23:20:12 +0000 (Wed, 14 Dec 2005) $
9# SVN revision $Rev: 29 $
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 }
[29]419
[16]420 # pre/post (un)install scripts
421 if (/^\%pre\b/) {
422 while (<SPECFILE>) {
423 redo LINE if /^\%/;
424 $preinstscript .= $_;
425 }
[6]426 }
[16]427 if (/^\%post\b/) {
428 while (<SPECFILE>) {
429 redo LINE if /^\%/;
430 $postinstscript .= $_;
431 }
[6]432 }
[16]433 if (/^\%preun\b/) {
434 while (<SPECFILE>) {
435 redo LINE if /^\%/;
436 $preuninstscript .= $_;
437 }
438 }
439 if (/^\%postun\b/) {
440 while (<SPECFILE>) {
441 redo LINE if /^\%/;
442 $postuninstscript .= $_;
443 }
444 }
[29]445 # done %pre/%post scripts
446
[23]447 if (/^\%files(?:\s+(?:-n\s+)?([a-zA-z0-9]+))?/) {
448 my $pkgname = 'main';
[29]449 if ($1) { # Magic to add entries to the right list of files
[24]450 if (/-n/) { $pkgname = $1; } else { $pkgname = "$pkgdata{main}{name}-$1"; }
[23]451 }
[27]452 while (<SPECFILE>) {
[29]453 chomp;
454 # need to update this to deal (properly) with %dir, %attr, etc
455 next if /^\%dir/;
456 next if /^\%attr/;
457 next if /^\%defattr/;
458
459 # and finally we can fall through %{_<FHS>}-prefixed locations...
460 $filelist{$pkgname} .= " $_" if /^\%\{_/;
461
462 # ... unknown or "next section" % directives ...
[27]463 redo LINE if /^\%/;
[29]464
465 # ... and "normal" files
[27]466 $filelist{$pkgname} .= " $_";
467 }
[29]468 } # done %file section
469
[18]470 if (/^\%changelog/) {
471 $pkgdata{main}{changelog} = '';
472 while (<SPECFILE>) {
473 redo LINE if /^\%/;
474 $pkgdata{main}{changelog} .= $_;
475 }
476 }
[14]477
478 } else { # Data from the spec file "header"
479
[5]480 if (/^summary:\s+(.+)/i) {
481 $pkgdata{main}{summary} = $1;
482 } elsif (/^name:\s+(.+)/i) {
[24]483 $pkgdata{main}{name} = expandmacros($1,'g');
[5]484 } elsif (/^version:\s+(.+)/i) {
[24]485 $pkgdata{main}{version} = expandmacros($1,'g');
[5]486 } elsif (/^release:\s+(.+)/i) {
[24]487 $pkgdata{main}{release} = expandmacros($1,'g');
[5]488 } elsif (/^group:\s+(.+)/i) {
489 $pkgdata{main}{group} = $1;
490 } elsif (/^copyright:\s+(.+)/i) {
491 $pkgdata{main}{copyright} = $1;
492 } elsif (/^url:\s+(.+)/i) {
493 $pkgdata{main}{url} = $1;
494 } elsif (/^packager:\s+(.+)/i) {
495 $pkgdata{main}{packager} = $1;
[7]496 } elsif (/^buildroot:\s+(.+)/i) {
497 $buildroot = $1;
[5]498 } elsif (/^source:\s+(.+)/i) {
499 $pkgdata{main}{source} = $1;
[6]500 die "Unknown tarball format $1\n" if $1 !~ /\.tar\.(?:gz|bz2)$/;
[15]501 } elsif (/^source([0-9]+):\s+(.+)/i) {
502 $pkgdata{sources}{$1} = $2;
[10]503 } elsif (/^patch([^:]+):\s+(.+)$/i) {
[26]504 my $patchname = "patch$1";
505 $pkgdata{main}{$patchname} = $2;
506 if ($pkgdata{main}{$patchname} =~ /\//) {
507 # URL-style patch. Rare but not unheard-of.
508 my @patchbits = split '/', $pkgdata{main}{$patchname};
509 $pkgdata{main}{$patchname} = $patchbits[$#patchbits];
510 }
[5]511 }
512#Name: suwrap
513#Version: 0.04
514#Release: 3
515#Group: Applications/System
516#Copyright: WebHart internal ONLY. :(
517#BuildArchitectures: i386
518#BuildRoot: /tmp/%{name}-%{version}
519#Url: http://virtual.webhart.net
520#Packager: Kris Deugau <kdeugau@deepnet.cx>
521#Source: ftp://virtual.webhart.net/%{name}-%{version}.tar.gz
522
523 }
524 }
[7]525
[14]526 # Parse and replace some more macros. More will be replaced even later.
527
[10]528 # Expand macros as necessary.
[12]529 $scriptletbase = expandmacros($scriptletbase,'gp');
[7]530
531 $buildroot = $cmdbuildroot if $cmdbuildroot;
[12]532 $buildroot = expandmacros($buildroot,'gp');
[7]533
[16]534 close SPECFILE;
[5]535} # end parse_spec()
536
537
[7]538## prep()
[14]539# Writes and executes the %prep script (mostly) built while reading the spec file.
[7]540sub prep {
[10]541 # Replace some things here just to make sure.
[12]542 $prepscript = expandmacros($prepscript,'gp');
[10]543
[24]544#print $prepscript; exit 0;
[23]545
[10]546 # create script filename
[13]547 my $prepscriptfile = "$tmpdir/deb-tmp.prep.".int(rand(99998)+1);
[10]548 sysopen(PREPSCRIPT, $prepscriptfile, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW)
[7]549 or die $!;
[10]550 print PREPSCRIPT $scriptletbase;
551 print PREPSCRIPT $prepscript;
552 close PREPSCRIPT;
[7]553
[10]554 # execute
555 print "Calling \%prep script $prepscriptfile...\n";
556 system("/bin/sh -e $prepscriptfile") == 0
[14]557 or die "Can't exec: $!\n";
[7]558
[10]559 # and clean up
560 unlink $prepscriptfile;
[7]561} # end prep()
562
563
[5]564## build()
[14]565# Writes and executes the %build script (mostly) built while reading the spec file.
[5]566sub build {
[12]567 # Expand the macros
568 $buildscript = expandmacros($buildscript,'cgbp');
569
[7]570 # create script filename
[13]571 my $buildscriptfile = "$tmpdir/deb-tmp.build.".int(rand(99998)+1);
[7]572 sysopen(BUILDSCRIPT, $buildscriptfile, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW)
573 or die $!;
574 print BUILDSCRIPT $scriptletbase;
575 print BUILDSCRIPT $buildscript;
576 close BUILDSCRIPT;
577
578 # execute
579 print "Calling \%build script $buildscriptfile...\n";
580 system("/bin/sh -e $buildscriptfile") == 0
[14]581 or die "Can't exec: $!\n";
[7]582
583 # and clean up
584 unlink $buildscriptfile;
[5]585} # end build()
586
587
[7]588## install()
[14]589# Writes and executes the %install script (mostly) built while reading the spec file.
[7]590sub install {
[12]591 # Expand the macros
592 $installscript = expandmacros($installscript,'igbp');
593
[7]594 # create script filename
[13]595 my $installscriptfile = "$tmpdir/deb-tmp.inst.".int(rand(99998)+1);
[7]596 sysopen(INSTSCRIPT, $installscriptfile, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW)
597 or die $!;
598 print INSTSCRIPT $scriptletbase;
[23]599# print INSTSCRIPT $cleanscript; # Clean up our install target before installing into it.
[7]600 print INSTSCRIPT $installscript;
601 close INSTSCRIPT;
602
603 # execute
604 print "Calling \%install script $installscriptfile...\n";
605 system("/bin/sh -e $installscriptfile") == 0
[14]606 or die "Can't exec: $!\n";
[7]607
608 # and clean up
609 unlink $installscriptfile;
610} # end install()
611
612
[8]613## binpackage()
614# Creates the binary .deb package from the installed tree in $buildroot.
[14]615# Writes and executes a shell script to do so.
616# Creates miscellaneous files required by dpkg-deb to actually build the package file.
[27]617# Should handle simple subpackages
[8]618sub binpackage {
[14]619 # Make sure we have somewhere to write the .deb file
[9]620 if (!-e "$topdir/DEBS/i386") {
621# "if [ -e $topdir/DEBS/i386 ]; then\n\tmkdir $topdir/DEBS/i386\nfi\n".
622 mkdir "$topdir/DEBS/i386";
623 }
[14]624
[27]625##work
626 foreach my $pkg (@pkglist) {
[8]627
[27]628 # Gotta do this first, otherwise we don't have a place to move files from %files
629 mkdir "$buildroot/$pkg";
[28]630
[27]631 my @pkgfilelist = split ' ', $filelist{$pkg};
632 foreach my $pkgfile (@pkgfilelist) {
633 my @filepath = ($pkgfile =~ /(.+)\/([a-zA-Z0-9_\.\+\-]+)$/);
634 qx { mkdir -p $buildroot/$pkg$filepath[0] }
635 if $filepath[0] ne '';
636 qx { mv $buildroot$pkgfile $buildroot/$pkg$filepath[0] };
637 }
[28]638
[27]639 # Gotta do this next, otherwise the control file has nowhere to go. >:(
640 mkdir "$buildroot/$pkg/DEBIAN";
641
642 # create script filename
643 my $debscriptfile = "$tmpdir/deb-tmp.pkg.".int(rand(99998)+1);
644 sysopen(DEBSCRIPT, $debscriptfile, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW)
[8]645 or die $!;
[27]646 print DEBSCRIPT $scriptletbase;
647 print DEBSCRIPT "fakeroot dpkg-deb -b $buildroot/$pkg $topdir/DEBS/i386/".
648 "$pkgdata{$pkg}{name}_$pkgdata{$pkg}{version}-$pkgdata{main}{release}_i386.deb\n";
649 # %$&$%@#@@#%@@@ Debian and their horrible ugly package names. >:(
650 close DEBSCRIPT;
[8]651
[27]652 my $control = "Package: $pkgdata{$pkg}{name}\n".
653 "Version: $pkgdata{$pkg}{version}-$pkgdata{main}{release}\n".
654 "Section: $pkgdata{$pkg}{group}\n".
[8]655 "Priority: optional\n".
656 "Architecture: i386\n".
657 "Maintainer: $pkgdata{main}{packager}\n".
[27]658 "Description: $pkgdata{$pkg}{summary}\n";
659 $control .= "$pkgdata{$pkg}{desc}\n";
[8]660
[27]661 open CONTROL, ">$buildroot/$pkg/DEBIAN/control";
662 print CONTROL $control;
663 close CONTROL;
[8]664
[27]665 if ($preinstscript ne '') {
666 open PREINST, ">$buildroot/$pkg/DEBIAN/preinst";
667 print PREINST "#!/bin/sh\nset -e\n\n";
668 print PREINST $preinstscript;
669 close PREINST;
670 `chmod 0755 $buildroot/$pkg/DEBIAN/preinst`;
671 }
672 if ($postinstscript ne '') {
673 open POSTINST, ">$buildroot/$pkg/DEBIAN/postinst";
674 print POSTINST "#!/bin/sh\nset -e\n\n";
675 print POSTINST $postinstscript;
676 close POSTINST;
677 `chmod 0755 $buildroot/$pkg/DEBIAN/postinst`;
678 }
679 if ($preuninstscript ne '') {
680 open PREUNINST, ">$buildroot/$pkg/DEBIAN/prerm";
681 print PREUNINST "#!/bin/sh\nset -e\n\n";
682 print PREUNINST $preuninstscript;
683 close PREUNINST;
684 `chmod 0755 $buildroot/$pkg/DEBIAN/prerm`;
685 }
686 if ($postuninstscript ne '') {
687 open POSTUNINST, ">$buildroot/$pkg/DEBIAN/postrm";
688 print POSTUNINST "#!/bin/sh\nset -e\n\n";
689 print POSTUNINST $postuninstscript;
690 close POSTUNINST;
691 `chmod 0755 $buildroot/$pkg/DEBIAN/postrm`;
692 }
[16]693
[27]694#print `ls -l $buildroot/DEBIAN`;
[16]695
[8]696#Package: httpd
697#Version: 2.0.54-7via
698#Section: unknown
699#Priority: optional
700#Architecture: i386
701#Depends: libc6 (>= 2.3.2.ds1-21), libdb4.2, libexpat1 (>= 1.95.8), libssl0.9.7, libapr0
702#Replaces: apache2
703#Installed-Size: 3076
704#Maintainer: Kris Deugau <kdeugau@vianet.ca>
705#Description: apache2 for ViaNet
706# apache2 for ViaNet. Includes per-vhost setuid patches from
707# http://home.samfundet.no/~sesse/mpm-itk/.
708
[27]709 # execute
710 print "Calling package creation script $debscriptfile for $pkgdata{$pkg}{name}...\n";
711 system("/bin/sh -e $debscriptfile") == 0
[14]712 or die "Can't exec: $!\n";
[8]713
[27]714 # and clean up
715 unlink $debscriptfile;
716
717 } # subpackage loop
718
[8]719} # end binpackage()
720
721
[4]722sub srcpackage {}
[10]723
724
725## expandmacros()
726# Expands all %{blah} macros in the passed string
[14]727# Split up a bit with some sections so we don't spend time trying to
728# expand macros that are only used in a few specific places.
[10]729sub expandmacros {
730 my $macrostring = shift;
[14]731 my $section = shift;
[10]732
[25]733 # To allow the FHS-ish %configure and %makeinstall to work The Right Way.
[12]734 # (Without clobbering the global $buildroot.)
735 my $prefix = '';
736
[11]737 if ($section =~ /c/) {
[12]738 # %configure macro
[17]739# Don't know what it's for, don't have a useful default replacement
740# --program-prefix=%{_program_prefix} \
741 $macrostring =~ s'%configure'./configure --host=$DEB_HOST_GNU_TYPE \
742 --build=$DEB_BUILD_GNU_TYPE \
743 --prefix=%{_prefix} \
744 --exec-prefix=%{_exec_prefix} \
745 --bindir=%{_bindir} \
746 --sbindir=%{_sbindir} \
747 --sysconfdir=%{_sysconfdir} \
748 --datadir=%{_datadir} \
749 --includedir=%{_includedir} \
750 --libdir=%{_libdir} \
751 --libexecdir=%{_libexecdir} \
752 --localstatedir=%{_localstatedir} \
753 --sharedstatedir=%{_sharedstatedir} \
754 --mandir=%{_mandir} \
755 --infodir=%{_infodir} ';
[12]756 } # done %configure
757
758 if ($section =~ /m/) {
759 $macrostring =~ s'%{__make}'make ';
[25]760 } # done make
[12]761
762 if ($section =~ /i/) {
763 # This is where we need to mangle $prefix.
[24]764 $macrostring =~ s'%makeinstall'make %{fhs} install';
[12]765 $prefix = $buildroot;
766 } # done %install and/or %makeinstall
767
768 # Build data
769 # Note that these are processed in reverse order to get the substitution order right
770 if ($section =~ /b/) {
[24]771# $macrostring =~ s'%{fhs}'host=$DEB_HOST_GNU_TYPE \
772# build=$DEB_BUILD_GNU_TYPE \
773 $macrostring =~ s'%{fhs}'prefix=%{_prefix} \
[17]774 exec-prefix=%{_exec_prefix} \
775 bindir=%{_bindir} \
776 sbindir=%{_sbindir} \
777 sysconfdir=%{_sysconfdir} \
778 datadir=%{_datadir} \
779 includedir=%{_includedir} \
780 libdir=%{_libdir} \
781 libexecdir=%{_libexecdir} \
782 localstatedir=%{_localstatedir} \
783 sharedstatedir=%{_sharedstatedir} \
784 mandir=%{_mandir} \
785 infodir=%{_infodir} \
786';
[10]787
788 # Note that the above regex terminates with the extra space
[12]789 # "Just In Case" of user additions, which will then get neatly
790 # tagged on the end where they take precedence (supposedly)
791 # over the "default" ones.
[10]792
[14]793 # Now we cascade the macros introduced above. >_<
794 # Wot ot to go theah:
795 $macrostring =~ s|%{_mandir}|%{_datadir}/man|g; #/usr/share/man
796 $macrostring =~ s|%{_infodir}|%{_datadir}/info|g; #/usr/share/info
[25]797 $macrostring =~ s|%{_oldincludedir}|/usr/include|g; #/usr/include
798 $macrostring =~ s|%{_includedir}|%{_prefix\}/include|g; #/usr/include
799 $macrostring =~ s|%{_libdir}|%{_exec_prefix}/%{_lib}|g; #/usr/lib
[14]800 $macrostring =~ s|%{_lib}|lib|g; #?
[25]801 $macrostring =~ s|%{_localstatedir}|/var|g; #/var
802 $macrostring =~ s|%{_sharedstatedir}|%{_prefix}/com|g; #/usr/com WTF?
803 $macrostring =~ s|%{_sysconfdir}|/etc|g; #/etc
804 $macrostring =~ s|%{_datadir}|%{_prefix}/share|g; #/usr/share
805 $macrostring =~ s|%{_libexecdir}|%{_exec_prefix}/libexec|g; #/usr/libexec
806 $macrostring =~ s|%{_sbindir}|%{_exec_prefix}/sbin|g; #/usr/sbin
807 $macrostring =~ s|%{_bindir}|%{_exec_prefix}/bin|g; #/usr/bin
808 $macrostring =~ s|%{_exec_prefix}|%{_prefix}|g; #/usr
[14]809 $macrostring =~ s|%{_prefix}|/usr|g; #/usr
[10]810 } # done with config section
811
[12]812 # Package data
813 if ($section =~ /p/) {
[15]814 $macrostring =~ s/\%\{buildroot\}/$buildroot/gi;
815 foreach my $source (keys %{$pkgdata{sources}}) {
816 $macrostring =~ s/\%\{source$source\}/$topdir\/SOURCES\/$pkgdata{sources}{$source}/gi;
817 }
818 $macrostring =~ s/\%\{name\}/$pkgdata{main}{name}/gi;
819 $macrostring =~ s/\%\{version\}/$pkgdata{main}{version}/gi;
820 $macrostring =~ s/\%\{release\}/$pkgdata{main}{release}/gi;
[12]821 }
822
823 # Globals, and not-so-globals
824 if ($section =~ /g/) {
[29]825 $macrostring =~ s|%{_builddir}|%{_topdir}/BUILD|g;
826 $macrostring =~ s|%{_topdir}|$topdir|g;
[13]827 $macrostring =~ s|%{_tmppath}|$tmpdir|g;
[12]828 $macrostring =~ s'%{_docdir}'/usr/share/doc'g;
[23]829
830 # %define's
831 foreach my $key (keys %specglobals) {
832 $macrostring =~ s|%{$key}|$specglobals{$key}|g;
833 }
834
835 # system programs. RPM uses a global config file for these; we'll just
836 # ASS-U-ME and make life a little simpler.
837 if ($macrostring =~ /\%\{\_\_([a-z0-9_-]+)\}/) {
838 $macrostring =~ s|%{__([a-z0-9_-]+)}|$1|g;
839 }
[10]840 } # done with globals section
841
842 return $macrostring;
843} # end expandmacros()
[22]844
845
846
847=head1 NAME
848
849debbuild - Build Debian-compatible packages from RPM spec files
850
851=head1 SYNOPSIS
852
853 debbuild {-ba|-bb|-bp|-bc|-bi|-bl|-bs} [build-options] file.spec
854
855 debbuild {-ta|-tb|-tp|-tc|-ti|-tl|-ts} [build-options] file.tar.{gz|bz2}
856
857 debbuild --rebuild file.src.{rpm|deb}
858
859=head1 DESCRIPTION
860
861This script attempts to build Debian-friendly semi-native packages
862from RPM spec files, RPM-friendly tarballs, and RPM source packages
863(.src.rpm). It accepts I<most> of the options rpmbuild does, and
864should be able to interpret most spec files usefully. Perl modules
865should be handled via CPAN+dh-make-perl instead; Debian's conventions
866for such things do not lend themselves to automated conversion.
867
868As far as possible, the command-line options are identical to those
869from rpmbuild, although several rpmbuild options are not supported.
870
871=cut
Note: See TracBrowser for help on using the repository browser.