File Coverage

blib/lib/Alien/OpenMP/configure.pm
Criterion Covered Total %
statement 45 55 81.8
branch 15 20 75.0
condition 11 17 64.7
subroutine 10 11 90.9
pod 5 6 83.3
total 86 109 78.9


line stmt bran cond sub pod time code
1             package Alien::OpenMP::configure;
2 3     3   129058 use strict;
  3         16  
  3         100  
3 3     3   15 use warnings;
  3         15  
  3         81  
4 3     3   12 use Config;
  3         5  
  3         2222  
5              
6             our $CCNAME = $ENV{CC} || $Config::Config{ccname};
7             our $OS = $^O;
8              
9             my $checked = 0;
10             my $supported = {
11             gcc => {
12             cflags => ['-fopenmp'],
13             libs => ['-fopenmp'],
14             auto_include => join qq{\n}, ('#include '),
15             },
16             clang => {
17             cflags => [ '-Xclang', '-fopenmp' ],
18             libs => ['-lomp'], # this could be -Xpreprocessor
19             auto_include => join qq{\n}, ('#include '),
20             },
21             };
22              
23             sub auto_include {
24 0     0 0 0 shift->_update_supported;
25 0   0     0 return $supported->{$CCNAME}{auto_include} || q{};
26             }
27              
28             sub cflags {
29 6     6 1 18 shift->_update_supported;
30 6 100 100     8 return join ' ', @{$supported->{$OS}{cflags} || $supported->{$CCNAME}{cflags} || []};
  6         55  
31             }
32              
33             sub is_known {
34 6     6 1 794 shift->_update_supported;
35 6   100     39 return !!(exists($supported->{$OS}) || exists($supported->{$CCNAME}));
36             }
37              
38 3     3 1 9 sub lddlflags { __PACKAGE__->libs }
39              
40             sub libs {
41 5     5 1 595 shift->_update_supported;
42 5 100 100     5 return join ' ', @{$supported->{$OS}{libs} || $supported->{$CCNAME}{libs} || []};
  5         43  
43             }
44              
45             sub unsupported {
46 2     2 1 2136 my ($self, $build) = (shift, shift);
47              
48             # build an array of messages
49 2         8 my @msg = ("This version of $CCNAME does not support OpenMP");
50 2 50 33     8 if ($CCNAME eq 'gcc' and $OS ne 'darwin') {
51 0         0 push @msg, "This could be a bug, please record and issue https://github.com/oodler577/p5-Alien-OpenMP/issues";
52             }
53              
54 2 100       6 if ($OS eq 'darwin') {
55 1         3 push @msg, "Support can be enabled by using Homebrew or Macports (https://clang-omp.github.io)";
56 1         3 push @msg, " brew install libomp (Homebrew https://brew.sh)";
57 1         2 push @msg, " port install libomp (Macports https://www.macports.org)";
58             }
59              
60             # report messages using appropriate method
61 2 50 33     20 if (ref($build)) {
    50          
62 0 0       0 return if $build->install_prop->{alien_openmp_compiler_has_openmp};
63 0         0 unshift @msg, "phase = @{[$build->meta->{phase}]}";
  0         0  
64 0         0 $build->log($_) for @msg;
65             }
66             elsif ($build && (my $log = $build->can('log'))) {
67 0         0 unshift @msg, "phase = @{[$build->meta->{phase}]}";
  0         0  
68 0         0 $log->($_) for @msg;
69             }
70             else {
71 2         129 warn join q{>}, __PACKAGE__, " $_\n" for @msg;
72             }
73 2         52 print "OS Unsupported\n";
74             }
75              
76             # test support only
77 6     6   19804 sub _reset { $checked = 0; }
78              
79             sub _update_supported {
80 17 100   17   39 return if $checked;
81 6 100       18 if ($OS eq 'darwin') {
82 3         19 require File::Which;
83 3         8 require Path::Tiny;
84              
85             # The issue here is that ccname=gcc and cc=cc as an interface to clang
86 3         18 $supported->{darwin} = {cflags => ['-Xclang', '-fopenmp'], libs => ['-lomp'],};
87 3 100       15 if (my $mp = File::Which::which('port')) {
88              
89             # macports /opt/local/bin/port
90 1         126 my $mp_prefix = Path::Tiny->new($mp)->parent->parent;
91 1         106 push @{$supported->{darwin}{cflags}}, "-I$mp_prefix/include/libomp";
  1         6  
92 1         5 unshift @{$supported->{darwin}{libs}}, "-L$mp_prefix/lib/libomp";
  1         3  
93             }
94             else {
95             # homebrew has the headers and library in /usr/local
96 2         369 push @{$supported->{darwin}{cflags}}, "-I/usr/local/include";
  2         8  
97 2         4 unshift @{$supported->{darwin}{libs}}, "-L/usr/local/lib";
  2         14  
98             }
99             }
100 6         14 $checked++;
101             }
102              
103             1;
104              
105             =encoding utf8
106              
107             =head1 NAME
108              
109             Alien::OpenMP::configure - Install time configuration helper
110              
111             =head1 SYNOPSIS
112              
113             # alienfile
114             use Alien::OpenMP::configure;
115              
116             if (!Alien::OpenMP::configure->is_known) {
117             Alien::OpenMP::configure->unsupported(__PACKAGE__);
118             exit;
119             }
120              
121             plugin 'Probe::CBuilder' => (
122             cflags => Alien::OpenMP::configure->cflags,
123             libs => Alien::OpenMP::configure->libs,
124             ...
125             );
126              
127             =head1 DESCRIPTION
128              
129             L is storage for the compiler flags required for multiple compilers on multiple systems and
130             an attempt to intelligently support them.
131              
132             This module is designed to be used by the L authors and contributors, rather than end users.
133              
134             =head1 METHODS
135              
136             L implements the following methods.
137              
138             =head2 cflags
139              
140             Obtain the compiler flags for the compiler and architecture suitable for passing as C to
141             L.
142              
143             =head2 is_known
144              
145             Return a Boolean to indicate whether the compiler is known to this module.
146              
147             =head2 lddlflags
148              
149             A synonym for L.
150              
151             =head2 libs
152              
153             Obtain the compiler flags for the compiler and architecture suitable for passing as C to
154             L.
155              
156             =head2 unsupported
157              
158             Report using L or L that the compiler/architecture
159             combination is unsupported and provide minimal notes on any solutions. There is little to no guarding of the actual
160             state of support in this function.
161              
162             =cut