source: trunk/debbuild@ 35

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

/trunk

Checkpoint - source package sub

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