File Coverage

blib/lib/ExtUtils/CChecker.pm
Criterion Covered Total %
statement 108 143 75.5
branch 31 60 51.6
condition 1 3 33.3
subroutine 21 25 84.0
pod 15 19 78.9
total 176 250 70.4


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