1 package Alien::wxWidgets::Utility;
5 Alien::wxWidgets::Utility - INTERNAL: do not use
10 use base qw(Exporter);
12 use File::Basename qw();
15 if( $^O eq 'MSWin32' && $Config{_a} ne $Config{lib_ext} ) {
18 \$Config{_a} is '$Config{_a}' and \$Config{lib_ext} is '$Config{lib_ext}':
19 they need to be equal for the build to succeed. If you are using ActivePerl
20 with MinGW/GCC, please:
22 - install ExtUtils::FakeConfig
23 - set PERL5OPT=-MConfig_m
31 our @EXPORT_OK = qw(awx_capture awx_cc_is_gcc awx_cc_version awx_cc_abi_version
32 awx_sort_config awx_grep_config awx_smart_config);
34 my $quotes = $^O =~ /MSWin32/ ? '"' : "'";
35 my $compiler_checked = '';
38 return File::Basename::basename( lc $_[0], '.exe' );
41 sub _warn_nonworking_compiler {
44 return if $compiler_checked eq $cc;
46 eval { require ExtUtils::CBuilder; };
47 return if $@; # avoid failing when called a Build.PL time
49 # a C++ compiler can act as a linker, except for MS cl.exe
50 my $ld = _exename( $Config{cc} ) eq 'cl' ? 'link' : $cc;
51 my $b = ExtUtils::CBuilder->new( config => { cc => $cc, ld => $ld },
55 if( !$b->have_compiler ) {
58 ATTENTION: It apperars '$cc' is not a working compiler, please make
59 sure all necessary packages are installed.
65 $compiler_checked = $cc;
69 qx!$^X -e ${quotes}open STDERR, q[>&STDOUT]; exec \@ARGV${quotes} -- $_[0]!;
75 return $^O =~ /MSWin32/ and $cc =~ /^cl/i;
81 return scalar( awx_capture( "$cc --version" ) =~ m/g(cc|\+\+)/i ) # 3.x
82 || scalar( awx_capture( "$cc" ) =~ m/gcc/i ); # 2.95
85 sub awx_cc_abi_version {
88 _warn_nonworking_compiler( $cc );
90 my $is_gcc = awx_cc_is_gcc( $cc );
91 my $is_msvc = awx_cc_is_msvc( $cc );
92 return 0 unless $is_gcc || $is_msvc;
93 my $ver = awx_cc_version( $cc );
95 return 0 unless $ver > 0;
96 return '3.4' if $ver >= 3.4;
97 return '3.2' if $ver >= 3.2;
100 return 0 if $ver < 7;
108 _warn_nonworking_compiler( $cc );
110 my $is_gcc = awx_cc_is_gcc( $cc );
111 my $is_msvc = awx_cc_is_msvc( $cc );
112 return 0 unless $is_gcc || $is_msvc;
115 my $ver = awx_capture( "$cc --version" );
116 $ver =~ m/(\d+\.\d+)(?:\.\d+)?/ or return 0;
118 } elsif( $is_msvc ) {
119 my $ver = awx_capture( $cc );
120 $ver =~ m/(\d+\.\d+)\.\d+/ or return 0;
121 return 8.0 if $1 >= 14;
122 return 7.1 if $1 >= 13.10;
123 return 7.0 if $1 >= 13;
124 return 6.0 if $1 >= 12;
125 return 5.0 if $1 >= 11;
130 sub awx_compiler_kind {
133 _warn_nonworking_compiler( $cc );
135 return 'gcc' if awx_cc_is_gcc( $cc );
136 return 'cl' if awx_cc_is_msvc( $cc );
138 return 'nc'; # as in 'No Clue'
141 # sort a list of configurations by version, debug/release, unicode/ansi, mslu
142 sub awx_sort_config {
143 # comparison functions treating undef as 0 or ''
144 # numerico comparison
145 my $make_cmpn = sub {
147 sub { exists $a->{$k} && exists $b->{$k} ? $a->{$k} <=> $b->{$k} :
148 exists $a->{$k} ? 1 :
149 exists $b->{$k} ? -1 :
153 my $make_cmps = sub {
155 sub { exists $a->{$k} && exists $b->{$k} ? $a->{$k} cmp $b->{$k} :
156 exists $a->{$k} ? 1 :
157 exists $b->{$k} ? -1 :
161 my $rev = sub { my $cmp = shift; sub { -1 * &$cmp } };
162 # compare by different criteria, using the first nonzero as tie-breaker
163 my $crit_sort = sub {
175 my $cmp = $crit_sort->( $make_cmpn->( 'version' ),
176 $rev->( $make_cmpn->( 'debug' ) ),
177 $make_cmpn->( 'unicode' ),
178 $make_cmpn->( 'mslu' ) );
180 return reverse sort $cmp @_;
183 sub awx_grep_config {
186 # compare to a numeric range or value
187 # low extreme included, high extreme excluded
188 # if $a{key} = [ lo, hi ] then range else low extreme
189 my $make_cmpr = sub {
192 return 1 unless exists $a{$k};
193 ref $a{$k} ? $a{$k}[0] <= $_->{$k} && $_->{$k} < $a{$k}[1] :
197 # compare for numeric equality
198 my $make_cmpn = sub {
200 sub { exists $a{$k} ? $a{$k} == $_->{$k} : 1 }
202 # compare for string equality
203 my $make_cmps = sub {
205 sub { exists $a{$k} ? $a{$k} eq $_->{$k} : 1 }
207 my $compare_tk = sub {
208 return 1 unless exists $a{toolkit};
209 my $atk = $a{toolkit} eq 'mac' ? 'osx_carbon' :
211 my $btk = $_->{toolkit} eq 'mac' ? 'osx_carbon' :
216 # note tha if the criteria was not supplied, the comparison is a noop
217 my $wver = $make_cmpr->( 'version' );
218 my $ckind = $make_cmps->( 'compiler_kind' );
219 my $cver = $make_cmpn->( 'compiler_version' );
220 my $tkit = $compare_tk;
221 my $deb = $make_cmpn->( 'debug' );
222 my $uni = $make_cmpn->( 'unicode' );
223 my $mslu = $make_cmpn->( 'mslu' );
224 my $key = $make_cmps->( 'key' );
226 grep { &$wver } grep { &$ckind } grep { &$cver }
227 grep { &$tkit } grep { &$deb } grep { &$uni }
228 grep { &$mslu } grep { &$key }
232 # automatically add compiler data unless the key was supplied
233 sub awx_smart_config {
235 # the key already identifies the configuration
236 return %args if $args{key};
238 my $cc = $ENV{CXX} || $ENV{CC} || $Config{ccname} || $Config{cc};
239 my $kind = awx_compiler_kind( $cc );
240 my $version = awx_cc_abi_version( $cc );
242 $args{compiler_kind} ||= $kind;
243 $args{compiler_version} ||= $version;
248 # allow to remap srings in the configuration; useful when building
253 if( $ENV{ALIEN_WX_PREFIXES} ) {
254 my @kv = split /,\s*/, $ENV{ALIEN_WX_PREFIXES};
257 my( $match, $repl ) = ( shift( @kv ) || '', shift( @kv ) || '' );
259 push @prefixes, [ $match, $^O eq 'MSWin32' ?
261 qr/\Q$match\E/, $repl ];
268 return $string if ref $string;
269 return $string if $Alien::wxWidgets::dont_remap;
271 foreach my $prefix ( @prefixes ) {
272 my( $str, $rx, $repl ) = @$prefix;
274 $string =~ s{$rx(\S*)}{$repl$1}g;