~peter-pearse/ubuntu/oneiric/libglib-perl/prop001

« back to all changes in this revision

Viewing changes to MakeHelper.pm

  • Committer: Bazaar Package Importer
  • Author(s): Marc 'HE' Brockschmidt
  • Date: 2004-06-14 13:23:01 UTC
  • Revision ID: james.westby@ubuntu.com-20040614132301-3jexjlx4er0qzvwi
Tags: upstream-1.043
ImportĀ upstreamĀ versionĀ 1.043

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#
 
2
# $Header: /cvsroot/gtk2-perl/gtk2-perl-xs/Glib/MakeHelper.pm,v 1.28.2.4 2004/04/12 02:26:37 muppetman Exp $
 
3
#
 
4
 
 
5
package Glib::MakeHelper;
 
6
 
 
7
our $VERSION = '0.03';
 
8
 
 
9
=head1 NAME
 
10
 
 
11
Glib::MakeHelper - Makefile.PL utilities for Glib-based extensions
 
12
 
 
13
=head1 SYNOPSIS
 
14
 
 
15
 eval "use Glib::MakeHelper; 1"
 
16
     or complain_that_glib_is_too_old_and_die();
 
17
 
 
18
 %xspod_files = Glib::MakeHelper->do_pod_files (@xs_files);
 
19
 
 
20
 package MY;
 
21
 sub postamble {
 
22
     return Glib::MakeHelper->postamble_clean ()
 
23
          . Glib::MakeHelper->postamble_docs (@main::xs_files)
 
24
          . Glib::MakeHelper->postamble_rpms (
 
25
                 MYLIB     => $build_reqs{MyLib},
 
26
            );
 
27
 }
 
28
 
 
29
=head1 DESCRIPTION
 
30
 
 
31
The Makefile.PL for your typical Glib-based module is huge and hairy, thanks to
 
32
all the crazy hoops you have to jump through to get things right.  This module
 
33
wraps up some of the more intense and error-prone bits to reduce the amount of
 
34
copied code and potential for errors.
 
35
 
 
36
=cut
 
37
 
 
38
use strict;
 
39
use warnings;
 
40
use Carp;
 
41
use Cwd;
 
42
 
 
43
our @gend_pods = ();
 
44
 
 
45
=head1 METHODS
 
46
 
 
47
=over
 
48
 
 
49
=item HASH = Glib::MakeHelper->do_pod_files (@xs_files)
 
50
 
 
51
Scan the I<@xs_files> and return a hash describing the pod files that will
 
52
be created.  This is in the format wanted by WriteMakefile(). If @ARGV contains
 
53
the string C<disable-apidoc> an empty list will be returned and thus no apidoc
 
54
pod will be generated speeding up the build process.
 
55
 
 
56
=cut
 
57
 
 
58
sub do_pod_files
 
59
{
 
60
        return () if (grep /disable[-_]apidoc/i, @ARGV);
 
61
        print STDERR "Including ApiDoc pod.\n";
 
62
 
 
63
        shift; # package name
 
64
 
 
65
        # try to get it from pwd first, then fall back to installed
 
66
        # this is so Glib will get associated copy, and everyone else
 
67
        # should use the installed glib copy
 
68
        eval { require 'ParseXSDoc.pm'; 1; } or require Glib::ParseXSDoc;
 
69
        $@ = undef;
 
70
        import Glib::ParseXSDoc;
 
71
 
 
72
        my %pod_files = ();
 
73
 
 
74
        open PARSE, '>build/doc.pl';
 
75
        select PARSE;
 
76
        my $pods = xsdocparse (@_);
 
77
        select STDOUT;
 
78
        @gend_pods = ();
 
79
        foreach (@$pods)
 
80
        {
 
81
                my $pod = $_;
 
82
                my $path = '$(INST_LIB)';
 
83
                $pod = File::Spec->catfile ($path, split (/::/, $_)) . ".pod";
 
84
                push @gend_pods, $pod;
 
85
                $pod_files{$pod} = '$(INST_MAN3DIR)/'.$_.'.$(MAN3EXT)';
 
86
        }
 
87
        $pod_files{'$(INST_LIB)/$(FULLEXT)/index.pod'} = '$(INST_MAN3DIR)/$(NAME)::index.$(MAN3EXT)';
 
88
 
 
89
        return %pod_files;
 
90
}
 
