1 package My::Build::Base;
4 use base qw(Module::Build);
5 use My::Build::Utility qw(awx_arch_file awx_touch);
6 use Alien::wxWidgets::Utility qw(awx_sort_config awx_grep_config);
9 use Fatal qw(open close unlink);
11 use File::Glob qw(bsd_glob);
15 # try to make "perl Makefile.PL && make test" work
16 # but avoid doubly building wxWidgets when doing
17 # "perl Makefile.PL && make && make test"
18 unlink 'configured' if -f 'configured';
19 $self->SUPER::ACTION_build;
25 $self->SUPER::ACTION_code;
26 # install_only is set when a wxWidgets build is already configured
27 # with Alien::wxWidgets
28 return if $self->notes( 'install_only' );
29 # see comment in ACTION_build for why 'configured' is used
30 return if -f 'configured';
31 $self->depends_on( 'build_wx' );
32 $self->create_config_file( awx_arch_file( 'Config/Config.pm' ) );
33 $self->install_wxwidgets;
34 # see comment in ACTION_build for why 'configured' is used
35 awx_touch( 'configured' );
36 $self->add_to_cleanup( 'configured' );
42 if( $self->notes( 'build_wx' ) ) {
43 $self->fetch_wxwidgets;
44 $self->extract_wxwidgets;
45 $self->massage_environment;
46 $self->build_wxwidgets;
47 $self->massage_environment; # twice on purpose
51 sub ACTION_build_perl {
54 $self->SUPER::ACTION_build;
55 $self->massage_environment;
56 $self->create_config_file( awx_arch_file( 'Config/Config.pm' ) );
59 sub ACTION_install_wx {
62 $self->depends_on( 'build_perl' );
63 $self->install_wxwidgets;
69 $self->SUPER::ACTION_install;
70 $self->install_system_wxwidgets;
73 sub ACTION_distcheck {
75 my $data = $self->notes( 'build_data' );
77 foreach my $p ( qw(msw mac unix) ) {
78 next unless exists $data->{$p};
80 foreach my $c ( qw(unicode ansi) ) {
81 next unless exists $data->{$p}{$c};
83 foreach my $f ( @{$data->{$p}{$c}} ) {
84 my $file = File::Spec->catfile( 'patches', $f );
86 warn 'Missing patch file: ', $file, "\n" unless -f $file;
91 $self->SUPER::ACTION_distcheck;
97 die unless $self->{awx_key};
99 return $self->{awx_key};
103 my( $class, $ver ) = @_;
106 $ver =~ m/^(\d)(\d)$/ and
107 $dec = $1 + $2 / 1000;
108 $ver =~ m/^(\d)(\d)(\d+)$/ and
109 $dec = $1 + $2 / 1000 + $3 / 1000000;
110 $ver =~ m/^(\d)(\d+)_(\d+)$/ and
111 $dec = $1 + $2 / 1000 + $3 / 1000000;
112 $ver =~ m/^(\d+)\.(\d+)\.(\d+)$/ and
113 $dec = $1 + $2 / 1000 + $3 / 1000000;
115 return sprintf( "%.6f", $dec );
120 my %config = $self->awx_configure;
121 my $ver = $self->awx_wx_config_data->{version};
123 $self->{awx_config} = \%config;
125 $config{version} = $self->_version_2_dec( $ver );
127 $config{compiler} = $ENV{CXX} || $self->awx_wx_config_data->{cxx};
128 $config{linker} = $self->awx_wx_config_data->{ld};
129 $config{config}{compiler_kind} = $self->notes( 'compiler_kind' ) ||
130 $self->awx_compiler_kind( $config{compiler} );
131 $config{config}{compiler_version} = $self->notes( 'compiler_version' ) ||
132 $self->awx_compiler_version( $config{compiler} );
133 $self->notes( 'compiler_kind' => $config{config}{compiler_kind} );
134 $self->notes( 'compiler_version' => $config{config}{compiler_version} );
136 my $base = $self->awx_get_name
137 ( toolkit => $config{config}{toolkit},
138 version => $config{version},
139 debug => $self->awx_is_debug,
140 unicode => $self->awx_is_unicode,
141 mslu => $self->awx_is_mslu,
142 compiler => $config{config}{compiler_kind},
143 compiler_version => $config{config}{compiler_version},
146 $self->{awx_key} = $base;
148 $config{wx_base_directory} = $self->awx_wx_config_data->{wxdir}
149 if $self->awx_wx_config_data->{wxdir};
150 $config{alien_base} = $self->{awx_base} = $base;
151 $config{alien_package} = "Alien::wxWidgets::Config::${base}";
156 sub create_config_file {
157 my( $self, $file ) = @_;
159 my $directory = File::Basename::dirname( $file );
160 my %config = $self->_init_config;
161 my $base = $self->awx_key;
163 my $body = Data::Dumper->Dump( [ \%config ] );
164 $body =~ s/rEpLaCe/$base/g;
166 File::Path::mkpath( $directory ) or die "mkpath '$directory': $!"
167 unless -d $directory;
168 open my $fh, '> ' . File::Spec->catfile( $directory, $base . '.pm' );
171 package $config{alien_package};
191 my $key = substr __PACKAGE__, 1 + rindex __PACKAGE__, ':';
194 print $fh <<'EOT' if $self->notes( 'mk_portable' ) && ( $^O =~ /^MSWin/ );
197 my $wxwidgetspath = __PACKAGE__ . '.pm';
198 $wxwidgetspath =~ s/::/\//g;
201 if( -f qq($_/$wxwidgetspath ) ) {
202 $portablebase = qq($_/Alien/wxWidgets/$key);
207 if( $portablebase ) {
208 $portablebase =~ s{/}{\\}g;
209 my $portablelibpath = qq($portablebase\\lib);
210 my $portableincpath = qq($portablebase\\include);
212 $VALUES{include_path} = qq{-I$portablelibpath -I$portableincpath};
213 $VALUES{link_libraries} =~ s{-L\S+\s}{-L$portablelibpath };
214 $VALUES{shared_library_path} = $portablelibpath;
215 $VALUES{wx_base_directory} = $portablebase;
216 $VALUES{prefix} = $portablebase;
222 sub values { %VALUES, key => $key }
225 +{ %{$VALUES{config}},
226 package => __PACKAGE__,
228 version => $VALUES{version},
238 sub fetch_wxwidgets {
241 return if -f $self->notes( 'build_data' )->{data}{archive};
244 print "Fetching wxWidgets...\n";
245 print "fetching from: ", $self->notes( 'build_data' )->{data}{url}, "\n";
247 my $path = File::Fetch->new
248 ( uri => $self->notes( 'build_data' )->{data}{url} )->fetch;
249 die 'Unable to fetch archive' unless $path;
252 sub extract_wxwidgets {
255 return if -d $self->notes( 'build_data' )->{data}{directory};
256 my $archive = $self->notes( 'build_data' )->{data}{archive};
258 print "Extracting wxWidgets...\n";
260 require Archive::Extract;
261 $Archive::Extract::PREFER_BIN = 1;
262 my $ae = Archive::Extract->new( archive => $archive );
264 die 'Error: ', $ae->error unless $ae->extract;
266 $self->patch_wxwidgets;
269 sub patch_wxwidgets {
271 my $old_dir = Cwd::cwd();
272 my @patches = $self->awx_wx_patches;
274 print "Patching wxWidgets...\n";
276 my $wx_dir = $self->notes( 'build_data' )->{data}{directory};
277 my $build_dir = File::Spec->rel2abs( $wx_dir );
280 foreach my $i ( @patches ) {
281 print "Applying patch: ", $i, "\n";
282 my $cmd = $self->_patch_command( $build_dir, $i );
284 system $cmd and die 'Error: ', $?;
291 my( $self, $base_dir, $patch_file ) = @_;
293 $patch_file = File::Spec->abs2rel( $patch_file, $base_dir );
294 my $cmd = $^X . ' ' . File::Spec->catfile( File::Spec->updir,
296 . " -N -p0 -u -b .bak < $patch_file";
301 sub build_wxwidgets {
302 die "Don't know how to build wxWidgets";
305 sub install_wxwidgets {
306 return unless $_[0]->notes( 'build_wx' );
307 die "Don't know how to build wxWidgets";
310 sub install_system_wxwidgets { }
314 return %{$self->{awx_config}} if $self->{awx_config};
318 $config{config}{debug} = $self->awx_is_debug;
319 $config{config}{unicode} = $self->awx_is_unicode;
320 $config{config}{mslu} = $self->awx_is_mslu;
321 $config{config}{build} = $self->awx_is_monolithic ? 'mono' : 'multi';
322 $config{link_flags} = '';
323 $config{c_flags} = '';
330 my $data = $self->awx_wx_config_data;
333 warn "Undefined key '", $_, "' in wx_config"
334 unless defined $data->{$_};
340 sub awx_monolithic { $_[0]->args( 'wxWidgets-monolithic' ) ? 1 : 0 }
341 sub awx_is_monolithic { $_[0]->awx_monolithic }
342 sub awx_debug { $_[0]->args( 'wxWidgets-debug' ) ? 1 : 0 }
343 sub awx_is_debug { $_[0]->awx_debug }
344 sub awx_unicode { $_[0]->notes( 'build_wx_unicode' )
345 || $_[0]->args( 'wxWidgets-unicode' ) ? 1 : 0 }
346 sub awx_is_unicode { $_[0]->awx_unicode }
348 sub awx_is_mslu { $_[0]->awx_mslu }
349 sub awx_static { $_[0]->args( 'wxWidgets-static' ) ? 1 : 0 }
350 sub awx_is_static { $_[0]->awx_static }
351 sub awx_universal { $_[0]->args( 'wxWidgets-universal' ) ? 1 : 0 }
352 sub awx_is_universal { $_[0]->awx_universal }
353 sub awx_get_package { local $_ = $_[0]; s/^My::Build:://; return $_ }
357 my $data = $self->notes( 'build_data' );
358 my $toolkit = $^O eq 'MSWin32' ? 'msw' :
359 $^O eq 'darwin' ? 'mac' :
361 my $unicode = $self->awx_unicode ? 'unicode' : 'ansi';
363 return unless exists $data->{$toolkit} and $data->{$toolkit}{$unicode};
365 return map { File::Spec->rel2abs( File::Spec->catfile( 'patches', $_ ) ) }
366 @{$data->{$toolkit}{$unicode}};
370 my( $self, %args ) = @_;
371 my $e = sub { defined $_[0] ? ( $_[0] ) : () };
372 my $pv = sub { join '.', map { 0 + ( $_ || 0 ) }
373 ( $_[0] =~ /(\d+)\.(\d{1,3})(\d{0,3})/ ) } ;
374 my $base = join '-', $args{toolkit}, $pv->( $args{version} ),
375 $e->( $args{debug} ? 'dbg' : undef ),
376 $e->( $args{unicode} ? 'uni' : undef ),
377 $e->( $args{mslu} ? 'mslu' : undef ),
378 $e->( $args{compiler} ),
379 $e->( $args{compiler_version} ),
382 $base =~ s/\./_/g; $base =~ s/-/_/g;
387 sub awx_compiler_kind { 'nc' } # as in 'No Clue'
389 sub awx_compiler_version {
390 return Alien::wxWidgets::Utility::awx_cc_abi_version( $_[1] );
393 sub awx_path_search {
394 my( $self, $file ) = @_;
396 foreach my $d ( File::Spec->path ) {
397 my $full = File::Spec->catfile( $d, $file );
398 # we are gonna use glob() to accept wildcards
399 foreach my $f ( bsd_glob( $full ) ) {
407 sub awx_uses_bakefile { 1 }
412 $self->awx_strip_dlls;
413 $self->_system( 'perl script/make_ppm.pl' );
420 $ret = @_ > 1 ? system @_ : system $_[0];
421 $ret and croak "system: @_: $?";