Add libwx-perl
[pkg-perl] / deb-src / libwx-perl / libwx-perl-0.96 / debian / libwx-perl / usr / lib / perl5 / Wx / build / MakeMaker.pm
1 package Wx::build::MakeMaker;
2
3 use strict;
4 use ExtUtils::MakeMaker;
5 use base 'Exporter';
6 use Config;
7 use vars qw(@EXPORT $VERSION);
8 use FindBin;
9 use File::Basename qw();
10
11 $VERSION = '0.28';
12 @EXPORT = 'wxWriteMakefile';
13
14 # get rid of suffix in MakeMaker version to be able treat it like a number in
15 # comparisons
16 my $MAKEMAKER_VERSION = $ExtUtils::MakeMaker::VERSION;
17 $MAKEMAKER_VERSION =~ s/_\d+$//;
18
19 # sanitize File::Find on filesystems where nlink of directories is < 2
20 use File::Find;
21 $File::Find::dont_use_nlink = 1 if ( stat('.') )[3] < 2;
22
23 =head1 NAME
24
25 Wx::build::MakeMaker - ExtUtils::MakeMaker specialisation for wxPerl modules
26
27 =head1 SYNOPSIS
28
29 use Wx::build::MakeMaker;
30
31 wxWriteMakefile( NAME         => 'My::Module',
32                  VERSION_FROM => 'Module.pm' );
33
34 =head1 FUNCTIONS
35
36 =head2 wxWriteMakefile
37
38   wxWriteMakefile( arameter => value, ... );
39
40 This functions is meant to be used exactly as
41 ExtUtils::MakeMaker::WriteMakefile (see). It accepts all WriteMakefile's
42 parameters, plus:
43
44 =over 4
45
46 =item * WX_CORE_LIB
47
48   WX_CORE_LIB => 'xrc core base'
49
50 link libraries from wxWidgets' core or contrib directory.
51 If not spedified, defaults to 'adv html core net base' for compatibility.
52
53 =item * WX_LIB
54
55   WX_LIB => '-lxrc'
56
57 Link additional libraries from wxWidgets' contrib directory.
58
59 =item * REQUIRE_WX
60
61   REQUIRE_WX => 2.003002  # wxWidgets 2.3.2
62
63 Do not build this module if wxWidgets' version is lower than the version
64 specified.
65
66 =item * NO_WX_PLATFORMS
67
68   NO_WX_PLATFORMS => [ 'x11', 'msw' ]
69
70 Do not build this module on the specified platform(s).
71
72 =item * ON_WX_PLATFORMs
73
74   ON_WX_PLATFORMS => [ 'gtk' ]
75
76 only build this module on the specified platform(s).
77
78 =back
79
80 =head1 PRIVATE FUNCTIONS
81
82 These functions are here for reference, do not use them.
83
84 =head2 is_core
85
86   if( is_core ) { ... }
87
88 True if it is building the wxPerl core (Wx.dll), false otherwise.
89
90 =head2 is_wxPerl_tree
91
92   if( is_wxPerl_tree ) { ... }
93
94 True if it is building any part of wxPerl, false otherwise.
95
96 =cut
97
98 my $is_wxperl_tree = 0;
99
100 sub is_core() { -f 'Wx.pm' }
101 sub _set_is_wxPerl_tree { $is_wxperl_tree = $_[0] ? 1 : 0 }
102 sub is_wxPerl_tree { $is_wxperl_tree }
103
104 #   _call_method( 'method', $this, @args );
105 # calls the _core or _ext version of a method;
106 sub _call_method {
107   my $name = shift;
108   my $this = shift;
109   $name .= is_core ? '_core' : '_ext';
110
111   return $this->$name( @_ );
112 }
113
114 =head2 set_hook_package
115
116   Wx::build::MakeMaker::set_hook_package( 'package_name' );
117
118 Package to be hooked into the MakeMaker inheritance chain.
119
120 =cut
121
122 # this is the default
123 my $hook_package;
124
125 BEGIN {
126   my $package_to_use;
127  SWITCH: {
128     local $_ = $Config{osname};
129
130     # Win32
131     m/MSWin32/ and do {
132       local $_ = File::Basename::basename( $Config{cc} );
133
134       m/^cl/i  and $package_to_use = 'Win32_MSVC'  and last SWITCH;
135       m/^gcc/i and $package_to_use = 'Win32_MinGW' and last SWITCH;
136
137       # default
138       die "Your compiler is not currently supported on Win32"
139     };
140
141     # MacOS X is slightly different...
142     m/darwin/ and do {
143       $package_to_use = 'MacOSX_GCC';
144       last SWITCH;
145     };
146
147     # default
148     $package_to_use = 'Any_wx_config';
149     last SWITCH;
150   }
151   $hook_package = 'Wx::build::MakeMaker::' . $package_to_use;
152 }
153
154 sub set_hook_package {
155   $hook_package = shift;
156 }
157
158 # this is a crude hack (at best), we put an arbitrary package
159 # into ExtUtils::MakeMaker inheritance chain in order to be able
160 # to customise it
161 sub import {
162   undef *MY::libscan;
163   *MY::libscan = _make_hook( 'libscan' );
164
165   Wx::build::MakeMaker->export_to_level( 1, @_ );
166 }
167
168 =head1 METHODS
169
170 =head2 get_api_directory
171
172   my $dir = $cfg->get_api_directory;
173
174 =head2 get_arch_directory
175
176   my $dir = $cfg->get_arch_directory;
177
178 =cut
179
180 sub get_api_directory {
181   if( is_wxPerl_tree() ) {
182     return Wx::build::Utils::src_dir( 'Wx.pm' );
183   } else {
184     my $path = $INC{'Wx/build/MakeMaker.pm'};
185     my( $vol, $dir, $file ) = File::Spec->splitpath( $path );
186     my @dirs = File::Spec->splitdir( $dir ); pop @dirs; pop @dirs;
187     return File::Spec->catpath( $vol, File::Spec->catdir( @dirs ) );
188   }
189 }
190
191 sub get_arch_directory {
192   if( is_wxPerl_tree() ) {
193     require Carp;
194     Carp::confess( "Should not be called!" );
195   } else {
196     my $path = $INC{'Wx/build/Opt.pm'};
197     my( $vol, $dir, $file ) = File::Spec->splitpath( $path );
198     my @dirs = File::Spec->splitdir( $dir ); pop @dirs; pop @dirs; pop @dirs;
199     return File::Spec->catpath( $vol, File::Spec->catdir( @dirs ) );
200   }
201 }
202
203 sub check_core_lib {
204   my( $this, @libs ) = @_;
205
206   return eval { Alien::wxWidgets->libraries( @libs ); 1 } ? 1 : 0;
207 }
208
209 sub get_core_lib {
210   my( $this, @libs ) = @_;
211
212   return join ' ', Alien::wxWidgets->libraries( @libs );
213 }
214
215 our $is_core = 0;
216
217 sub get_wx_platform { Alien::wxWidgets->config->{toolkit} }
218 sub get_wx_version { Alien::wxWidgets->version }
219 sub _unicode { Alien::wxWidgets->config->{unicode} }
220 sub _mslu    { Alien::wxWidgets->config->{mslu} }
221 sub _debug   { Alien::wxWidgets->config->{debug} }
222 sub _core    { $is_core }
223 sub _static  { Alien::wxWidgets->config->{static} }
224
225 sub _make_hook {
226   my $hook_sub = shift;
227
228   return sub {
229     my $this = $_[0];
230     my $class = ref $this;
231     ( my $file = $hook_package ) =~ s{::}{/}g;
232     no strict 'refs';
233     require "$file.pm";
234     undef *{"${class}::${hook_sub}"};
235     unshift @{"${class}::ISA"}, $hook_package;
236
237     shift->$hook_sub( @_ );
238   }
239 }
240
241 # this method calls ->configure
242 # in the appropriate Wx::build::MakeMaker::PACKAGE,
243 # and merges the results with its inputs
244 use vars qw(%cfg1 %cfg2);
245
246 sub _libs($) { ref( $_[0] ) ? @{$_[0]} : ( $_[0] ) }
247
248 # removes the -L/path from the imput and returns them and
249 # the cleaned input
250 sub _split_lib($) {
251   my $str = shift || '';
252   my @paths = $str =~ m/(-L[^ ]+)/g;
253   $str =~ s/-L[^ ]+ +//g;
254
255   return ( $str, @paths );
256 }
257
258 sub merge_config {
259   my( $cfg1, $cfg2 ) = @_;
260   local *cfg1 = $cfg1;
261   local *cfg2 = $cfg2;
262   my %cfg = %cfg1;
263
264   foreach my $i ( keys %cfg2 ) {
265     if( exists $cfg{$i} ) {
266       # merging libraries is always a mess; the hope is that
267       # this will work in all cases, but there are no guarantees...
268       if( $i eq 'LIBS' ) {
269         my @a = _libs(  $cfg{LIBS} );
270         my @b = _libs( $cfg2{LIBS} );
271
272         my @c;
273         foreach my $i ( @b ) {
274           my( $mi, @ipaths ) = _split_lib( $i );
275           foreach my $j ( @a ) {
276             my( $mj, @jpaths ) = _split_lib( $j );
277             push @c, " @ipaths @jpaths $mj $mi ";
278           }
279         }
280
281         $cfg{LIBS} = \@c;
282         next;
283       }
284
285       if( $i eq 'clean' || $i eq 'realclean' ) {
286         $cfg{$i}{FILES} .= ' ' . $cfg{$i}{FILES};
287         next;
288       }
289
290       if( ref($cfg{$i}) || ref($cfg2{$i}) ) {
291         die "non scalar key '$i' while merging configuration information";
292         $cfg{$i} = $cfg2{$i};
293       } else {
294         $cfg{$i} .= " $cfg2{$i}";
295       }
296     } else {
297       $cfg{$i} = $cfg2{$i};
298     }
299   }
300
301   return %cfg;
302 }
303
304 sub configure {
305   ( my $file = $hook_package ) =~ s{::}{/}g;
306   require "$file.pm";
307
308   # do it at runtime
309   require Alien::wxWidgets;
310   Alien::wxWidgets->VERSION( 0.04 );
311
312   my $this = $_[0];
313   my %cfg1 = %{$_[1]};
314   my %cfg2 = _call_method( 'configure', $hook_package );
315   my %cfg = merge_config( \%cfg1, \%cfg2 );
316
317   return \%cfg;
318 }
319
320 sub _make_override {
321   my $name = shift;
322   my $sub = sub {
323     package MY;
324     my $this = shift;
325     my $full = "SUPER::$name";
326     $this->$full( @_ );
327   };
328   no strict 'refs';
329   *{"${name}_core"} = $sub;
330   *{"${name}_ext"}  = $sub;
331   *{"${name}"}      = sub { _call_method( $name, @_ ) };
332 }
333
334 _make_override( 'subdirs' );
335 _make_override( 'postamble' );
336 _make_override( 'depend' );
337 _make_override( 'install' );
338 _make_override( 'libscan' );
339 _make_override( 'constants' );
340 _make_override( 'metafile_target' );
341 _make_override( 'manifypods' );
342 sub ppd { package MY; shift->SUPER::ppd( @_ ) }
343 sub dynamic_lib { package MY; shift->SUPER::dynamic_lib( @_ ) }
344 sub const_config { package MY; shift->SUPER::const_config( @_ ) }
345
346 use vars qw(%args %additional_arguments $wx_top_file);
347 sub _process_mm_arguments {
348   my( $args, $has_alien ) = @_;
349   local *args = $args;
350   my $build = 1;
351   my %options =
352     Wx::build::Options->get_makemaker_options( is_wxPerl_tree()
353                                                ? () : ( 'saved' ) );
354
355   $additional_arguments{WX_TOP} = $wx_top_file if $wx_top_file;
356   unless( $has_alien ) {
357       $args{depend} = { '$(FIRST_MAKEFILE)' => 'alien_wxwidgets_missing' };
358       delete $args{$_} foreach grep /WX_|_WX/, keys %args;
359       return 1;
360   }
361   my $platform = Alien::wxWidgets->config->{toolkit};
362
363   $args{CCFLAGS} .= $options{extra_cflags} ? ' ' . $options{extra_cflags} : '';
364   $args{LIBS} .=  $options{extra_libs} ? ' ' . $options{extra_libs} : '';
365   $args{WX_CORE_LIB} ||= 'adv html core net base';
366
367   foreach ( keys %args ) {
368     my $v = $args{$_};
369
370     m/^(NO|ON)_WX_PLATFORMS$/ and do {
371       my $on = $1 eq 'ON';
372
373       if( $on ) {
374         # build if platform is explicitly listed
375         $build &&= grep { $_ eq $platform } @$v;
376       } else {
377         # build unless platform is explicitly listed
378         $build &&= !grep { $_ eq $platform } @$v;
379       }
380
381       delete $args{$_};
382     };
383
384     m/^REQUIRE_WX$/ and do {
385       $build &&= __PACKAGE__->get_wx_version() >= $v;
386       delete $args{$_};
387     };
388
389     m/^REQUIRE_WX_LIB$/ and do {
390       my @libs = split ' ', $v;
391       $build &&= __PACKAGE__->check_core_lib( @libs ) if $v=~/\S/;
392       delete $args{$_};
393     };
394   }
395
396   return $build unless $build;
397
398   foreach ( keys %args ) {
399     my $v = $args{$_};
400
401     m/^WX_CORE_LIB_MAYBE$/ and do {
402       my @libs = split ' ', $v;
403       $args{LIBS} .= ' ' . join ' ',
404                            map  { __PACKAGE__->get_core_lib( $_ ) }
405                            grep { __PACKAGE__->check_core_lib( $_ ) }
406                                 ( $v=~/\S/ ? @libs : () );
407       delete $args{$_};
408     };
409
410     m/^WX_CORE_LIB$/ and do {
411       my @libs = split ' ', $v;
412       $args{LIBS} .= ' ' . join ' ', __PACKAGE__->get_core_lib( @libs ) if $v=~/\S/;
413       delete $args{$_};
414     };
415
416     m/^WX_LIB$/ and do {
417       die "Please use WX_CORE_LIB instead of WX_LIB";
418     };
419
420     m/^(?:ABSTRACT_FROM|AUTHOR)/ and do {
421       # args not known prior to Perl 5.005_03 (the check is a bit conservative)
422       delete $args{$_} if $MAKEMAKER_VERSION < 5.43;
423     };
424
425     m/^(?:LICENSE)/ and do {
426       # args not known prior to MakeMaker 6.32
427       delete $args{$_} if $MAKEMAKER_VERSION < 6.32;
428     };
429
430     m/^WX_TOP$/ and do {
431       $wx_top_file = $args{$_};
432     };
433
434     m/^WX_/ and do {
435       $additional_arguments{$_} = delete $args{$_};
436     };
437   }
438
439   return $build;
440 }
441
442 sub wxWriteMakefile {
443   my %params = @_;
444   local $is_core = 0;
445
446   my $has_alien = $Wx::build::MakeMaker::Core::has_alien;
447   $has_alien = defined( $has_alien ) ? $has_alien : 1;
448
449   $params{XSOPT}     = ' -noprototypes' .
450     ( is_wxPerl_tree() ? ' -nolinenumbers ' : ' ' );
451   if( $has_alien ) {
452     $params{CONFIGURE} = \&Wx::build::MakeMaker::configure;
453     require Wx::build::MakeMaker::Any_OS;
454     push @{$params{TYPEMAPS} ||= []},
455       File::Spec->catfile( __PACKAGE__->get_api_directory, 'typemap' );
456     ( $params{PREREQ_PM} ||= {} )->{Wx} ||= '0.19' unless is_wxPerl_tree();
457   }
458
459   my $build = Wx::build::MakeMaker::_process_mm_arguments( \%params, $has_alien );
460
461   if( $build ) {
462     WriteMakefile( %params );
463   } else {
464     ExtUtils::MakeMaker::WriteEmptyMakefile( %params );
465   }
466 }
467
468 1;
469
470 # local variables:
471 # mode: cperl
472 # end: