File Coverage

blib/lib/Devel/CheckCompiler.pm
Criterion Covered Total %
statement 51 53 96.2
branch 17 26 65.3
condition 1 3 33.3
subroutine 11 11 100.0
pod 3 3 100.0
total 83 96 86.4


line stmt bran cond sub pod time code
1             package Devel::CheckCompiler;
2 5     5   342365 use strict;
  5         9  
  5         143  
3 5     5   21 use warnings;
  5         6  
  5         111  
4 5     5   119 use 5.008001;
  5         15  
5             our $VERSION = '0.07';
6 5     5   917 use parent qw/Exporter/;
  5         562  
  5         23  
7              
8             our @EXPORT = qw/check_c99 check_c99_or_exit check_compile/;
9 5     5   296 use Config;
  5         7  
  5         206  
10 5     5   2466 use ExtUtils::CBuilder;
  5         300797  
  5         2110  
11              
12             my $C99_SOURCE = <<'C99';
13             // include a C99 header
14             #include <stdbool.h>
15             inline // a C99 keyword with C99 style comments
16             int test_c99() {
17             int i = 0;
18             i++;
19             int j = i - 1; // another C99 feature: declaration after statement
20             // another C99 feature: for loop variable declarations
21             for (int k = 0; k < 3; i++) {
22             }
23             return j;
24             }
25             C99
26              
27             sub check_c99 {
28 4     4 1 4257 check_compile($C99_SOURCE);
29             }
30              
31             sub check_c99_or_exit {
32 4 100   4 1 3814 check_compile($C99_SOURCE) or do {
33 2         138 warn "Your system is not support C99(OS unsupported)\n";
34 2         12 exit 0;
35             };
36             }
37              
38             sub _is_gcc {
39 7 50   7   383 return 0 if $Config{gccversion} eq '';
40             # For clang on MacOSX and *BSD distributions
41 7 50       79 return 0 if $Config{gccversion} =~ m/clang/i;
42             # For Intel C and C++ compiler
43 7 50       49 return 0 if $Config{gccversion} =~ m/intel/i;
44              
45 7         26 return 1;
46             }
47              
48             sub _gcc_version {
49 7 50   7   72 if ($Config{gccversion} =~ m/^(\d+)\.(\d+)\.(\d+)/) {
50             return {
51 7         52 major => $1,
52             minor => $2,
53             patch => $3,
54             };
55             }
56              
57 0         0 return;
58             }
59              
60             sub check_compile {
61 11     11 1 12301 my ($src, %opt) = @_;
62              
63 11         61 my $cbuilder = ExtUtils::CBuilder->new(quiet => 1);
64 11 100       49 return 0 unless $cbuilder->have_compiler;
65              
66 7         64 require File::Temp;
67              
68 7         25 my $tmpfile = File::Temp->new(SUFFIX => '.c');
69 7         2569 $tmpfile->print($src);
70 7         151 $tmpfile->close();
71              
72 7         370 my $compile_flags;
73 7 50       37 if (_is_gcc()) {
74 7         20 my $gcc_version = _gcc_version();
75             # '-std=gnu11' is default from GCC 5
76 7 50 33     93 if (defined $gcc_version && $gcc_version->{major} < 5) {
77 7         31 $compile_flags = ['-std=c99'];
78             }
79             }
80              
81 7         15 my $objname = eval {
82 7         56 $cbuilder->compile(source => $tmpfile->filename, extra_compiler_flags => $compile_flags);
83             };
84 7 100       106 if ($objname) {
85 6         11 my $ret = 1;
86 6 100       24 if ($opt{executable}) {
87 2         5 my $execfile = eval {
88             $cbuilder->link_executable(objects => $objname,
89 2         13 extra_linker_flags => $opt{extra_linker_flags});
90             };
91              
92 2 50       45 if ($execfile) {
93 2 50       116 unlink $execfile or warn "Cannot unlink $execfile (ignored): $!";
94             } else {
95 0         0 $ret = 0;
96             }
97             }
98 6 50       256 unlink $objname or warn "Cannot unlink $objname (ignored): $!";
99 6         38 return $ret;
100             } else {
101 1         5 return 0;
102             }
103             }
104              
105             1;
106             __END__
107              
108             =encoding utf8
109              
110             =head1 NAME
111              
112             Devel::CheckCompiler - Check the compiler's availability
113              
114             =head1 SYNOPSIS
115              
116             use Devel::CheckCompiler;
117              
118             check_c99_or_exit();
119              
120             =head1 DESCRIPTION
121              
122             Devel::CheckCompiler is checker for compiler's availability.
123              
124             =head1 FUNCTIONS
125              
126             =over 4
127              
128             =item C<check_c99()>
129              
130             Returns true if the current system has a working C99 compiler, false otherwise.
131              
132             =item C<check_c99_or_exit()>
133              
134             Check the current system has a working C99 compiler, if it's not available, exit by 0.
135              
136             =item C<check_compile($src: Str, %options)>
137              
138             Compile C<$src> as C code. Return 1 if it's available, 0 otherwise.
139              
140             Possible options are:
141              
142             =over
143              
144             =item executable :Bool = false
145              
146             Check to see if generating executable is possible if this parameter is true.
147              
148             =item extra_linker_flags : Str | ArrayRef[Str]
149              
150             Any additional flags you wish to pass to the linker. This option is used
151             only when C<executable> option specified.
152              
153             =back
154              
155             =back
156              
157             =head1 AUTHOR
158              
159             Tokuhiro Matsuno E<lt>tokuhirom AAJKLFJEF@ GMAIL COME<gt>
160              
161             =head1 SEE ALSO
162              
163             L<ExtUtils::CBuilder>
164              
165             =head1 LICENSE
166              
167             Copyright (C) Tokuhiro Matsuno
168              
169             This library is free software; you can redistribute it and/or modify
170             it under the same terms as Perl itself.
171              
172             =cut