91
 
 
92
=item string = Glib::MakeHelper->postamble_clean (@files)
 
93
 
 
94
Create and return the text of a realclean rule that cleans up after much 
 
95
of the autogeneration performed by Glib-based modules.  Everything in @files
 
96
will be deleted, too (it may be empty).
 
97
 
 
98
The reasoning behind using this instead of just having you use the 'clean'
 
99
or 'realclean' keys is that this avoids you having to remember to put Glib's
 
100
stuff in your Makefile.PL's WriteMakefile arguments.
 
101
 
 
102
=cut
 
103
 
 
104
sub postamble_clean
 
105
{
 
106
        shift; # package name
 
107
"
 
108
realclean ::
 
109
        -\$(RM_RF) build blib_done perl-\$(DISTNAME).spec ".join(" ", @_)."
 
110
";
 
111
}
 
112
 
 
113
=item string = Glib::MakeHelper->postamble_docs (@xs_files)
 
114
 
 
115
NOTE: this is The Old Way.  see L<postamble_docs_full> for The New Way.
 
116
 
 
117
Create and return the text of Makefile rules to build documentation from
 
118
the XS files with Glib::ParseXSDoc and Glib::GenPod.
 
119
 
 
120
Use this in your MY::postamble to enable autogeneration of POD.
 
121
 
 
122
This updates dependencies with the list of pod names generated by an earlier
 
123
run of C<do_pod_files>.
 
124
 
 
125
There is a special Makefile variable POD_DEPENDS that should be set to the
 
126
list of files that need to be created before the doc.pl step is run, include
 
127
files.
 
128
 
 
129
There is also a variable BLIB_DONE which should be used as a dependency
 
130
anywhere a rule needs to be sure that a loadable and working module resides in
 
131
the blib directory before running.
 
132
 
 
133
=cut
 
134
 
 
135
sub postamble_docs
 
136
{
 
137
        my ($class, @xs_files) = @_;
 
138
        return Glib::MakeHelper->postamble_docs_full (XS_FILES => \@xs_files);
 
139
}
 
140
 
 
141
=item string = Glib::MakeHelper->postamble_docs_full (...)
 
142
 
 
143
Create and return the text of Makefile rules to build documentation from
 
144
the XS files with Glib::ParseXSDoc and Glib::GenPod.
 
145
 
 
146
Use this in your MY::postamble to enable autogeneration of POD.
 
147
 
 
148
This updates dependencies with the list of pod names generated by an earlier
 
149
run of C<do_pod_files>.
 
150
 
 
151
There is a special Makefile variable POD_DEPENDS that should be set to the
 
152
list of files that need to be created before the doc.pl step is run, include
 
153
files.
 
154
 
 
155
There is also a variable BLIB_DONE which should be used as a dependancy
 
156
anywhere a rule needs to be sure that a loadable and working module resides in
 
157
the blib directory before running.
 
158
 
 
159
The parameters are a list of key=>value pairs.  You must specify at minimum
 
160
either DEPENDS or XS_FILES.
 
161
 
 
162
=over
 
163
 
 
164
=item DEPENDS => ExtUtils::Depends object
 
165
 
 
166
Most gtk2-perl modules use ExtUtils::Depends to find headers, typemaps,
 
167
and other data from parent modules and to install this data for child
 
168
modules.  We can find from this object the list of XS files to scan for
 
169
documentation, doctype mappings for parent modules, and other goodies.
 
