1 package Wx::build::MakeMaker;
4 use ExtUtils::MakeMaker;
7 use vars qw(@EXPORT $VERSION);
9 use File::Basename qw();
12 @EXPORT = 'wxWriteMakefile';
14 # get rid of suffix in MakeMaker version to be able treat it like a number in
16 my $MAKEMAKER_VERSION = $ExtUtils::MakeMaker::VERSION;
17 $MAKEMAKER_VERSION =~ s/_\d+$//;
19 # sanitize File::Find on filesystems where nlink of directories is < 2
21 $File::Find::dont_use_nlink = 1 if ( stat('.') )[3] < 2;
25 Wx::build::MakeMaker - ExtUtils::MakeMaker specialisation for wxPerl modules
29 use Wx::build::MakeMaker;
31 wxWriteMakefile( NAME => 'My::Module',
32 VERSION_FROM => 'Module.pm' );
36 =head2 wxWriteMakefile
38 wxWriteMakefile( arameter => value, ... );
40 This functions is meant to be used exactly as
41 ExtUtils::MakeMaker::WriteMakefile (see). It accepts all WriteMakefile's
48 WX_CORE_LIB => 'xrc core base'
50 link libraries from wxWidgets' core or contrib directory.
51 If not spedified, defaults to 'adv html core net base' for compatibility.
57 Link additional libraries from wxWidgets' contrib directory.
61 REQUIRE_WX => 2.003002 # wxWidgets 2.3.2
63 Do not build this module if wxWidgets' version is lower than the version
66 =item * NO_WX_PLATFORMS
68 NO_WX_PLATFORMS => [ 'x11', 'msw' ]
70 Do not build this module on the specified platform(s).
72 =item * ON_WX_PLATFORMs
74 ON_WX_PLATFORMS => [ 'gtk' ]
76 only build this module on the specified platform(s).
80 =head1 PRIVATE FUNCTIONS
82 These functions are here for reference, do not use them.
88 True if it is building the wxPerl core (Wx.dll), false otherwise.
92 if( is_wxPerl_tree ) { ... }
94 True if it is building any part of wxPerl, false otherwise.
98 my $is_wxperl_tree = 0;
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 }
104 # _call_method( 'method', $this, @args );
105 # calls the _core or _ext version of a method;
109 $name .= is_core ? '_core' : '_ext';
111 return $this->$name( @_ );
114 =head2 set_hook_package
116 Wx::build::MakeMaker::set_hook_package( 'package_name' );
118 Package to be hooked into the MakeMaker inheritance chain.
122 # this is the default
128 local $_ = $Config{osname};
132 local $_ = File::Basename::basename( $Config{cc} );
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;
138 die "Your compiler is not currently supported on Win32"
141 # MacOS X is slightly different...
143 $package_to_use = 'MacOSX_GCC';
148 $package_to_use = 'Any_wx_config';
151 $hook_package = 'Wx::build::MakeMaker::' . $package_to_use;
154 sub set_hook_package {
155 $hook_package = shift;
158 # this is a crude hack (at best), we put an arbitrary package
159 # into ExtUtils::MakeMaker inheritance chain in order to be able
163 *MY::libscan = _make_hook( 'libscan' );
165 Wx::build::MakeMaker->export_to_level( 1, @_ );
170 =head2 get_api_directory
172 my $dir = $cfg->get_api_directory;
174 =head2 get_arch_directory
176 my $dir = $cfg->get_arch_directory;
180 sub get_api_directory {
181 if( is_wxPerl_tree() ) {
182 return Wx::build::Utils::src_dir( 'Wx.pm' );
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 ) );
191 sub get_arch_directory {
192 if( is_wxPerl_tree() ) {
194 Carp::confess( "Should not be called!" );
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 ) );
204 my( $this, @libs ) = @_;
206 return eval { Alien::wxWidgets->libraries( @libs ); 1 } ? 1 : 0;
210 my( $this, @libs ) = @_;
212 return join ' ', Alien::wxWidgets->libraries( @libs );
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} }
226 my $hook_sub = shift;
230 my $class = ref $this;
231 ( my $file = $hook_package ) =~ s{::}{/}g;
234 undef *{"${class}::${hook_sub}"};
235 unshift @{"${class}::ISA"}, $hook_package;
237 shift->$hook_sub( @_ );
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);
246 sub _libs($) { ref( $_[0] ) ? @{$_[0]} : ( $_[0] ) }
248 # removes the -L/path from the imput and returns them and
251 my $str = shift || '';
252 my @paths = $str =~ m/(-L[^ ]+)/g;
253 $str =~ s/-L[^ ]+ +//g;
255 return ( $str, @paths );
259 my( $cfg1, $cfg2 ) = @_;
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...
269 my @a = _libs( $cfg{LIBS} );
270 my @b = _libs( $cfg2{LIBS} );
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 ";
285 if( $i eq 'clean' || $i eq 'realclean' ) {
286 $cfg{$i}{FILES} .= ' ' . $cfg{$i}{FILES};
290 if( ref($cfg{$i}) || ref($cfg2{$i}) ) {
291 die "non scalar key '$i' while merging configuration information";
292 $cfg{$i} = $cfg2{$i};
294 $cfg{$i} .= " $cfg2{$i}";
297 $cfg{$i} = $cfg2{$i};
305 ( my $file = $hook_package ) =~ s{::}{/}g;
309 require Alien::wxWidgets;
310 Alien::wxWidgets->VERSION( 0.04 );
314 my %cfg2 = _call_method( 'configure', $hook_package );
315 my %cfg = merge_config( \%cfg1, \%cfg2 );
325 my $full = "SUPER::$name";
329 *{"${name}_core"} = $sub;
330 *{"${name}_ext"} = $sub;
331 *{"${name}"} = sub { _call_method( $name, @_ ) };
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( @_ ) }
346 use vars qw(%args %additional_arguments $wx_top_file);
347 sub _process_mm_arguments {
348 my( $args, $has_alien ) = @_;
352 Wx::build::Options->get_makemaker_options( is_wxPerl_tree()
353 ? () : ( 'saved' ) );
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;
361 my $platform = Alien::wxWidgets->config->{toolkit};
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';
367 foreach ( keys %args ) {
370 m/^(NO|ON)_WX_PLATFORMS$/ and do {
374 # build if platform is explicitly listed
375 $build &&= grep { $_ eq $platform } @$v;
377 # build unless platform is explicitly listed
378 $build &&= !grep { $_ eq $platform } @$v;
384 m/^REQUIRE_WX$/ and do {
385 $build &&= __PACKAGE__->get_wx_version() >= $v;
389 m/^REQUIRE_WX_LIB$/ and do {
390 my @libs = split ' ', $v;
391 $build &&= __PACKAGE__->check_core_lib( @libs ) if $v=~/\S/;
396 return $build unless $build;
398 foreach ( keys %args ) {
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 : () );
410 m/^WX_CORE_LIB$/ and do {
411 my @libs = split ' ', $v;
412 $args{LIBS} .= ' ' . join ' ', __PACKAGE__->get_core_lib( @libs ) if $v=~/\S/;
417 die "Please use WX_CORE_LIB instead of WX_LIB";
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;
425 m/^(?:LICENSE)/ and do {
426 # args not known prior to MakeMaker 6.32
427 delete $args{$_} if $MAKEMAKER_VERSION < 6.32;
431 $wx_top_file = $args{$_};
435 $additional_arguments{$_} = delete $args{$_};
442 sub wxWriteMakefile {
446 my $has_alien = $Wx::build::MakeMaker::Core::has_alien;
447 $has_alien = defined( $has_alien ) ? $has_alien : 1;
449 $params{XSOPT} = ' -noprototypes' .
450 ( is_wxPerl_tree() ? ' -nolinenumbers ' : ' ' );
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();
459 my $build = Wx::build::MakeMaker::_process_mm_arguments( \%params, $has_alien );
462 WriteMakefile( %params );
464 ExtUtils::MakeMaker::WriteEmptyMakefile( %params );