File Coverage

blib/lib/ExtUtils/CChecker.pm
Criterion Covered Total %
statement 111 146 76.0
branch 31 60 51.6
condition 1 3 33.3
subroutine 22 26 84.6
pod 15 19 78.9
total 180 254 70.8


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2010-2021 -- leonerd@leonerd.org.uk
5              
6             package ExtUtils::CChecker;
7              
8 7     7   350474 use v5;
  7         72  
9 7     7   29 use strict;
  7         12  
  7         150  
10 7     7   29 use warnings;
  7         18  
  7         320  
11              
12             our $VERSION = '0.11';
13              
14 7     7   37 use Carp;
  7         11  
  7         381  
15              
16 7     7   3212 use ExtUtils::CBuilder;
  7         488181  
  7         7960  
17              
18             =head1 NAME
19              
20             C - configure-time utilities for using C headers,
21             libraries, or OS features
22              
23             =head1 SYNOPSIS
24              
25             use Module::Build;
26             use ExtUtils::CChecker;
27              
28             my $cc = ExtUtils::CChecker->new;
29              
30             $cc->assert_compile_run(
31             diag => "no PF_MOONLASER",
32             source => <<'EOF' );
33             #include
34             #include
35             int main(int argc, char *argv[]) {
36             printf("PF_MOONLASER is %d\n", PF_MOONLASER);
37             return 0;
38             }
39             EOF
40              
41             Module::Build->new(
42             ...
43             )->create_build_script;
44              
45             =head1 DESCRIPTION
46              
47             Often Perl modules are written to wrap functionality found in existing C
48             headers, libraries, or to use OS-specific features. It is useful in the
49             F or F file to check for the existance of these
50             requirements before attempting to actually build the module.
51              
52             Objects in this class provide an extension around L to
53             simplify the creation of a F<.c> file, compiling, linking and running it, to
54             test if a certain feature is present.
55              
56             It may also be necessary to search for the correct library to link against,
57             or for the right include directories to find header files in. This class also
58             provides assistance here.
59              
60             =cut
61              
62             =head1 CONSTRUCTOR
63              
64             =cut
65              
66             =head2 new
67              
68             $cc = ExtUtils::CChecker->new( %args )
69              
70             Returns a new instance of a C object. Takes the following
71             named parameters:
72              
73             =over 4
74              
75             =item defines_to => PATH
76              
77             If given, defined symbols will be written to a C preprocessor F<.h> file of
78             the given name, instead of by adding extra C<-DI> arguments to the
79             compiler flags.
80              
81             =item quiet => BOOL
82              
83             If given, sets the C option to the underlying C
84             instance. If absent, defaults to enabled. To disable quietness, i.e. to print
85             more verbosely, pass a defined-but-false value, such as C<0>.
86              
87             =item config => HASH
88              
89             If given, passed through as the configuration of the underlying
90             C instance.
91              
92             =back
93              
94             =cut
95              
96             sub new
97             {
98 6     6 1 459 my $class = shift;
99 6         17 my %args = @_;
100              
101 6         13 my $quiet = 1;
102 6 50 33     28 $quiet = 0 if defined $args{quiet} and !$args{quiet};
103              
104             my $cb = ExtUtils::CBuilder->new(
105             quiet => $quiet,
106             config => $args{config},
107 6         89 );
108              
109             return bless {
110             cb => $cb,
111             seq => 0,
112              
113             defines_to => $args{defines_to},
114              
115 6         212675 include_dirs => [],
116             extra_compiler_flags => [],
117             extra_linker_flags => [],
118             }, $class;
119             }
120              
121             =head1 METHODS
122              
123             =cut
124              
125             =head2 include_dirs
126              
127             $dirs = $cc->include_dirs
128              
129             Returns the currently-configured include directories in an ARRAY reference.
130              
131             =cut
132              
133             sub include_dirs
134             {
135 5     5 1 17 my $self = shift;
136             # clone it just so caller can't modify ours
137 5         13 return [ @{ $self->{include_dirs} } ];
  5         81  
138             }
139              
140             =head2 extra_compiler_flags
141              
142             $flags = $cc->extra_compiler_flags
143              
144             Returns the currently-configured extra compiler flags in an ARRAY reference.
145              
146             =cut
147              
148             sub extra_compiler_flags
149             {
150 7     7 1 44 my $self = shift;
151             # clone it just so caller can't modify ours
152 7         17 return [ @{ $self->{extra_compiler_flags} } ];
  7         90  
153             }
154              
155             =head2 extra_linker_flags
156              
157             $flags = $cc->extra_linker_flags
158              
159             Returns the currently-configured extra linker flags in an ARRAY reference.
160              
161             =cut
162              
163             sub extra_linker_flags
164             {
165 5     5 1 12 my $self = shift;
166             # clone it just so caller can't modify ours
167 5         10 return [ @{ $self->{extra_linker_flags} } ];
  5         28  
168             }
169              
170             =head2 push_include_dirs
171              
172             $cc->push_include_dirs( @dirs )
173              
174             Adds more include directories
175              
176             =cut
177              
178             sub push_include_dirs
179             {
180 2     2 1 2170 my $self = shift;
181 2         4 push @{ $self->{include_dirs} }, @_;
  2         15  
182             }
183              
184             =head2 push_extra_compiler_flags
185              
186             $cc->push_extra_compiler_flags( @flags )
187              
188             Adds more compiler flags
189              
190             =cut
191              
192             sub push_extra_compiler_flags
193             {
194 3     3 1 21 my $self = shift;
195 3         10 push @{ $self->{extra_compiler_flags} }, @_;
  3         27  
196             }
197              
198             =head2 push_extra_linker_flags
199              
200             $cc->push_extra_linker_flags( @flags )
201              
202             Adds more linker flags
203              
204             =cut
205              
206             sub push_extra_linker_flags
207             {
208 2     2 1 8 my $self = shift;
209 2         8 push @{ $self->{extra_linker_flags} }, @_;
  2         9  
210             }
211              
212             sub cbuilder
213             {
214 12     12 0 29 my $self = shift;
215 12         262 return $self->{cb};
216             }
217              
218             sub compile
219             {
220 7     7 0 16 my $self = shift;
221 7         19 my %args = @_;
222              
223 7 100       39 $args{include_dirs} = [ map { defined $_ ? @$_ : () } $self->{include_dirs}, $args{include_dirs} ];
  14         58  
224 7 100       30 $args{extra_compiler_flags} = [ map { defined $_ ? @$_ : () } $self->{extra_compiler_flags}, $args{extra_compiler_flags} ];
  14         37  
225              
226 7         45 $self->cbuilder->compile( %args );
227             }
228              
229             sub link_executable
230             {
231 5     5 0 27 my $self = shift;
232 5         29 my %args = @_;
233              
234 5 100       90 $args{extra_linker_flags} = [ map { defined $_ ? @$_ : () } $self->{extra_linker_flags}, $args{extra_linker_flags} ];
  10         79  
235              
236 5         51 $self->cbuilder->link_executable( %args );
237             }
238              
239             sub fail
240             {
241 1     1 0 8 my $self = shift;
242 1         12 my ( $diag ) = @_;
243              
244 1 50       11 my $message = defined $diag ? "OS unsupported - $diag\n" : "OS unsupported\n";
245 1         40 die $message;
246             }
247              
248             sub define
249             {
250 2     2 1 33 my $self = shift;
251 2         34 my ( $symbol ) = @_;
252              
253 2 100       43 if( $self->{defines_to} ) {
254 1 50       10 unless( $self->{defines_fh} ) {
255 1 50       122 open $self->{defines_fh}, ">", $self->{defines_to} or croak "Cannot open $self->{defines_to} for writing - $!";
256 1         57 $self->{defines_fh}->autoflush(1);
257             }
258              
259 1         181 $self->{defines_fh}->print( "#define $symbol /**/\n" );
260             }
261             else {
262 1         34 $self->push_extra_compiler_flags( "-D$symbol" );
263             }
264             }
265              
266             =head2 try_compile_run
267              
268             $success = $cc->try_compile_run( %args )
269              
270             $success = $cc->try_compile_run( $source )
271              
272             Try to compile, link, and execute a C program whose source is given. Returns
273             true if the program compiled and linked, and exited successfully. Returns
274             false if any of these steps fail.
275              
276             Takes the following named arguments. If a single argument is given, that is
277             taken as the source string.
278              
279             =over 4
280              
281             =item source => STRING
282              
283             The source code of the C program to try compiling, building, and running.
284              
285             =item extra_compiler_flags => ARRAY
286              
287             Optional. If specified, pass extra flags to the compiler.
288              
289             =item extra_linker_flags => ARRAY
290              
291             Optional. If specified, pass extra flags to the linker.
292              
293             =item define => STRING
294              
295             Optional. If specified, then the named symbol will be defined if the program
296             ran successfully. This will either on the C compiler commandline (by passing
297             an option C<-DI>), or in the C file.
298              
299             =back
300              
301             =cut
302              
303             sub try_compile_run
304             {
305 7     7 1 1732 my $self = shift;
306 7 100       66 my %args = ( @_ == 1 ) ? ( source => $_[0] ) : @_;
307              
308 7 50       29 defined $args{source} or croak "Expected 'source'";
309              
310 7         52 my $seq = $self->{seq}++;
311              
312 7         36 my $test_source = "test-$$-$seq.c";
313              
314 7 50       850 open( my $test_source_fh, "> $test_source" ) or die "Cannot write $test_source - $!";
315              
316 7         128 print $test_source_fh $args{source};
317              
318 7         343 close $test_source_fh;
319              
320 7         49 my %compile_args = (
321             source => $test_source,
322             );
323              
324 7 50       42 $compile_args{include_dirs} = $args{include_dirs} if exists $args{include_dirs};
325 7 50       24 $compile_args{extra_compiler_flags} = $args{extra_compiler_flags} if exists $args{extra_compiler_flags};
326              
327 7         13 my $test_obj = eval { $self->compile( %compile_args ) };
  7         43  
328              
329 7         180170 unlink $test_source;
330              
331 7 100       152 if( not defined $test_obj ) {
332 2         135 return 0;
333             }
334              
335 5         73 my %link_args = (
336             objects => $test_obj,
337             );
338              
339 5 50       57 $link_args{extra_linker_flags} = $args{extra_linker_flags} if exists $args{extra_linker_flags};
340              
341 5         35 my $test_exe = eval { $self->link_executable( %link_args ) };
  5         73  
342              
343 5         152800 unlink $test_obj;
344              
345 5 50       83 if( not defined $test_exe ) {
346 0         0 return 0;
347             }
348              
349 5 50       13430 if( system( "./$test_exe" ) != 0 ) {
350 0         0 unlink $test_exe;
351 0         0 return 0;
352             }
353              
354 5         358 unlink $test_exe;
355              
356 5 100       152 $self->define( $args{define} ) if defined $args{define};
357              
358 5         574 return 1;
359             }
360              
361             =head2 assert_compile_run
362              
363             $cc->assert_compile_run( %args )
364              
365             Calls C. If it fails, die with an C message.
366             Useful to call from F or F.
367              
368             Takes one extra optional argument:
369              
370             =over 4
371              
372             =item diag => STRING
373              
374             If present, this string will be appended to the failure message if one is
375             generated. It may provide more useful information to the user on why the OS is
376             unsupported.
377              
378             =back
379              
380             =cut
381              
382             sub assert_compile_run
383             {
384 2     2 1 1410 my $self = shift;
385 2         18 my %args = @_;
386              
387 2         6 my $diag = delete $args{diag};
388 2 100       10 $self->try_compile_run( %args ) or $self->fail( $diag );
389             }
390              
391             =head2 try_find_cflags_for
392              
393             $success = $cc->try_find_cflags_for( %args )
394              
395             I
396              
397             Try to compile, link and execute the given source, using extra compiler flags.
398              
399             When a usable combination is found, the flags are stored in the object for use
400             in further compile operations, or returned by C. The
401             method then returns true.
402              
403             If no usable combination is found, it returns false.
404              
405             Takes the following extra arguments:
406              
407             =over 4
408              
409             =item source => STRING
410              
411             Source code to compile
412              
413             =item cflags => ARRAY of ARRAYs
414              
415             Gives a list of sets of flags. Each set of flags should be strings in its own
416             array reference.
417              
418             =item define => STRING
419              
420             Optional. If specified, then the named symbol will be defined if the program
421             ran successfully.
422              
423             =back
424              
425             =cut
426              
427             sub try_find_cflags_for
428             {
429 0     0 1 0 my $self = shift;
430 0         0 my %args = @_;
431              
432 0 0       0 ref( my $cflags = $args{cflags} ) eq "ARRAY" or croak "Expected 'cflags' as ARRAY ref";
433              
434 0         0 foreach my $f ( @$cflags ) {
435 0 0       0 ref $f eq "ARRAY" or croak "Expected 'cflags' element as ARRAY ref";
436              
437 0 0       0 $self->try_compile_run( %args, extra_compiler_flags => $f ) or next;
438              
439 0         0 $self->push_extra_compiler_flags( @$f );
440              
441 0         0 return 1;
442             }
443              
444 0         0 return 0;
445             }
446              
447             =head2 try_find_include_dirs_for
448              
449             $success = $cc->try_find_include_dirs_for( %args )
450              
451             Try to compile, link and execute the given source, using extra include
452             directories.
453              
454             When a usable combination is found, the directories required are stored in the
455             object for use in further compile operations, or returned by C.
456             The method then returns true.
457              
458             If no a usable combination is found, it returns false.
459              
460             Takes the following arguments:
461              
462             =over 4
463              
464             =item source => STRING
465              
466             Source code to compile
467              
468             =item dirs => ARRAY of ARRAYs
469              
470             Gives a list of sets of dirs. Each set of dirs should be strings in its own
471             array reference.
472              
473             =item define => STRING
474              
475             Optional. If specified, then the named symbol will be defined if the program
476             ran successfully. This will either on the C compiler commandline (by passing
477             an option C<-DI>), or in the C file.
478              
479             =back
480              
481             =cut
482              
483             sub try_find_include_dirs_for
484             {
485 0     0 1 0 my $self = shift;
486 0         0 my %args = @_;
487              
488 0 0       0 ref( my $dirs = $args{dirs} ) eq "ARRAY" or croak "Expected 'dirs' as ARRAY ref";
489              
490 0         0 foreach my $d ( @$dirs ) {
491 0 0       0 ref $d eq "ARRAY" or croak "Expected 'dirs' element as ARRAY ref";
492              
493 0 0       0 $self->try_compile_run( %args, include_dirs => $d ) or next;
494              
495 0         0 $self->push_include_dirs( @$d );
496              
497 0         0 return 1;
498             }
499              
500 0         0 return 0;
501             }
502              
503             =head2 try_find_libs_for
504              
505             $success = $cc->try_find_libs_for( %args )
506              
507             Try to compile, link and execute the given source, when linked against a
508             given set of extra libraries.
509              
510             When a usable combination is found, the libraries required are stored in the
511             object for use in further link operations, or returned by
512             C. The method then returns true.
513              
514             If no usable combination is found, it returns false.
515              
516             Takes the following arguments:
517              
518             =over 4
519              
520             =item source => STRING
521              
522             Source code to compile
523              
524             =item libs => ARRAY of STRINGs
525              
526             Gives a list of sets of libraries. Each set of libraries should be
527             space-separated.
528              
529             =item define => STRING
530              
531             Optional. If specified, then the named symbol will be defined if the program
532             ran successfully. This will either on the C compiler commandline (by passing
533             an option C<-DI>), or in the C file.
534              
535             =back
536              
537             =cut
538              
539             sub try_find_libs_for
540             {
541 0     0 1 0 my $self = shift;
542 0         0 my %args = @_;
543              
544 0 0       0 ref( my $libs = $args{libs} ) eq "ARRAY" or croak "Expected 'libs' as ARRAY ref";
545              
546 0         0 foreach my $l ( @$libs ) {
547 0         0 my @extra_linker_flags = map { "-l$_" } split m/\s+/, $l;
  0         0  
548              
549 0 0       0 $self->try_compile_run( %args, extra_linker_flags => \@extra_linker_flags ) or next;
550              
551 0         0 $self->push_extra_linker_flags( @extra_linker_flags );
552              
553 0         0 return 1;
554             }
555              
556 0         0 return 0;
557             }
558              
559             =head2 find_cflags_for
560              
561             $cc->find_cflags_for( %args )
562              
563             =head2 find_include_dirs_for
564              
565             $cc->find_include_dirs_for( %args )
566              
567             =head2 find_libs_for
568              
569             $cc->find_libs_for( %args )
570              
571             Calls C, C or
572             C respectively. If it fails, die with an
573             C message.
574              
575             Each method takes one extra optional argument:
576              
577             =over 4
578              
579             =item diag => STRING
580              
581             If present, this string will be appended to the failure message if one is
582             generated. It may provide more useful information to the user on why the OS is
583             unsupported.
584              
585             =back
586              
587             =cut
588              
589             foreach ( qw( find_cflags_for find_libs_for find_include_dirs_for ) ) {
590             my $trymethod = "try_$_";
591              
592             my $code = sub {
593 0     0   0 my $self = shift;
594 0         0 my %args = @_;
595              
596 0         0 my $diag = delete $args{diag};
597 0 0       0 $self->$trymethod( %args ) or $self->fail( $diag );
598             };
599              
600 7     7   60 no strict 'refs';
  7         26  
  7         1521  
601             *$_ = $code;
602             }
603              
604             =head2 extend_module_build
605              
606             $cc->extend_module_build( $build )
607              
608             I
609              
610             Sets the appropriate arguments into the given L instance.
611              
612             =cut
613              
614             sub extend_module_build
615             {
616 3     3 1 14 my $self = shift;
617 3         8 my ( $build ) = @_;
618              
619 3         84 foreach my $key (qw( include_dirs extra_compiler_flags extra_linker_flags )) {
620 9 100       56 my @vals = @{ $self->$key } or next;
  9         96  
621              
622 6         18 push @vals, @{ $build->$key };
  6         51  
623              
624             # Module::Build ->include_dirs wants an ARRAYref
625 6 100       109 $build->$key( $key eq "include_dirs" ? [ @vals ] : @vals );
626             }
627             }
628              
629             =head2 new_module_build
630              
631             $mb = $cc->new_module_build( %args )
632              
633             Construct and return a new L object, preconfigured with the
634             C, C and C options
635             that have been configured on this object, by the above methods.
636              
637             This is provided as a simple shortcut for the common use case, that a
638             F file is using the C object to detect the
639             required arguments to pass.
640              
641             =cut
642              
643             sub new_module_build
644             {
645 3     3 1 1925 my $self = shift;
646 3         13 my %args = @_;
647              
648 3         663 require Module::Build;
649 3         56028 my $build = Module::Build->new( %args );
650              
651 3         85404 $self->extend_module_build( $build );
652              
653 3         32 return $build;
654             }
655              
656             =head1 EXAMPLES
657              
658             =head2 Socket Libraries
659              
660             Some operating systems provide the BSD sockets API in their primary F.
661             Others keep it in a separate library which should be linked against. The
662             following example demonstrates how this would be handled.
663              
664             use ExtUtils::CChecker;
665              
666             my $cc = ExtUtils::CChecker->new;
667              
668             $cc->find_libs_for(
669             diag => "no socket()",
670             libs => [ "", "socket nsl" ],
671             source => q[
672             #include
673             int main(int argc, char *argv) {
674             int fd = socket(PF_INET, SOCK_STREAM, 0);
675             if(fd < 0)
676             return 1;
677             return 0;
678             }
679             ] );
680              
681             $cc->new_module_build(
682             module_name => "Your::Name::Here",
683             requires => {
684             'IO::Socket' => 0,
685             },
686             ...
687             )->create_build_script;
688              
689             By using the C method, the detected C
690             value has been automatically passed into the new C object.
691              
692             =head2 Testing For Optional Features
693              
694             Sometimes a function or ability may be optionally provided by the OS, or you
695             may wish your module to be useable when only partial support is provided,
696             without requiring it all to be present. In these cases it is traditional to
697             detect the presence of this optional feature in the F script, and
698             define a symbol to declare this fact if it is found. The XS code can then use
699             this symbol to select between differing implementations. For example, the
700             F:
701              
702             use ExtUtils::CChecker;
703              
704             my $cc = ExtUtils::CChecker->new;
705              
706             $cc->try_compile_run(
707             define => "HAVE_MANGO",
708             source => <<'EOF' );
709             #include
710             #include
711             int main(void) {
712             if(mango() != 0)
713             exit(1);
714             exit(0);
715             }
716             EOF
717              
718             $cc->new_module_build(
719             ...
720             )->create_build_script;
721              
722             If the C code compiles and runs successfully, and exits with a true status,
723             the symbol C will be defined on the compiler commandline. This
724             allows the XS code to detect it, for example
725              
726             int
727             mango()
728             CODE:
729             #ifdef HAVE_MANGO
730             RETVAL = mango();
731             #else
732             croak("mango() not implemented");
733             #endif
734             OUTPUT:
735             RETVAL
736              
737             This module will then still compile even if the operating system lacks this
738             particular function. Trying to invoke the function at runtime will simply
739             throw an exception.
740              
741             =head2 Linux Kernel Headers
742              
743             Operating systems built on top of the F kernel often share a looser
744             association with their kernel version than most other operating systems. It
745             may be the case that the running kernel is newer, containing more features,
746             than the distribution's F headers would believe. In such circumstances
747             it can be difficult to make use of new socket options, Cs, etc..
748             without having the constants that define them and their parameter structures,
749             because the relevant header files are not visible to the compiler. In this
750             case, there may be little choice but to pull in some of the kernel header
751             files, which will provide the required constants and structures.
752              
753             The Linux kernel headers can be found using the F directory. A
754             fragment in F like the following, may be appropriate.
755              
756             chomp( my $uname_r = `uname -r` );
757              
758             my @dirs = (
759             [],
760             [ "/lib/modules/$uname_r/source/include" ],
761             );
762              
763             $cc->find_include_dirs_for(
764             diag => "no PF_MOONLASER",
765             dirs => \@dirs,
766             source => <<'EOF' );
767             #include
768             #include
769             int family = PF_MOONLASER;
770             struct laserwl lwl;
771             int main(int argc, char *argv[]) {
772             return 0;
773             }
774             EOF
775              
776             This fragment will first try to compile the program as it stands, hoping that
777             the F headers will be sufficient. If it fails, it will then try
778             including the kernel headers, which should make the constant and structure
779             visible, allowing the program to compile.
780              
781             =head2 Creating an C<#include> file
782              
783             Sometimes, rather than setting defined symbols on the compiler commandline, it
784             is preferrable to have them written to a C preprocessor include (F<.h>) file.
785             This may be beneficial for cross-platform portability concerns, as not all C
786             compilers may take extra C<-D> arguments on the command line, or platforms may
787             have small length restrictions on the length of a command line.
788              
789             use ExtUtils::CChecker;
790              
791             my $cc = ExtUtils::CChecker->new(
792             defines_to => "mymodule-config.h",
793             );
794              
795             $cc->try_compile_run(
796             define => "HAVE_MANGO",
797             source => <<'EOF' );
798             #include
799             #include
800             #include "mymodule-config.h"
801             int main(void) {
802             if(mango() != 0)
803             exit(1);
804             exit(0);
805             }
806             EOF
807              
808             Because the F file is written and flushed after every
809             define operation, it will still be useable in later C fragments to test for
810             features detected in earlier ones.
811              
812             It is suggested not to name the file simply F, as the core of Perl
813             itself has a file of that name containing its own compile-time detected
814             configuration. A confusion between the two could lead to surprising results.
815              
816             =head1 AUTHOR
817              
818             Paul Evans
819              
820             =cut
821              
822             0x55AA;