170
 
 
171
=item XS_FILES => \@xs_file_names
 
172
 
 
173
A list of xs files to scan for documentation.  Ignored if DEPENDS is
 
174
used.
 
175
 
 
176
=item DOCTYPES => \@doctypes_file_names
 
177
 
 
178
List of filenames to pass to C<Glib::GenPod::add_types>.  May be omitted.
 
179
 
 
180
=item COPYRIGHT => string
 
181
 
 
182
POD text to be inserted in the 'COPYRIGHT' section of each generated page.
 
183
May be omitted.
 
184
 
 
185
=item COPYRIGHT_FROM => file name
 
186
 
 
187
The name of a file containing the POD to be inserted in the 'COPYRIGHT'
 
188
section of each generated page.  May be omitted.
 
189
 
 
190
=item NAME => extension name
 
191
 
 
192
The name of the extension, used to set $Glib::GenPod::MAIN_MOD (used in the
 
193
generated see-also listings).  May be omitted in favor of the name held
 
194
inside the ExtUtils::Depends object.  If DEPENDS is also specified, NAME wins.
 
195
 
 
196
=back
 
197
 
 
198
=cut
 
199
 
 
200
sub postamble_docs_full {
 
201
        my $class = shift; # package name
 
202
        my %params = @_;
 
203
 
 
204
        croak "Usage: $class\->postamble_docs_full (...)\n"
 
205
            . "  where ... is a list of key/value pairs including at the\n"
 
206
            . "  very least one of DEPENDS=>\$extutils_depends_object or\n"
 
207
            . "  XS_FILES=>\@xs_files\n"
 
208
            . "    "
 
209
                unless $params{DEPENDS} or $params{XS_FILES};
 
210
 
 
211
        my @xs_files = ();
 
212
        my @doctypes = ();
 
213
        my $add_types = '';
 
214
        my $copyright = '';
 
215
        my $name = '';
 
216
 
 
217
        if ($params{DOCTYPES}) {
 
218
                @doctypes = ('ARRAY' eq ref $params{DOCTYPES})
 
219
                          ? @{$params{DOCTYPES}}
 
220
                          : ($params{DOCTYPES});
 
221
        }
 
222
 
 
223
        if (UNIVERSAL::isa ($params{DEPENDS}, 'ExtUtils::Depends')) {
 
224
                my $dep = $params{DEPENDS};
 
225
 
 
226
                # fetch list of XS files from depends object.
 
227
                # HACK ALERT: the older versions of ExtUtils::Depends
 
228
                # (<0.2) use a different key layout and don't store enough
 
229
                # metadata about the dependencies, so we require >=0.2;
 
230
                # however, the older versions don't support import version
 
231
                # checking (in fact they don't support version-checking at
 
232
                # all), so the "use" test in a Makefile.PL can't tell if
 
233
                # it has loaded a new enough version!
 
234
                # the rewrite at version 0.200 added the get_dep() method,
 
235
                # which we use, so let's check for that.
 
236
                unless (defined &ExtUtils::Depends::get_deps) {
 
237
                        use ExtUtils::MakeMaker;
 
238
                        warn "ExtUtils::Depends is too old, need at "
 
239
                           . "least version 0.2";
 
240
                        # this is so that CPAN builds will do the upgrade
 
241
                        # properly.
 
242
                        WriteMakefile(
 
243
                                PREREQ_FATAL => 1,
 
244
                                PREREQ_PM => { 'ExtUtils::Depends' => 0.2, },
 
245
                        );
 
246
                        exit 1; # not reached.
 
247
                }
 
248
                # continue with the excessive validation...
 
249
                croak "value of DEPENDS key must be an ExtUtils::Depends object"
 
250
                        unless UNIVERSAL::isa $dep, 'ExtUtils::Depends';
 
251
                croak "corrupt or invalid ExtUtils::Depends instance -- "
 
252
                    . "the xs key is "
 
253
                    .(exists ($dep->{xs}) ? "missing" : "broken")."!"
 
254
                        unless exists $dep->{xs}
 
255
                           and 'ARRAY' eq ref $dep->{xs};
 
256
 
 
257
                # finally, *this* is what we wanted.
 
258
                @xs_files = @{$dep->{xs}};
 
259
 
 
260
                # fetch doctypes files from the depends' dependencies.
 
261
                my %deps = $dep->get_deps;
 
262
                foreach my $d (keys %deps) {
 
263
                        my $f = File::Spec->catfile ($deps{$d}{instpath},
 
264
                                                     'doctypes');
 
265
                        #warn "looking for $f\n";
 
266
                        push @doctypes, $f
 
267
                                if -f $f;
 
268
                }
 
269
 
 
270
                # the depends object conveniently knows the main module name.
 
271
                $name = $dep->{name};
 
272
        } else {
 
273
                @xs_files = @{ $params{XS_FILES} };
 
274
        }
 
275
 
 
276
        if ($params{COPYRIGHT}) {
 
277
                $copyright = $params{COPYRIGHT};
 
278
        } elsif ($params{COPYRIGHT_FROM}) {
 
279
                open IN, $params{COPYRIGHT_FROM} or
 
280
                        croak "can't open $params{COPYRIGHT_FROM} for reading: $!\n";
 
281
                local $/ = undef;
 
282
                $copyright = <IN>;
 
283
                close IN;
 
284
        }
 
285
 
 
286
        if ($copyright) {
 
287
                # this text has to be escaped for both make and the shell.
 
288
                $copyright =~ s/\n/\\n/gm; # collapse to one line.
 
289
                $copyright =~ s/"/\"/gm;   # escape double-quotes
 
290
                $copyright = "\$\$Glib::GenPod::COPYRIGHT=\"$copyright\";";
 
291
        }
 
292
 
 
293
        # the module name specified explicitly overrides the one in a
 
294
        # depends object.
 
295
        $name = $params{NAME} if $params{NAME};
 
296
        # now sanitize
 
297
        if ($name) {
 
298
                # this is supposed to be a module name; names don't have
 
299
                # things in them that need escaping, so let's leave it alone.
 
300
                # that way, if there's a quoting error, the user will figure
 
301
                # it out real quick.
 
302
                $name = "\$\$Glib::GenPod::MAIN_MOD=\"$name\";";
 
303
        }
 
304
 
 
305
        #warn "".scalar(@doctypes)." doctype files\n";
 
306
        #warn "".scalar(@xs_files)." xs files\n";
 
307
        
 
308
        $add_types = "add_types (".join(", ",map {"\"$_\""} @doctypes)."); "
 
309
                if @doctypes;
 
310
 
 
311
        my $docgen_code = ''
 
312
            . $add_types
 
313
            . ' '
 
314
            . $copyright
 
315
            . ' '
 
316
            . $name
 
317
            . ' $(POD_SET) '
 
318
            . 'xsdoc2pod("build/doc.pl", "$(INST_LIB)", "build/podindex");';
 
319
 
 
320
        #warn "docgen_code: $docgen_code\n";
 
321
 
 
322
        # BLIB_DONE should be set to something we can depend on that will
 
323
        # ensure that we are safe to link against an up to date module out
 
324
        # of blib. basically what we need to wait on is the static/dynamic
 
325
        # lib file to be created. the following trick is intended to handle
 
326
        # both of those cases without causing the other to happen.
 
327
        my $blib_done;
 
328
        # this is very sloppy, because different makes have different
 
329
        # conditional syntaxes.
 
330
        use Config;
 
331
        if ($Config{make} eq 'nmake') {
 
332
                warn "loathe nmake.\n";
 
333
                $blib_done = "
 
334
!If \"\$(LINKTYPE)\" == \"dynamic\"
 
335
BLIB_DONE=\$(INST_DYNAMIC)
 
336
!ELSE
 
337
BLIB_DONE=\$(INST_STATIC)
 
338
!ENDIF
 
339
";
 
340
        } else {
 
341
                # assuming GNU Make
 
342
                $blib_done = "
 
343
ifeq (\$(LINKTYPE), dynamic)
 
344
        BLIB_DONE=\$(INST_DYNAMIC)
 
345
else
 
346
        BLIB_DONE=\$(INST_STATIC)
 
347
endif
 
348
";
 
349
        }
 
350
 
 
351
"
 
352
BLIB_DONE=
 
353
$blib_done
 
354
 
 
355
# documentation stuff
 
356
build/doc.pl :: Makefile @xs_files
 
357
        $^X -I \$(INST_LIB) -I \$(INST_ARCHLIB) -MGlib::ParseXSDoc \\
 
358
                -e 'xsdocparse (".join(", ",map {"\"$_\""} @xs_files).")' > \$@
 
359
 
 
360
# passing all of these files through the single podindex file, which is 
 
361
# created at the same time, prevents problems with -j4 where xsdoc2pod would 
 
362
# have multiple instances
 
363
@gend_pods :: build/podindex \$(POD_DEPENDS)
 
364
 
 
365
build/podindex :: \$(BLIB_DONE) Makefile build/doc.pl
 
366
        $^X -I \$(INST_LIB) -I \$(INST_ARCHLIB) -MGlib::GenPod -M\$(NAME) \\
 
367
                -e '$docgen_code'
 
368
 
 
369
\$(INST_LIB)/\$(FULLEXT)/:
 
370
        $^X -MExtUtils::Command -e mkpath \$@
 
371
 
 
372
\$(INST_LIB)/\$(FULLEXT)/index.pod :: \$(INST_LIB)/\$(FULLEXT)/ build/podindex
 
373
        $^X -e 'print \"\\n=head1 NAME\\n\\n\$(NAME) API Reference Pod Index\\n\\n=head1 PAGES\\n\\n=over\\n\\n\"' \\
 
374
                > \$(INST_LIB)/\$(FULLEXT)/index.pod
 
375
        $^X -nae 'print \"=item L<\$\$F[1]>\\n\\n\";' < build/podindex >> \$(INST_LIB)/\$(FULLEXT)/index.pod
 
376
        $^X -e 'print \"=back\\n\\n\";' >> \$(INST_LIB)/\$(FULLEXT)/index.pod
 
377
"
 
378
}
 
