File Coverage

lib/Module/Build/Pluggable/XSUtil.pm
Criterion Covered Total %
statement 67 85 78.8
branch 21 36 58.3
condition 2 9 22.2
subroutine 14 14 100.0
pod 0 2 0.0
total 104 146 71.2


line stmt bran cond sub pod time code
1             package Module::Build::Pluggable::XSUtil;
2 9     9   8507 use strict;
  9         22  
  9         352  
3 9     9   51 use warnings;
  9         29  
  9         227  
4 9     9   357 use 5.008005;
  9         29  
  9         481  
5             our $VERSION = '1.02';
6 9     9   55 use parent qw/Module::Build::Pluggable::Base/;
  9         16  
  9         336  
7 9     9   60185 use Config;
  9         33  
  9         344  
8 9     9   101 use Carp ();
  9         22  
  9         1675  
9              
10             # -------------------------------------------------------------------------
11             # utility methods
12              
13             sub _xs_debugging {
14 8     8   46 my $self = shift;
15 8   66     285 return $ENV{XS_DEBUG} || $self->builder->args('g');
16             }
17              
18             # GNU C Compiler
19             sub _is_gcc {
20 6     6   283 return $Config{gccversion};
21             }
22              
23             # Microsoft Visual C++ Compiler (cl.exe)
24             sub _is_msvc {
25 1     1   74 return $Config{cc} =~ /\A cl \b /xmsi;
26             }
27              
28             sub _gcc_version {
29 7     7   103709 my $res = `$Config{cc} --version`;
30 7         433 my ($version) = $res =~ /\(GCC\) ([0-9.]+)/;
31 9     9   55 no warnings 'numeric', 'uninitialized';
  9         18  
  9         7383  
32 7         700 return sprintf '%g', $version;
33             }
34              
35             # -------------------------------------------------------------------------
36             # hooks
37              
38             sub HOOK_prepare {
39 8     8 0 1102 my ($self, $args) = @_;
40              
41             # add -g option
42 8 50       100 Carp::confess("-g option is defined at other place.") if $args->{get_options}->{g};
43 8         126 $args->{get_options}->{g} = { type => '!' };
44             }
45              
46             sub HOOK_configure {
47 8     8 0 850530 my $self = shift;
48 8 50       327 unless ($self->builder->have_c_compiler()) {
49 0         0 warn "This distribution requires a C compiler, but it's not available, stopped.\n";
50 0         0 exit -1;
51             }
52              
53             # runtime deps
54 8         2998502 $self->configure_requires('ExtUtils::ParseXS' => '2.21');
55 8         906 $self->requires('XSLoader' => '0.02');
56              
57             # cleanup options
58 8 50       1849 if ($^O eq 'cygwin') {
59 0         0 $self->bulder->add_to_cleanup('*.stackdump');
60             }
61              
62             # debugging options
63 8 100       142 if ($self->_xs_debugging()) {
64 1 50       67 if ($self->_is_msvc()) {
65 0         0 $self->add_extra_compiler_flags('-Zi');
66             } else {
67 1         18 $self->add_extra_compiler_flags(qw/-g -ggdb -g3/);
68             }
69 1         96 $self->add_extra_compiler_flags('-DXS_ASSERT');
70             }
71              
72             # c++ options
73 8 50       653 if ($self->{'c++'}) {
74 0         0 $self->configure_requires('ExtUtils::CBuilder' => '0.28');
75              
76 0         0 require ExtUtils::CBuilder;
77 0         0 my $cbuilder = ExtUtils::CBuilder->new(quiet => 1);
78 0 0       0 $cbuilder->have_cplusplus or do {
79 0         0 warn "This environment does not have a C++ compiler(OS unsupported)\n";
80 0         0 exit 0;
81             };
82             }
83              
84             # c99 is required
85 8 50       89 if ($self->{c99}) {
86 0         0 $self->configure_requires('Devel::CheckCompiler' => '0.01');
87              
88 0         0 require Devel::CheckCompiler;
89 0         0 Devel::CheckCompiler::check_c99_or_exit();
90             }
91              
92             # write xshelper.h
93 8 100       120 if (my $xshelper = $self->{xshelper}) {
94 2 100       20 if ($xshelper eq '1') { # { xshelper => 1 }
95 1         6 $xshelper = 'xshelper.h';
96             }
97 2         724 File::Path::mkpath(File::Basename::dirname($xshelper));
98 2         2329 require Devel::XSHelper;
99 2         34 Devel::XSHelper::WriteFile($xshelper);
100              
101             # generate ppport.h to same directory automatically.
102 2 50       19 unless (defined $self->{ppport}) {
103 2         37 (my $ppport = $xshelper) =~ s!xshelper\.h$!ppport\.h!;
104 2         19 $self->{ppport} = $ppport;
105             }
106             }
107              
108             # write ppport.h
109 8 100       88 if (my $ppport = $self->{ppport}) {
110 4 100       46 if ($ppport eq '1') { # { ppport => 1 }
111 1         5 $ppport = 'ppport.h';
112             }
113 4         1130 File::Path::mkpath(File::Basename::dirname($ppport));
114 4         13847 require Devel::PPPort;
115 4         2613 Devel::PPPort::WriteFile($ppport);
116             }
117              
118             # cc_warnings => 1
119 8         22471 $self->add_extra_compiler_flags($self->_cc_warnings());
120             }
121              
122             sub _cc_warnings {
123 8     8   148 my $self = shift;
124              
125 8         33 my @flags;
126 8 100       87 if($self->_is_gcc()){
    50          
127 7         128 push @flags, qw(-Wall);
128              
129 7         58 my $gccversion = $self->_gcc_version();
130 7 50       202 if($gccversion >= 4.0){
131 0         0 push @flags, qw(-Wextra);
132 0 0 0     0 if(!($self->{c99} or $self->{'c++'})) {
133             # Note: MSVC++ doesn't support C99,
134             # so -Wdeclaration-after-statement helps
135             # ensure C89 specs.
136 0         0 push @flags, qw(-Wdeclaration-after-statement);
137             }
138 0 0 0     0 if($gccversion >= 4.1 && !$self->{'c++'}) {
139 0         0 push @flags, qw(-Wc++-compat);
140             }
141             }
142             else{
143 7         115 push @flags, qw(-W -Wno-comment);
144             }
145             }
146             elsif ($self->_is_msvc()) {
147 1         6 push @flags, qw(-W3);
148             }
149             else{
150             # TODO: support other compilers
151             }
152            
153 8         584 return @flags;
154             }
155              
156             1;
157             __END__