source: trunk/debbuild@ 30

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

/trunk

checkpoint
%files support should be pretty much complete for basic cases

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