379
 
 
380
=item string = Glib::MakeHelper->postamble_rpms (HASH)
 
381
 
 
382
Create and return the text of Makefile rules to manage building RPMs.
 
383
You'd put this in your Makefile.PL's MY::postamble.
 
384
 
 
385
I<HASH> is a set of search and replace keys for the spec file.  All 
 
386
occurences of @I<key>@ in the spec file template perl-$(DISTNAME).spec.in
 
387
will be replaced with I<value>.  'VERSION' and 'SOURCE' are supplied for
 
388
you.  For example:
 
389
 
 
390
 Glib::MakeHelper->postamble_rpms (
 
391
        MYLIB     => 2.0.0, # we can work with anything from this up
 
392
        MYLIB_RUN => 2.3.1, # we are actually compiled against this one
 
393
        PERL_GLIB => 1.01,  # you must have this version of Glib
 
394
 );
 
395
 
 
396
will replace @MYLIB@, @MYLIB_RUN@, and @PERL_GLIB@ in spec file.  See
 
397
the build setups for Glib and Gtk2 for examples.
 
398
 
 
399
Note: This function just returns an empty string on Win32.
 
400
 
 
401
=cut
 
402
 
 
403
sub postamble_rpms
 
404
{
 
405
        shift; # package name
 
406
 
 
407
        return '' if $^O eq 'MSWin32';
 
408
        
 
409
        my @dirs = qw{$(RPMS_DIR) $(RPMS_DIR)/BUILD $(RPMS_DIR)/RPMS 
 
410
                      $(RPMS_DIR)/SOURCES $(RPMS_DIR)/SPECS $(RPMS_DIR)/SRPMS};
 
411
        my $cwd = getcwd();
 
412
        
 
413
        chomp (my $date = `date +"%a %b %d %Y"`);
 
414
 
 
415
        my %subs = (
 
416
                'VERSION' => '$(VERSION)',
 
417
                'SOURCE'  => '$(DISTNAME)-$(VERSION).tar.gz',
 
418
                'DATE'    => $date,
 
419
                @_,
 
420
        );
 
421
        
 
422
        my $substitute = '$(PERL) -npe \''.join('; ', map {
 
423
                        "s/\\\@$_\\\@/$subs{$_}/g";
 
424
                } keys %subs).'\'';
 
425
 
 
426
"
 
427
 
 
428
RPMS_DIR=\$(HOME)/rpms
 
429
 
 
430
\$(RPMS_DIR)/:
 
431
        -mkdir @dirs
 
432
 
 
433
SUBSTITUTE=$substitute
 
434
 
 
435
perl-\$(DISTNAME).spec :: perl-\$(DISTNAME).spec.in \$(VERSION_FROM) Makefile
 
436
        \$(SUBSTITUTE) \$< > \$@
 
437
 
 
438
dist-rpms :: Makefile dist perl-\$(DISTNAME).spec \$(RPMS_DIR)/
 
439
        cp \$(DISTNAME)-\$(VERSION).tar.gz \$(RPMS_DIR)/SOURCES/
 
440
        rpmbuild -ba --define \"_topdir \$(RPMS_DIR)\" perl-\$(DISTNAME).spec
 
441
 
 
442
dist-srpms :: Makefile dist perl-\$(DISTNAME).spec \$(RPMS_DIR)/
 
443
        cp \$(DISTNAME)-\$(VERSION).tar.gz \$(RPMS_DIR)/SOURCES/
 
444
        rpmbuild -bs --nodeps --define \"_topdir \$(RPMS_DIR)\" perl-\$(DISTNAME).spec
 
445
";
 
446
}
 
