| 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; |