File Coverage

blib/lib/Alien/Build/Plugin/Probe/CBuilder.pm
Criterion Covered Total %
statement 68 88 77.2
branch 11 22 50.0
condition 2 8 25.0
subroutine 10 10 100.0
pod 1 1 100.0
total 92 129 71.3


line stmt bran cond sub pod time code
1             package Alien::Build::Plugin::Probe::CBuilder;
2              
3 4     4   7687 use strict;
  4         8  
  4         125  
4 4     4   21 use warnings;
  4         9  
  4         91  
5 4     4   67 use 5.008004;
  4         15  
6 4     4   880 use Alien::Build::Plugin;
  4         8  
  4         30  
7 4     4   993 use File::chdir;
  4         6320  
  4         419  
8 4     4   30 use File::Temp ();
  4         19  
  4         87  
9 4     4   22 use Capture::Tiny qw( capture_merged capture );
  4         9  
  4         4272  
10              
11             # ABSTRACT: Probe for system libraries by guessing with ExtUtils::CBuilder
12             our $VERSION = '2.46'; # VERSION
13              
14              
15             has options => sub { {} };
16              
17              
18             has cflags => '';
19              
20              
21             has libs => '';
22              
23              
24             has program => 'int main(int argc, char *argv[]) { return 0; }';
25              
26              
27             has version => undef;
28              
29              
30             has aliens => [];
31              
32              
33             has lang => 'C';
34              
35             sub init
36             {
37 5     5 1 14 my($self, $meta) = @_;
38              
39 5         22 $meta->add_requires('configure' => 'ExtUtils::CBuilder' => 0 );
40              
41 5 50       19 if(@{ $self->aliens })
  5         19  
42             {
43 0 0 0     0 die "You can't specify both 'aliens' and either 'cflags' or 'libs' for the Probe::CBuilder plugin" if $self->cflags || $self->libs;
44              
45 0         0 $meta->add_requires('configure' => $_ => 0 ) for @{ $self->aliens };
  0         0  
46 0         0 $meta->add_requires('Alien::Build::Plugin::Probe::CBuilder' => '0.53');
47              
48 0         0 my $cflags = '';
49 0         0 my $libs = '';
50 0         0 foreach my $alien (@{ $self->aliens })
  0         0  
51             {
52 0         0 my $pm = "$alien.pm";
53 0         0 $pm =~ s/::/\//g;
54 0         0 require $pm;
55 0         0 $cflags .= $alien->cflags . ' ';
56 0         0 $libs .= $alien->libs . ' ';
57             }
58 0         0 $self->cflags($cflags);
59 0         0 $self->libs($libs);
60             }
61              
62 5         12 my @cpp;
63              
64 5 50       19 if($self->lang ne 'C')
65             {
66 0         0 $meta->add_requires('Alien::Build::Plugin::Probe::CBuilder' => '0.53');
67 0 0       0 @cpp = ('C++' => 1) if $self->lang eq 'C++';
68             }
69              
70             $meta->register_hook(
71             probe => sub {
72 4     4   19 my($build) = @_;
73              
74 4         29 $build->hook_prop->{probe_class} = __PACKAGE__;
75 4         42 $build->hook_prop->{probe_instance_id} = $self->instance_id;
76              
77 4         21 local $CWD = File::Temp::tempdir( CLEANUP => 1, DIR => $CWD );
78              
79 4         2173 open my $fh, '>', 'mytest.c';
80 4         40 print $fh $self->program;
81 4         147 close $fh;
82              
83 4         18 $build->log("trying: cflags=@{[ $self->cflags ]} libs=@{[ $self->libs ]}");
  4         30  
  4         16  
84              
85 4         32 my $cb = ExtUtils::CBuilder->new(%{ $self->options });
  4         23  
86              
87 4         4319 my($out1, $obj) = capture_merged { eval {
88 4         21 $cb->compile(
89             source => 'mytest.c',
90             extra_compiler_flags => $self->cflags,
91             @cpp,
92             );
93 4         148 } };
94              
95 4 100       3564 if(my $error = $@)
96             {
97 1         10 $build->log("compile failed: $error");
98 1         8 $build->log("compile failed: $out1");
99 1         18 die $@;
100             }
101              
102 3         3221 my($out2, $exe) = capture_merged { eval {
103 3         19 $cb->link_executable(
104             objects => [$obj],
105             extra_linker_flags => $self->libs,
106             );
107 3         96 } };
108              
109 3 50       2386 if(my $error = $@)
110             {
111 0         0 $build->log("link failed: $error");
112 0         0 $build->log("link failed: $out2");
113 0         0 die $@;
114             }
115              
116 3 50       97 my($out, $err, $ret) = capture { system($^O eq 'MSWin32' ? $exe : "./$exe") };
  3         3152  
117 3 50       2756 die "execute failed" if $ret;
118              
119 3         22 my $cflags = $self->cflags;
120 3         52 my $libs = $self->libs;
121              
122 3         36 $cflags =~ s{\s*$}{ };
123 3         22 $libs =~ s{\s*$}{ };
124              
125 3         21 $build->install_prop->{plugin_probe_cbuilder_gather}->{$self->instance_id} = {
126             cflags => $cflags,
127             libs => $libs,
128             };
129              
130 3 100       9 if(defined $self->version)
131             {
132 1         10 my($version) = $out =~ $self->version;
133 1         4 $build->hook_prop->{version} = $version;
134 1         5 $build->install_prop->{plugin_probe_cbuilder_gather}->{$self->instance_id}->{version} = $version;
135             }
136              
137 3         31 'system';
138             }
139 5         86 );
140              
141             $meta->register_hook(
142             gather_system => sub {
143 2     2   23 my($build) = @_;
144              
145             return if $build->hook_prop->{name} eq 'gather_system'
146 2 50 50     10 && ($build->install_prop->{system_probe_instance_id} || '') ne $self->instance_id;
      33        
147              
148 2 50       6 if(my $p = $build->install_prop->{plugin_probe_cbuilder_gather}->{$self->instance_id})
149             {
150 2         26 $build->runtime_prop->{$_} = $p->{$_} for keys %$p;
151             }
152             },
153 5         28 );
154             }
155              
156             1;
157              
158             __END__