447
 
 
448
package MY;
 
449
 
 
450
=back
 
451
 
 
452
=head1 NOTICE
 
453
 
 
454
The MakeMaker distributed with perl 5.8.x generates makefiles with a bug that
 
455
causes object files to be created in the wrong directory.  There is an override
 
456
inserted by this module under the name MY::const_cccmd to fix this issue.
 
457
 
 
458
=cut
 
459
 
 
460
sub const_cccmd {
 
461
        my $inherited = shift->SUPER::const_cccmd (@_);
 
462
        return '' unless $inherited;
 
463
        use Config;
 
464
        # a more sophisticated match may be necessary, but this works for me.
 
465
        if ($Config{cc} eq "cl") {
 
466
                warn "you are using MSVC... my condolences.\n";
 
467
                $inherited .= ' /Fo$@';
 
468
        } else {
 
469
                $inherited .= ' -o $@';
 
470
        }
 
471
        $inherited;
 
472
}
 
473
 
 
474
1;
 
475
 
 
476
=head1 AUTHOR
 
477
 
 
478
Ross McFarland E<lt>rwmcfa1 at neces dot comE<gt>
 
479
 
 
480
hacked up and documented by muppet.
 
481
 
 
482
=head1 COPYRIGHT AND LICENSE
 
483
 
 
484
Copyright 2003-2004 by the gtk2-perl team
 
485
 
 
486
This library is free software; you can redistribute it and/or modify
 
487
it under the terms of the Lesser General Public License (LGPL).  For 
 
488
more information, see http://www.fsf.org/licenses/lgpl.txt
 
489
 
 
490
=cut