5
package Glib::MakeHelper;
11
Glib::MakeHelper - Makefile.PL utilities for Glib-based extensions
15
eval "use Glib::MakeHelper; 1"
16
or complain_that_glib_is_too_old_and_die();
18
%xspod_files = Glib::MakeHelper->do_pod_files (@xs_files);
22
return Glib::MakeHelper->postamble_clean ()
23
. Glib::MakeHelper->postamble_docs (@main::xs_files)
24
. Glib::MakeHelper->postamble_rpms (
25
MYLIB => $build_reqs{MyLib},
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.
49
=item HASH = Glib::MakeHelper->do_pod_files (@xs_files)
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.
60
return () if (grep /disable[-_]apidoc/i, @ARGV);
61
print STDERR "Including generated API documentation...\n";
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;
70
import Glib::ParseXSDoc;
74
open PARSE, '>build/doc.pl';
76
my $pods = xsdocparse (@_);
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)';
87
$pod_files{'$(INST_LIB)/$(FULLEXT)/index.pod'} = '$(INST_MAN3DIR)/$(NAME)::index.$(MAN3EXT)';
92
=item LIST = Glib::MakeHelper->select_files_by_version ($stem, $major, $minor)
94
Returns a list of all files that match "$stem-\d+\.\d+" and for which the first
95
number is bigger than I<$major> and the second number is bigger than I<$minor>.
96
If I<$minor> is odd, it will be incremented by one so that the version number of
97
an upcoming stable release can be used during development as well.
101
sub select_files_by_version {
102
my ($class, $stem, $major, $minor) = @_;
104
# make minors even, so that we don't have to deal with stable/unstable
105
# file naming changes.
106
$minor++ if ($minor % 2);
109
foreach (glob $stem . '-*.*') {
110
if (/$stem-(\d+)\.(\d+)/) {
120
=item LIST = Glib::MakeHelper->read_source_list_file ($filename)
122
Reads I<$filename>, removes all comments (starting with "#") and leading and
123
trailing whitespace, and returns a list of all lines that survived the treatment.
127
sub read_source_list_file {
128
my ($class, $filename) = @_;
130
open IN, $filename or die "can't read $filename: $!\n";
132
s/#.*$//; # eat comments
133
s/^\s*//; # trim leading space
134
s/\s*$//; # trim trailing space
135
push @list, $_ if $_; # keep non-blanks
141
=item string = Glib::MakeHelper->get_configure_requires_yaml (%module_to_version)
143
Generates YAML code that lists every module found in I<%module_to_version>
144
under the C<configure_requires> key. This can be used with
145
L<ExtUtils::MakeMaker>'s C<EXTRA_META> parameter to specify which modules are
146
needed at I<Makefile.PL> time.
148
This function is B<deprecated> since L<ExtUtils::MakeMaker> 6.46 removed
149
support for C<EXTRA_META> in favor of the new keys C<META_MERGE> and
154
sub get_configure_requires_yaml {
155
shift; # package name
158
my $yaml = "configure_requires:\n";
159
while (my ($module, $version) = each %prereqs) {
160
$yaml .= " $module: $version\n";
166
=item string = Glib::MakeHelper->postamble_clean (@files)
168
Create and return the text of a realclean rule that cleans up after much
169
of the autogeneration performed by Glib-based modules. Everything in @files
170
will be deleted, too (it may be empty).
172
The reasoning behind using this instead of just having you use the 'clean'
173
or 'realclean' keys is that this avoids you having to remember to put Glib's
174
stuff in your Makefile.PL's WriteMakefile arguments.
178
our @ADDITIONAL_FILES_TO_CLEAN = ();
182
shift; # package name
185
-\$(RM_RF) build perl-\$(DISTNAME).spec @ADDITIONAL_FILES_TO_CLEAN @_
189
=item string = Glib::MakeHelper->postamble_docs (@xs_files)
191
NOTE: this is The Old Way. see L<postamble_docs_full> for The New Way.
193
Create and return the text of Makefile rules to build documentation from
194
the XS files with Glib::ParseXSDoc and Glib::GenPod.
196
Use this in your MY::postamble to enable autogeneration of POD.
198
This updates dependencies with the list of pod names generated by an earlier
199
run of C<do_pod_files>.
201
There is a special Makefile variable POD_DEPENDS that should be set to the
202
list of files that need to be created before the doc.pl step is run, include
205
There is also a variable BLIB_DONE which should be used as a dependency
206
anywhere a rule needs to be sure that a loadable and working module resides in
207
the blib directory before running.
213
my ($class, @xs_files) = @_;
214
return Glib::MakeHelper->postamble_docs_full (XS_FILES => \@xs_files);
217
=item string = Glib::MakeHelper->postamble_docs_full (...)
219
Create and return the text of Makefile rules to build documentation from
220
the XS files with Glib::ParseXSDoc and Glib::GenPod.
222
Use this in your MY::postamble to enable autogeneration of POD.
224
This updates dependencies with the list of pod names generated by an earlier
225
run of C<do_pod_files>.
227
There is a special Makefile variable POD_DEPENDS that should be set to the
228
list of files that need to be created before the doc.pl step is run, include
231
There is also a variable BLIB_DONE which should be used as a dependancy
232
anywhere a rule needs to be sure that a loadable and working module resides in
233
the blib directory before running.
235
The parameters are a list of key=>value pairs. You must specify at minimum
236
either DEPENDS or XS_FILES.
240
=item DEPENDS => ExtUtils::Depends object
242
Most gtk2-perl modules use ExtUtils::Depends to find headers, typemaps,
243
and other data from parent modules and to install this data for child
244
modules. We can find from this object the list of XS files to scan for
245
documentation, doctype mappings for parent modules, and other goodies.
247
=item XS_FILES => \@xs_file_names
249
A list of xs files to scan for documentation. Ignored if DEPENDS is
252
=item DOCTYPES => \@doctypes_file_names
254
List of filenames to pass to C<Glib::GenPod::add_types>. May be omitted.
256
=item COPYRIGHT => string
258
POD text to be inserted in the 'COPYRIGHT' section of each generated page.
261
=item COPYRIGHT_FROM => file name
263
The name of a file containing the POD to be inserted in the 'COPYRIGHT'
264
section of each generated page. May be omitted.
266
=item NAME => extension name
268
The name of the extension, used to set the main mod for Glib::GenPod (used in the
269
generated see-also listings). May be omitted in favor of the name held
270
inside the ExtUtils::Depends object. If DEPENDS is also specified, NAME wins.
276
sub postamble_docs_full {
277
my $class = shift; # package name
280
croak "Usage: $class\->postamble_docs_full (...)\n"
281
. " where ... is a list of key/value pairs including at the\n"
282
. " very least one of DEPENDS=>\$extutils_depends_object or\n"
283
. " XS_FILES=>\@xs_files\n"
285
unless $params{DEPENDS} or $params{XS_FILES};
293
if ($params{DOCTYPES}) {
294
@doctypes = ('ARRAY' eq ref $params{DOCTYPES})
295
? @{$params{DOCTYPES}}
296
: ($params{DOCTYPES});
299
if (UNIVERSAL::isa ($params{DEPENDS}, 'ExtUtils::Depends')) {
300
my $dep = $params{DEPENDS};
302
# fetch list of XS files from depends object.
303
# HACK ALERT: the older versions of ExtUtils::Depends
304
# (<0.2) use a different key layout and don't store enough
305
# metadata about the dependencies, so we require >=0.2;
306
# however, the older versions don't support import version
307
# checking (in fact they don't support version-checking at
308
# all), so the "use" test in a Makefile.PL can't tell if
309
# it has loaded a new enough version!
310
# the rewrite at version 0.200 added the get_dep() method,
311
# which we use, so let's check for that.
312
unless (defined &ExtUtils::Depends::get_deps) {
313
use ExtUtils::MakeMaker;
314
warn "ExtUtils::Depends is too old, need at "
315
. "least version 0.2";
316
# this is so that CPAN builds will do the upgrade
320
PREREQ_PM => { 'ExtUtils::Depends' => 0.2, },
322
exit 1; # not reached.
324
# continue with the excessive validation...
325
croak "value of DEPENDS key must be an ExtUtils::Depends object"
326
unless UNIVERSAL::isa $dep, 'ExtUtils::Depends';
327
croak "corrupt or invalid ExtUtils::Depends instance -- "
329
.(exists ($dep->{xs}) ? "missing" : "broken")."!"
330
unless exists $dep->{xs}
331
and 'ARRAY' eq ref $dep->{xs};
333
# finally, *this* is what we wanted.
334
@xs_files = @{$dep->{xs}};
336
# fetch doctypes files from the depends' dependencies.
337
my %deps = $dep->get_deps;
338
foreach my $d (keys %deps) {
339
my $f = File::Spec->catfile ($deps{$d}{instpath},
341
#warn "looking for $f\n";
346
# the depends object conveniently knows the main module name.
347
$name = $dep->{name};
349
@xs_files = @{ $params{XS_FILES} };
352
if ($params{COPYRIGHT}) {
353
$copyright = $params{COPYRIGHT};
354
} elsif ($params{COPYRIGHT_FROM}) {
355
open IN, $params{COPYRIGHT_FROM} or
356
croak "can't open $params{COPYRIGHT_FROM} for reading: $!\n";
363
# this text has to be escaped for both make and the shell.
364
$copyright =~ s/\n/\\n/gm; # collapse to one line.
365
$copyright =~ s|/|\\/|g; # escape slashes for qq//
366
$copyright = "Glib::GenPod::set_copyright(qq/$copyright/);";
369
# the module name specified explicitly overrides the one in a
371
$name = $params{NAME} if $params{NAME};
374
# this is supposed to be a module name; names don't have
375
# things in them that need escaping, so let's leave it alone.
376
# that way, if there's a quoting error, the user will figure
378
$name = "Glib::GenPod::set_main_mod(qq($name));";
381
#warn "".scalar(@doctypes)." doctype files\n";
382
#warn "".scalar(@xs_files)." xs files\n";
385
$add_types = 'add_types ('
386
. join(', ', map {'qq(' . quotemeta ($_) . ')'} @doctypes)
397
. 'xsdoc2pod(q(build/doc.pl), q($(INST_LIB)), q(build/podindex));';
399
#warn "docgen_code: $docgen_code\n";
401
# BLIB_DONE should be set to something we can depend on that will
402
# ensure that we are safe to link against an up to date module out
403
# of blib. basically what we need to wait on is the static/dynamic
404
# lib file to be created. the following trick is intended to handle
405
# both of those cases without causing the other to happen.
409
BLIB_DONE=build/blib_done_\$(LINKTYPE)
411
build/blib_done_dynamic :: \$(INST_DYNAMIC)
412
\$(NOECHO) \$(TOUCH) \$@
414
build/blib_done_static :: \$(INST_STATIC)
415
\$(NOECHO) \$(TOUCH) \$@
417
build/blib_done_ :: build/blib_done_dynamic
418
\$(NOECHO) \$(TOUCH) \$@
420
# documentation stuff
421
\$(INST_LIB)/Glib/GenPod.pm \$(INST_LIB)/Glib/ParseXSDoc.pm: pm_to_blib
423
build/doc.pl :: Makefile @xs_files
424
\$(NOECHO) \$(ECHO) Parsing XS files...
425
\$(NOECHO) $^X -I \$(INST_LIB) -I \$(INST_ARCHLIB) -MGlib::ParseXSDoc \\
426
-e "xsdocparse (qw(@xs_files))" > \$@
428
# passing all of these files through the single podindex file, which is
429
# created at the same time, prevents problems with -j4 where xsdoc2pod would
430
# have multiple instances
431
@gend_pods :: build/podindex
433
build/podindex :: \$(BLIB_DONE) Makefile build/doc.pl \$(POD_DEPENDS)
434
\$(NOECHO) \$(ECHO) Generating POD...
435
\$(NOECHO) $^X -I \$(INST_LIB) -I \$(INST_ARCHLIB) -MGlib::GenPod -M\$(NAME) \\
438
\$(INST_LIB)/\$(FULLEXT)/:
439
$^X -MExtUtils::Command -e mkpath \$@
441
\$(INST_LIB)/\$(FULLEXT)/index.pod :: \$(INST_LIB)/\$(FULLEXT)/ build/podindex
442
\$(NOECHO) \$(ECHO) Creating POD index...
443
\$(NOECHO) $^X -e "print qq(\\n=head1 NAME\\n\\n\$(NAME) \\\\- API Reference Pod Index\\n\\n=head1 PAGES\\n\\n=over\\n\\n)" \\
444
> \$(INST_LIB)/\$(FULLEXT)/index.pod
445
\$(NOECHO) $^X -ne "print q(=item L<) . (split q( ))[1] . qq(>\\n\\n);" < build/podindex >> \$(INST_LIB)/\$(FULLEXT)/index.pod
446
\$(NOECHO) $^X -e "print qq(=back\\n\\n);" >> \$(INST_LIB)/\$(FULLEXT)/index.pod
450
=item string = Glib::MakeHelper->postamble_rpms (HASH)
452
Create and return the text of Makefile rules to manage building RPMs.
453
You'd put this in your Makefile.PL's MY::postamble.
455
I<HASH> is a set of search and replace keys for the spec file. All
456
occurences of @I<key>@ in the spec file template perl-$(DISTNAME).spec.in
457
will be replaced with I<value>. 'VERSION' and 'SOURCE' are supplied for
460
Glib::MakeHelper->postamble_rpms (
461
MYLIB => 2.0.0, # we can work with anything from this up
462
MYLIB_RUN => 2.3.1, # we are actually compiled against this one
463
PERL_GLIB => 1.01, # you must have this version of Glib
466
will replace @MYLIB@, @MYLIB_RUN@, and @PERL_GLIB@ in spec file. See
467
the build setups for Glib and Gtk2 for examples.
469
Note: This function just returns an empty string on Win32.
475
shift; # package name
477
return '' unless $ENV{GPERL_BUILD_RPMS};
479
my @dirs = qw{$(RPMS_DIR) $(RPMS_DIR)/BUILD $(RPMS_DIR)/RPMS
480
$(RPMS_DIR)/SOURCES $(RPMS_DIR)/SPECS $(RPMS_DIR)/SRPMS};
483
chomp (my $date = `date +"%a %b %d %Y"`);
486
'VERSION' => '$(VERSION)',
487
'SOURCE' => '$(DISTNAME)-$(VERSION).tar.gz',
492
my $substitute = '$(PERL) -npe \''.join('; ', map {
493
"s/\\\@$_\\\@/$subs{$_}/g";
498
RPMS_DIR=\$(HOME)/rpms
503
SUBSTITUTE=$substitute
505
perl-\$(DISTNAME).spec :: perl-\$(DISTNAME).spec.in \$(VERSION_FROM) Makefile
506
\$(SUBSTITUTE) \$< > \$@
508
dist-rpms :: Makefile dist perl-\$(DISTNAME).spec \$(RPMS_DIR)/
509
cp \$(DISTNAME)-\$(VERSION).tar.gz \$(RPMS_DIR)/SOURCES/
510
rpmbuild -ba --define \"_topdir \$(RPMS_DIR)\" perl-\$(DISTNAME).spec
512
dist-srpms :: Makefile dist perl-\$(DISTNAME).spec \$(RPMS_DIR)/
513
cp \$(DISTNAME)-\$(VERSION).tar.gz \$(RPMS_DIR)/SOURCES/
514
rpmbuild -bs --nodeps --define \"_topdir \$(RPMS_DIR)\" perl-\$(DISTNAME).spec
518
=item string = Glib::MakeHelper->postamble_precompiled_headers (@headers)
520
Create and return the text of Makefile rules for a 'precompiled-headers' target
521
that precompiles I<@headers>. If you call this before you call
522
C<postamble_clean>, all temporary files will be removed by the 'realclean'
527
sub postamble_precompiled_headers
529
shift; # package name
531
my @precompiled_headers = ();
533
foreach my $header (@headers) {
534
my $output = $header . '.gch';
535
push @precompiled_headers, $output;
536
push @ADDITIONAL_FILES_TO_CLEAN, $output;
540
\$(CCCMD) \$(CCCDLFLAGS) "-I\$(PERL_INC)" \$(PASTHRU_DEFINE) \$(DEFINE) $header
545
precompiled-headers: @precompiled_headers
555
The MakeMaker distributed with perl 5.8.x generates makefiles with a bug that
556
causes object files to be created in the wrong directory. There is an override
557
inserted by this module under the name MY::const_cccmd to fix this issue.
562
my $inherited = shift->SUPER::const_cccmd (@_);
563
return '' unless $inherited;
565
# a more sophisticated match may be necessary, but this works for me.
566
if ($Config::Config{cc} eq "cl") {
567
$inherited .= ' /Fo$@';
569
$inherited .= ' -o $@';
575
# And, some black magick to help make learn to shut the hell up.
580
my @lines = split /\n/, $cmds;
585
s/^\t/\t\$(NOECHO) \$(ECHO) [ XS \$< ]\n\t\$(NOECHO) /;
587
s/^\t/\t\$(NOECHO) \$(ECHO) [ CC \$< ]\n\t\$(NOECHO) /;
589
s/^\t/\t\$(NOECHO) \$(ECHO) [ LD \$@ ]\n\t\$(NOECHO) /;
590
} elsif (/[_\b]AR\b/) {
591
s/^\t/\t\$(NOECHO) \$(ECHO) [ AR \$@ ]\n\t\$(NOECHO) /;
594
return join "\n", @lines;
597
sub c_o { return quiet_rule (shift->SUPER::c_o (@_)); }
598
sub xs_o { return quiet_rule (shift->SUPER::xs_o (@_)); }
599
sub xs_c { return quiet_rule (shift->SUPER::xs_c (@_)); }
600
sub dynamic_lib { return quiet_rule (shift->SUPER::dynamic_lib (@_)); }
601
sub static_lib { return quiet_rule (shift->SUPER::static_lib (@_)); }
607
Ross McFarland E<lt>rwmcfa1 at neces dot comE<gt>
609
hacked up and documented by muppet.
611
=head1 COPYRIGHT AND LICENSE
613
Copyright 2003-2004 by the gtk2-perl team
615
This library is free software; you can redistribute it and/or modify
616
it under the terms of the Lesser General Public License (LGPL). For
617
more information, see http://www.fsf.org/licenses/lgpl.txt