File Coverage

lib/Module/Build/Pluggable/XSUtil.pm
Criterion Covered Total %
statement 66 84 78.5
branch 21 36 58.3
condition 2 9 22.2
subroutine 14 14 100.0
pod 0 2 0.0
total 103 145 71.0


line stmt bran cond sub pod time code
1             package Module::Build::Pluggable::XSUtil;
2 9     9   4920 use strict;
  9         17  
  9         257  
3 9     9   34 use warnings;
  9         13  
  9         221  
4 9     9   189 use 5.008005;
  9         29  
5             our $VERSION = '1.03';
6 9     9   43 use parent qw/Module::Build::Pluggable::Base/;
  9         14  
  9         170  
7 9     9   32683 use Config;
  9         14  
  9         283  
8 9     9   32 use Carp ();
  9         10  
  9         1217  
9              
10             # -------------------------------------------------------------------------
11             # utility methods
12              
13             sub _xs_debugging {
14 8     8   24 my $self = shift;
15 8   66     112 return $ENV{XS_DEBUG} || $self->builder->args('g');
16             }
17              
18             # GNU C Compiler
19             sub _is_gcc {
20 6     6   134 return $Config{gccversion};
21             }
22              
23             # Microsoft Visual C++ Compiler (cl.exe)
24             sub _is_msvc {
25 1     1   37 return $Config{cc} =~ /\A cl \b /xmsi;
26             }
27              
28             sub _gcc_version {
29 7     7   20728 my $res = `$Config{cc} --version`;
30 7         126 my ($version) = $res =~ /\(GCC\) ([0-9.]+)/;
31 9     9   39 no warnings 'numeric', 'uninitialized';
  9         18  
  9         4401  
32 7         192 return sprintf '%g', $version;
33             }
34              
35             # -------------------------------------------------------------------------
36             # hooks
37              
38             sub HOOK_prepare {
39 8     8 0 689 my ($self, $args) = @_;
40              
41             # add -g option
42 8 50       85 Carp::confess("-g option is defined at other place.") if $args->{get_options}->{g};
43 8         83 $args->{get_options}->{g} = { type => '!' };
44             }
45              
46             sub HOOK_configure {
47 8     8 0 238663 my $self = shift;
48 8 50       112 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         923643 $self->configure_requires('ExtUtils::ParseXS' => '2.21');
55 8         502 $self->requires('XSLoader' => '0.02');
56              
57             # cleanup options
58 8 50       383 if ($^O eq 'cygwin') {
59 0         0 $self->builder->add_to_cleanup('*.stackdump');
60             }
61              
62             # debugging options
63 8 100       55 if ($self->_xs_debugging()) {
64 1 50       46 if ($self->_is_msvc()) {
65 0         0 $self->add_extra_compiler_flags('-Zi');
66             } else {
67 1         13 $self->add_extra_compiler_flags(qw/-g -ggdb -g3/);
68             }
69 1         62 $self->add_extra_compiler_flags('-DXS_ASSERT');
70             }
71              
72             # c++ options
73 8 50       347 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       57 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       84 if (my $xshelper = $self->{xshelper}) {
94 2 100       14 if ($xshelper eq '1') { # { xshelper => 1 }
95 1         3 $xshelper = 'xshelper.h';
96             }
97 2         418 File::Path::mkpath(File::Basename::dirname($xshelper));
98 2         1152 require Devel::XSHelper;
99 2         8 Devel::XSHelper::WriteFile($xshelper);
100              
101             # generate ppport.h to same directory automatically.
102 2 50       10 unless (defined $self->{ppport}) {
103 2         13 (my $ppport = $xshelper) =~ s!xshelper\.h$!ppport\.h!;
104 2         8 $self->{ppport} = $ppport;
105             }
106             }
107              
108             # write ppport.h
109 8 100       54 if (my $ppport = $self->{ppport}) {
110 4 100       24 if ($ppport eq '1') { # { ppport => 1 }
111 1         3 $ppport = 'ppport.h';
112             }
113 4         622 File::Path::mkpath(File::Basename::dirname($ppport));
114 4         5779 require Devel::PPPort;
115 4         1425 Devel::PPPort::WriteFile($ppport);
116             }
117              
118             # cc_warnings => 1
119 8         8974 $self->add_extra_compiler_flags($self->_cc_warnings());
120             }
121              
122             sub _cc_warnings {
123 8     8   82 my $self = shift;
124              
125 8         21 my @flags;
126 8 100       32 if($self->_is_gcc()){
    50          
127 7         54 push @flags, qw(-Wall);
128              
129 7         31 my $gccversion = $self->_gcc_version();
130 7 50       92 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         67 push @flags, qw(-W -Wno-comment);
144             }
145             }
146             elsif ($self->_is_msvc()) {
147 1         5 push @flags, qw(-W3);
148             }
149             else{
150             # TODO: support other compilers
151             }
152            
153 8         236 return @flags;
154             }
155              
156             1;
157             __END__