source: trunk/debbuild@ 27

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

/trunk

Checkpoint
%files support sort of in place
Basic support for subpackages in place

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