Add built local::lib
[catagits/Gitalist.git] / local-lib5 / lib / perl5 / ExtUtils / Depends.pm
CommitLineData
3fea05b9 1#
2# $Id$
3#
4
5package ExtUtils::Depends;
6
7use strict;
8use warnings;
9use Carp;
10use File::Find;
11use File::Spec;
12use Data::Dumper;
13
14our $VERSION = '0.302';
15
16sub import {
17 my $class = shift;
18 return unless @_;
19 die "$class version $_[0] is required--this is only version $VERSION"
20 if $VERSION < $_[0];
21}
22
23sub new {
24 my ($class, $name, @deps) = @_;
25 my $self = bless {
26 name => $name,
27 deps => {},
28 inc => [],
29 libs => '',
30
31 pm => {},
32 typemaps => [],
33 xs => [],
34 c => [],
35 }, $class;
36
37 $self->add_deps (@deps);
38
39 # attempt to load these now, so we'll find out as soon as possible
40 # whether the dependencies are valid. we'll load them again in
41 # get_makefile_vars to catch any added between now and then.
42 $self->load_deps;
43
44 return $self;
45}
46
47sub add_deps {
48 my $self = shift;
49 foreach my $d (@_) {
50 $self->{deps}{$d} = undef
51 unless $self->{deps}{$d};
52 }
53}
54
55sub get_deps {
56 my $self = shift;
57 $self->load_deps; # just in case
58
59 return %{$self->{deps}};
60}
61
62sub set_inc {
63 my $self = shift;
64 push @{ $self->{inc} }, @_;
65}
66
67sub set_libs {
68 my ($self, $newlibs) = @_;
69 $self->{libs} = $newlibs;
70}
71
72sub add_pm {
73 my ($self, %pm) = @_;
74 while (my ($key, $value) = each %pm) {
75 $self->{pm}{$key} = $value;
76 }
77}
78
79sub _listkey_add_list {
80 my ($self, $key, @list) = @_;
81 $self->{$key} = [] unless $self->{$key};
82 push @{ $self->{$key} }, @list;
83}
84
85sub add_xs { shift->_listkey_add_list ('xs', @_) }
86sub add_c { shift->_listkey_add_list ('c', @_) }
87sub add_typemaps {
88 my $self = shift;
89 $self->_listkey_add_list ('typemaps', @_);
90 $self->install (@_);
91}
92
93# no-op, only used for source back-compat
94sub add_headers { carp "add_headers() is a no-op" }
95
96####### PRIVATE
97sub basename { (File::Spec->splitdir ($_[0]))[-1] }
98# get the name in Makefile syntax.
99sub installed_filename {
100 my $self = shift;
101 return '$(INST_ARCHLIB)/$(FULLEXT)/Install/'.basename ($_[0]);
102}
103
104sub install {
105 # install things by adding them to the hash of pm files that gets
106 # passed through WriteMakefile's PM key.
107 my $self = shift;
108 foreach my $f (@_) {
109 $self->add_pm ($f, $self->installed_filename ($f));
110 }
111}
112
113sub save_config {
114 use Data::Dumper;
115 use IO::File;
116
117 my ($self, $filename) = @_;
118
119 my $file = IO::File->new (">".$filename)
120 or croak "can't open '$filename' for writing: $!\n";
121
122 print $file "package $self->{name}\::Install::Files;\n\n";
123 # for modern stuff
124 print $file "".Data::Dumper->Dump([{
125 inc => join (" ", @{ $self->{inc} }),
126 libs => $self->{libs},
127 typemaps => [ map { basename $_ } @{ $self->{typemaps} } ],
128 deps => [keys %{ $self->{deps} }],
129 }], ['self']);
130 # for ancient stuff
131 print $file "\n\n# this is for backwards compatiblity\n";
132 print $file "\@deps = \@{ \$self->{deps} };\n";
133 print $file "\@typemaps = \@{ \$self->{typemaps} };\n";
134 print $file "\$libs = \$self->{libs};\n";
135 print $file "\$inc = \$self->{inc};\n";
136 # this is riduculous, but old versions of ExtUtils::Depends take
137 # first $loadedmodule::CORE and then $INC{$file} --- the fallback
138 # includes the Filename.pm, which is not useful. so we must add
139 # this crappy code. we don't worry about portable pathnames,
140 # as the old code didn't either.
141 (my $mdir = $self->{name}) =~ s{::}{/}g;
142 print $file <<"EOT";
143
144 \$CORE = undef;
145 foreach (\@INC) {
146 if ( -f \$_ . "/$mdir/Install/Files.pm") {
147 \$CORE = \$_ . "/$mdir/Install/";
148 last;
149 }
150 }
151EOT
152
153 print $file "\n1;\n";
154
155 close $file;
156
157 # we need to ensure that the file we just created gets put into
158 # the install dir with everything else.
159 #$self->install ($filename);
160 $self->add_pm ($filename, $self->installed_filename ('Files.pm'));
161}
162
163sub load {
164 my $dep = shift;
165 my @pieces = split /::/, $dep;
166 my @suffix = qw/ Install Files /;
167 my $relpath = File::Spec->catfile (@pieces, @suffix) . '.pm';
168 my $depinstallfiles = join "::", @pieces, @suffix;
169 eval {
170 require $relpath
171 } or die " *** Can't load dependency information for $dep:\n $@\n";
172 #
173 #print Dumper(\%INC);
174
175 # effectively $instpath = dirname($INC{$relpath})
176 @pieces = File::Spec->splitdir ($INC{$relpath});
177 pop @pieces;
178 my $instpath = File::Spec->catdir (@pieces);
179
180 no strict;
181
182 croak "No dependency information found for $dep"
183 unless $instpath;
184
185 if (not File::Spec->file_name_is_absolute ($instpath)) {
186 $instpath = File::Spec->rel2abs ($instpath);
187 }
188
189 my @typemaps = map {
190 File::Spec->rel2abs ($_, $instpath)
191 } @{"$depinstallfiles\::typemaps"};
192
193 {
194 instpath => $instpath,
195 typemaps => \@typemaps,
196 inc => "-I$instpath ".${"$depinstallfiles\::inc"},
197 libs => ${"$depinstallfiles\::libs"},
198 # this will not exist when loading files from old versions
199 # of ExtUtils::Depends.
200 (exists ${"$depinstallfiles\::"}{deps}
201 ? (deps => \@{"$depinstallfiles\::deps"})
202 : ()),
203 }
204}
205
206sub load_deps {
207 my $self = shift;
208 my @load = grep { not $self->{deps}{$_} } keys %{ $self->{deps} };
209 foreach my $d (@load) {
210 my $dep = load ($d);
211 $self->{deps}{$d} = $dep;
212 if ($dep->{deps}) {
213 foreach my $childdep (@{ $dep->{deps} }) {
214 push @load, $childdep
215 unless
216 $self->{deps}{$childdep}
217 or
218 grep {$_ eq $childdep} @load;
219 }
220 }
221 }
222}
223
224sub uniquify {
225 my %seen;
226 # we use a seen hash, but also keep indices to preserve
227 # first-seen order.
228 my $i = 0;
229 foreach (@_) {
230 $seen{$_} = ++$i
231 unless exists $seen{$_};
232 }
233 #warn "stripped ".(@_ - (keys %seen))." redundant elements\n";
234 sort { $seen{$a} <=> $seen{$b} } keys %seen;
235}
236
237
238sub get_makefile_vars {
239 my $self = shift;
240
241 # collect and uniquify things from the dependencies.
242 # first, ensure they are completely loaded.
243 $self->load_deps;
244
245 ##my @defbits = map { split } @{ $self->{defines} };
246 my @incbits = map { split } @{ $self->{inc} };
247 my @libsbits = split /\s+/, $self->{libs};
248 my @typemaps = @{ $self->{typemaps} };
249 foreach my $d (keys %{ $self->{deps} }) {
250 my $dep = $self->{deps}{$d};
251 #push @defbits, @{ $dep->{defines} };
252 push @incbits, @{ $dep->{defines} } if $dep->{defines};
253 push @incbits, split /\s+/, $dep->{inc} if $dep->{inc};
254 push @libsbits, split /\s+/, $dep->{libs} if $dep->{libs};
255 push @typemaps, @{ $dep->{typemaps} } if $dep->{typemaps};
256 }
257
258 # we have a fair bit of work to do for the xs files...
259 my @clean = ();
260 my @OBJECT = ();
261 my %XS = ();
262 foreach my $xs (@{ $self->{xs} }) {
263 (my $c = $xs) =~ s/\.xs$/\.c/i;
264 (my $o = $xs) =~ s/\.xs$/\$(OBJ_EXT)/i;
265 $XS{$xs} = $c;
266 push @OBJECT, $o;
267 # according to the MakeMaker manpage, the C files listed in
268 # XS will be added automatically to the list of cleanfiles.
269 push @clean, $o;
270 }
271
272 # we may have C files, as well:
273 foreach my $c (@{ $self->{c} }) {
274 (my $o = $c) =~ s/\.c$/\$(OBJ_EXT)/i;
275 push @OBJECT, $o;
276 push @clean, $o;
277 }
278
279 my %vars = (
280 INC => join (' ', uniquify @incbits),
281 LIBS => join (' ', uniquify $self->find_extra_libs, @libsbits),
282 TYPEMAPS => [@typemaps],
283 );
284
285 $self->build_dll_lib(\%vars) if $^O =~ /MSWin32/;
286
287 # we don't want to provide these if there is no data in them;
288 # that way, the caller can still get default behavior out of
289 # MakeMaker when INC, LIBS and TYPEMAPS are all that are required.
290 $vars{PM} = $self->{pm}
291 if %{ $self->{pm} };
292 $vars{clean} = { FILES => join (" ", @clean), }
293 if @clean;
294 $vars{OBJECT} = join (" ", @OBJECT)
295 if @OBJECT;
296 $vars{XS} = \%XS
297 if %XS;
298
299 %vars;
300}
301
302sub build_dll_lib {
303 my ($self, $vars) = @_;
304 $vars->{macro} ||= {};
305 $vars->{macro}{'INST_DYNAMIC_LIB'} =
306 '$(INST_ARCHAUTODIR)/$(BASEEXT)$(LIB_EXT)';
307}
308
309sub find_extra_libs {
310 my $self = shift;
311
312 my %mappers = (
313 MSWin32 => sub { $_[0] . '\.(?:lib|a)' },
314 cygwin => sub { $_[0] . '\.dll'},
315 );
316 my $mapper = $mappers{$^O};
317 return () unless defined $mapper;
318
319 my @found_libs = ();
320 foreach my $name (keys %{ $self->{deps} }) {
321 (my $stem = $name) =~ s/^.*:://;
322 my $lib = $mapper->($stem);
323 my $pattern = qr/$lib$/;
324
325 my $matching_dir;
326 my $matching_file;
327 find (sub {
328 if ((not $matching_file) && /$pattern/) {;
329 $matching_dir = $File::Find::dir;
330 $matching_file = $File::Find::name;
331 }
332 }, map { -d $_ ? ($_) : () } @INC); # only extant dirs
333
334 if ($matching_file && -f $matching_file) {
335 push @found_libs, ('-L' . $matching_dir, '-l' . $stem);
336 next;
337 }
338 }
339
340 return @found_libs;
341}
342
343# Hook into ExtUtils::MakeMaker to create an import library on MSWin32 when gcc
344# is used. FIXME: Ideally, this should be done in EU::MM itself.
345package # wrap to fool the CPAN indexer
346 ExtUtils::MM;
347use Config;
348sub static_lib {
349 my $base = shift->SUPER::static_lib(@_);
350
351 return $base unless $^O =~ /MSWin32/ && $Config{cc} =~ /^gcc/i;
352
353 return <<'__EOM__';
354# This isn't actually a static lib, it just has the same name on Win32.
355$(INST_DYNAMIC_LIB): $(INST_DYNAMIC)
356 dlltool --def $(EXPORT_LIST) --output-lib $@ --dllname $(BASEEXT).$(SO) $(INST_DYNAMIC)
357
358dynamic:: $(INST_DYNAMIC_LIB)
359__EOM__
360}
361
3621;
363
364__END__
365
366=head1 NAME
367
368ExtUtils::Depends - Easily build XS extensions that depend on XS extensions
369
370=head1 SYNOPSIS
371
372 use ExtUtils::Depends;
373 $package = new ExtUtils::Depends ('pkg::name', 'base::package')
374 # set the flags and libraries to compile and link the module
375 $package->set_inc("-I/opt/blahblah");
376 $package->set_libs("-lmylib");
377 # add a .c and an .xs file to compile
378 $package->add_c('code.c');
379 $package->add_xs('module-code.xs');
380 # add the typemaps to use
381 $package->add_typemaps("typemap");
382 # install some extra data files and headers
383 $package->install (qw/foo.h data.txt/);
384 # save the info
385 $package->save_config('Files.pm');
386
387 WriteMakefile(
388 'NAME' => 'Mymodule',
389 $package->get_makefile_vars()
390 );
391
392=head1 DESCRIPTION
393
394This module tries to make it easy to build Perl extensions that use
395functions and typemaps provided by other perl extensions. This means
396that a perl extension is treated like a shared library that provides
397also a C and an XS interface besides the perl one.
398
399This works as long as the base extension is loaded with the RTLD_GLOBAL
400flag (usually done with a
401
402 sub dl_load_flags {0x01}
403
404in the main .pm file) if you need to use functions defined in the module.
405
406The basic scheme of operation is to collect information about a module
407in the instance, and then store that data in the Perl library where it
408may be retrieved later. The object can also reformat this information
409into the data structures required by ExtUtils::MakeMaker's WriteMakefile
410function.
411
412When creating a new Depends object, you give it a name, which is the name
413of the module you are building. You can also specify the names of modules
414on which this module depends. These dependencies will be loaded
415automatically, and their typemaps, header files, etc merged with your new
416object's stuff. When you store the data for your object, the list of
417dependencies are stored with it, so that another module depending on your
418needn't know on exactly which modules yours depends.
419
420For example:
421
422 Gtk2 depends on Glib
423
424 Gnome2::Canvas depends on Gtk2
425
426 ExtUtils::Depends->new ('Gnome2::Canvas', 'Gtk2');
427 this command automatically brings in all the stuff needed
428 for Glib, since Gtk2 depends on it.
429
430
431=head1 METHODS
432
433=over
434
435=item $object = ExtUtils::Depends->new($name, @deps)
436
437Create a new depends object named I<$name>. Any modules listed in I<@deps>
438(which may be empty) are added as dependencies and their dependency
439information is loaded. An exception is raised if any dependency information
440cannot be loaded.
441
442=item $depends->add_deps (@deps)
443
444Add modules listed in I<@deps> as dependencies.
445
446=item (hashes) = $depends->get_deps
447
448Fetch information on the dependencies of I<$depends> as a hash of hashes,
449which are dependency information indexed by module name. See C<load>.
450
451=item $depends->set_inc (@newinc)
452
453Add strings to the includes or cflags variables.
454
455=item $depends->set_libs (@newlibs)
456
457Add strings to the libs (linker flags) variable.
458
459=item $depends->add_pm (%pm_files)
460
461Add files to the hash to be passed through ExtUtils::WriteMakefile's
462PM key.
463
464=item $depends->add_xs (@xs_files)
465
466Add xs files to be compiled.
467
468=item $depends->add_c (@c_files)
469
470Add C files to be compiled.
471
472=item $depends->add_typemaps (@typemaps)
473
474Add typemap files to be used and installed.
475
476=item $depends->add_headers (list)
477
478No-op, for backward compatibility.
479
480=item $depends->install (@files)
481
482Install I<@files> to the data directory for I<$depends>.
483
484This actually works by adding them to the hash of pm files that gets
485passed through WriteMakefile's PM key.
486
487=item $depends->save_config ($filename)
488
489Save the important information from I<$depends> to I<$filename>, and
490set it up to be installed as I<name>::Install::Files.
491
492Note: the actual value of I<$filename> seems to be irrelevant, but its
493usage is kept for backward compatibility.
494
495=item hash = $depends->get_makefile_vars
496
497Return the information in I<$depends> in a format digestible by
498WriteMakefile.
499
500This sets at least the following keys:
501
502 INC
503 LIBS
504 TYPEMAPS
505 PM
506
507And these if there is data to fill them:
508
509 clean
510 OBJECT
511 XS
512
513=item hashref = ExtUtils::Depends::load (name)
514
515Load and return dependency information for I<name>. Croaks if no such
516information can be found. The information is returned as an anonymous
517hash containing these keys:
518
519=over
520
521=item instpath
522
523The absolute path to the data install directory for this module.
524
525=item typemaps
526
527List of absolute pathnames for this module's typemap files.
528
529=item inc
530
531CFLAGS string for this module.
532
533=item libs
534
535LIBS string for this module.
536
537=item deps
538
539List of modules on which this one depends. This key will not exist when
540loading files created by old versions of ExtUtils::Depends.
541
542=back
543
544=item $depends->load_deps
545
546Load I<$depends> dependencies, by calling C<load> on each dependency module.
547This is usually done for you, and should only be needed if you want to call
548C<get_deps> after calling C<add_deps> manually.
549
550=back
551
552
553=head1 BUGS
554
555Version 0.2 discards some of the more esoteric features provided by the
556older versions. As they were completely undocumented, and this module
557has yet to reach 1.0, this may not exactly be a bug.
558
559This module is tightly coupled to the ExtUtils::MakeMaker architecture.
560
561=head1 SEE ALSO
562
563ExtUtils::MakeMaker.
564
565=head1 AUTHOR
566
567Paolo Molaro <lupus at debian dot org> wrote the original version for
568Gtk-Perl. muppet <scott at asofyet dot org> rewrote the innards for
569version 0.2, borrowing liberally from Paolo's code.
570
571=head1 MAINTAINER
572
573The Gtk2 project, http://gtk2-perl.sf.net/
574
575=head1 LICENSE
576
577This library is free software; you may redistribute it and/or modify it
578under the same terms as Perl itself.
579
580=cut
581