File Coverage

blib/lib/Module/Install/XSUtil.pm
Criterion Covered Total %
statement 24 354 6.7
branch 1 142 0.7
condition 0 47 0.0
subroutine 8 42 19.0
pod 18 19 94.7
total 51 604 8.4


line stmt bran cond sub pod time code
1             package Module::Install::XSUtil;
2              
3 1     1   22295 use 5.005_03;
  1         3  
  1         42  
4              
5             $VERSION = '0.45';
6              
7 1     1   631 use Module::Install::Base;
  1         3  
  1         35  
8             @ISA = qw(Module::Install::Base);
9              
10 1     1   6 use strict;
  1         2  
  1         26  
11              
12 1     1   6 use Config;
  1         1  
  1         42  
13              
14 1     1   5 use File::Spec;
  1         2  
  1         21  
15 1     1   7 use File::Find;
  1         1  
  1         116  
16              
17 1 50   1   6 use constant _VERBOSE => $ENV{MI_VERBOSE} ? 1 : 0;
  1         2  
  1         1203  
18              
19             my %ConfigureRequires = (
20             'ExtUtils::ParseXS' => 3.18, # shipped with Perl 5.18.0
21             );
22              
23             my %BuildRequires = (
24             );
25              
26             my %Requires = (
27             'XSLoader' => 0.02,
28             );
29              
30             my %ToInstall;
31              
32             my $UseC99 = 0;
33             my $UseCplusplus = 0;
34              
35             sub _verbose{
36 0     0     print STDERR q{# }, @_, "\n";
37             }
38              
39             sub _xs_debugging{
40 0   0 0     return $ENV{XS_DEBUG} || scalar( grep{ $_ eq '-g' } @ARGV );
41             }
42              
43             sub _xs_initialize{
44 0     0     my($self) = @_;
45              
46 0 0         unless($self->{xsu_initialized}){
47 0           $self->{xsu_initialized} = 1;
48              
49 0 0         if(!$self->cc_available()){
50 0           warn "This distribution requires a C compiler, but it's not available, stopped.\n";
51 0           exit;
52             }
53              
54 0           $self->configure_requires(%ConfigureRequires);
55 0           $self->build_requires(%BuildRequires);
56 0           $self->requires(%Requires);
57              
58 0           $self->makemaker_args->{OBJECT} = '$(O_FILES)';
59 0           $self->clean_files('$(O_FILES)');
60 0 0         $self->clean_files('*.stackdump') if $^O eq 'cygwin';
61              
62 0 0         if($self->_xs_debugging()){
63             # override $Config{optimize}
64 0 0         if(_is_msvc()){
65 0           $self->makemaker_args->{OPTIMIZE} = '-Zi';
66             }
67             else{
68 0           $self->makemaker_args->{OPTIMIZE} = '-g -ggdb -g3';
69             }
70 0           $self->cc_define('-DXS_ASSERT');
71             }
72             }
73 0           return;
74             }
75              
76             # GNU C Compiler
77             sub _is_gcc{
78 0     0     return $Config{gccversion};
79             }
80              
81             # Microsoft Visual C++ Compiler (cl.exe)
82             sub _is_msvc{
83 0     0     return $Config{cc} =~ /\A cl \b /xmsi;
84             }
85              
86             {
87             my $cc_available;
88              
89             sub cc_available {
90 0 0   0 1   return defined $cc_available ?
91             $cc_available :
92             ($cc_available = shift->can_cc())
93             ;
94             }
95              
96             # cf. https://github.com/sjn/toolchain-site/blob/219db464af9b2f19b04fec05547ac10180a469f3/lancaster-consensus.md
97             my $want_xs;
98             sub want_xs {
99 0     0 1   my($self, $default) = @_;
100 0 0         return $want_xs if defined $want_xs;
101              
102             # you're using this module, you must want XS by default
103             # unless PERL_ONLY is true.
104 0 0         $default = !$ENV{PERL_ONLY} if not defined $default;
105              
106 0           foreach my $arg(@ARGV){
107              
108 0           my ($k, $v) = split '=', $arg; # MM-style named args
109 0 0 0       if ($k eq 'PUREPERL_ONLY' && defined $v) {
    0          
    0          
110 0           return $want_xs = !$v;
111             }
112             elsif($arg eq '--pp'){ # old-style
113 0           return $want_xs = 0;
114             }
115             elsif($arg eq '--xs'){
116 0           return $want_xs = 1;
117             }
118             }
119              
120 0 0         if ($ENV{PERL_MM_OPT}) {
121 0           my($v) = $ENV{PERL_MM_OPT} =~ /\b PUREPERL_ONLY = (\S+) /xms;
122 0 0         if (defined $v) {
123 0           return $want_xs = !$v;
124             }
125             }
126              
127 0           return $want_xs = $default;
128             }
129             }
130              
131             sub use_ppport{
132 0     0 1   my($self, $dppp_version) = @_;
133 0 0         return if $self->{_ppport_ok}++;
134              
135 0           $self->_xs_initialize();
136              
137 0           my $filename = 'ppport.h';
138              
139 0   0       $dppp_version ||= 3.19; # the more, the better
140 0           $self->configure_requires('Devel::PPPort' => $dppp_version);
141 0           $self->build_requires('Devel::PPPort' => $dppp_version);
142              
143 0           print "Writing $filename\n";
144              
145 0           my $e = do{
146 0           local $@;
147 0           eval qq{
148             use Devel::PPPort;
149             Devel::PPPort::WriteFile(q{$filename});
150             };
151 0           $@;
152             };
153 0 0         if($e){
154 0           print "Cannot create $filename because: $@\n";
155             }
156              
157 0 0         if(-e $filename){
158 0           $self->clean_files($filename);
159 0           $self->cc_define('-DUSE_PPPORT');
160 0           $self->cc_append_to_inc('.');
161             }
162 0           return;
163             }
164              
165             sub use_xshelper {
166 0     0 1   my($self, $opt) = @_;
167 0           $self->_xs_initialize();
168 0           $self->use_ppport();
169              
170 0           my $file = 'xshelper.h';
171 0 0         open my $fh, '>', $file or die "Cannot open $file for writing: $!";
172 0           print $fh $self->_xshelper_h();
173 0 0         close $fh or die "Cannot close $file: $!";
174 0 0         if(defined $opt) {
175 0 0         if($opt eq '-clean') {
176 0           $self->clean_files($file);
177             }
178             else {
179 0           $self->realclean_files($file);
180             }
181             }
182 0           return;
183             }
184              
185             sub _gccversion {
186 0     0     my $res = `$Config{cc} --version`;
187 0           my ($version) = $res =~ /\(GCC\) ([0-9.]+)/;
188 1     1   8 no warnings 'numeric', 'uninitialized';
  1         13  
  1         4536  
189 0           return sprintf '%g', $version;
190             }
191              
192             sub cc_warnings{
193 0     0 1   my($self) = @_;
194              
195 0           $self->_xs_initialize();
196              
197 0 0         if(_is_gcc()){
    0          
198 0           $self->cc_append_to_ccflags(qw(-Wall));
199              
200 0           my $gccversion = _gccversion();
201 0 0         if($gccversion >= 4.0){
202 0           $self->cc_append_to_ccflags(qw(-Wextra));
203 0 0 0       if(!($UseC99 or $UseCplusplus)) {
204             # Note: MSVC++ doesn't support C99,
205             # so -Wdeclaration-after-statement helps
206             # ensure C89 specs.
207 0           $self->cc_append_to_ccflags(qw(-Wdeclaration-after-statement));
208             }
209 0 0 0       if($gccversion >= 4.1 && !$UseCplusplus) {
210 0           $self->cc_append_to_ccflags(qw(-Wc++-compat));
211             }
212             }
213             else{
214 0           $self->cc_append_to_ccflags(qw(-W -Wno-comment));
215             }
216             }
217             elsif(_is_msvc()){
218 0           $self->cc_append_to_ccflags(qw(-W3));
219             }
220             else{
221             # TODO: support other compilers
222             }
223              
224 0           return;
225             }
226              
227             sub c99_available {
228 0     0 1   my($self) = @_;
229              
230 0 0         return 0 if not $self->cc_available();
231              
232 0           require File::Temp;
233 0           require File::Basename;
234              
235 0           my $tmpfile = File::Temp->new(SUFFIX => '.c');
236              
237 0           $tmpfile->print(<<'C99');
238             // include a C99 header
239             #include
240             inline // a C99 keyword with C99 style comments
241             int test_c99() {
242             int i = 0;
243             i++;
244             int j = i - 1; // another C99 feature: declaration after statement
245             return j;
246             }
247             C99
248              
249 0           $tmpfile->close();
250              
251 0           system "$Config{cc} -c " . $tmpfile->filename;
252              
253 0           (my $objname = File::Basename::basename($tmpfile->filename)) =~ s/\Q.c\E$/$Config{_o}/;
254 0 0         unlink $objname or warn "Cannot unlink $objname (ignored): $!";
255              
256 0           return $? == 0;
257             }
258              
259             sub requires_c99 {
260 0     0 1   my($self) = @_;
261 0 0         if(!$self->c99_available) {
262 0           warn "This distribution requires a C99 compiler, but $Config{cc} seems not to support C99, stopped.\n";
263 0           exit;
264             }
265 0           $self->_xs_initialize();
266 0           $UseC99 = 1;
267 0           return;
268             }
269              
270             sub requires_cplusplus {
271 0     0 1   my($self) = @_;
272 0 0         if(!$self->cc_available) {
273 0           warn "This distribution requires a C++ compiler, but $Config{cc} seems not to support C++, stopped.\n";
274 0           exit;
275             }
276 0           $self->_xs_initialize();
277 0           $UseCplusplus = 1;
278 0           return;
279             }
280              
281             sub cc_append_to_inc{
282 0     0 1   my($self, @dirs) = @_;
283              
284 0           $self->_xs_initialize();
285              
286 0           for my $dir(@dirs){
287 0 0         unless(-d $dir){
288 0           warn("'$dir' not found: $!\n");
289             }
290              
291 0           _verbose "inc: -I$dir" if _VERBOSE;
292             }
293              
294 0           my $mm = $self->makemaker_args;
295 0           my $paths = join q{ }, map{ s{\\}{\\\\}g; qq{"-I$_"} } @dirs;
  0            
  0            
296              
297 0 0         if($mm->{INC}){
298 0           $mm->{INC} .= q{ } . $paths;
299             }
300             else{
301 0           $mm->{INC} = $paths;
302             }
303 0           return;
304             }
305              
306             sub cc_libs {
307 0     0 1   my ($self, @libs) = @_;
308              
309 0           @libs = map{
310 0 0         my($name, $dir) = ref($_) eq 'ARRAY' ? @{$_} : ($_, undef);
  0            
311 0           my $lib;
312 0 0         if(defined $dir) {
313 0 0         $lib = ($dir =~ /^-/ ? qq{$dir } : qq{-L$dir });
314             }
315             else {
316 0           $lib = '';
317             }
318 0 0         $lib .= ($name =~ /^-/ ? qq{$name} : qq{-l$name});
319 0           _verbose "libs: $lib" if _VERBOSE;
320 0           $lib;
321             } @libs;
322              
323 0           $self->cc_append_to_libs( @libs );
324             }
325              
326             sub cc_append_to_libs{
327 0     0 1   my($self, @libs) = @_;
328              
329 0           $self->_xs_initialize();
330              
331 0 0         return unless @libs;
332              
333 0           my $libs = join q{ }, @libs;
334              
335 0           my $mm = $self->makemaker_args;
336              
337 0 0         if ($mm->{LIBS}){
338 0           $mm->{LIBS} .= q{ } . $libs;
339             }
340             else{
341 0           $mm->{LIBS} = $libs;
342             }
343 0           return $libs;
344             }
345              
346             sub cc_assert_lib {
347 0     0 1   my ($self, @dcl_args) = @_;
348              
349 0 0         if ( ! $self->{xsu_loaded_checklib} ) {
350 0           my $loaded_lib = 0;
351 0           foreach my $checklib (qw(inc::Devel::CheckLib Devel::CheckLib)) {
352 0           eval "use $checklib 0.4";
353 0 0         if (!$@) {
354 0           $loaded_lib = 1;
355 0           last;
356             }
357             }
358              
359 0 0         if (! $loaded_lib) {
360 0           warn "Devel::CheckLib not found in inc/ nor \@INC";
361 0           exit 0;
362             }
363              
364 0           $self->{xsu_loaded_checklib}++;
365 0           $self->configure_requires( "Devel::CheckLib" => "0.4" );
366 0           $self->build_requires( "Devel::CheckLib" => "0.4" );
367             }
368              
369 0           Devel::CheckLib::check_lib_or_exit(@dcl_args);
370             }
371              
372             sub cc_append_to_ccflags{
373 0     0 1   my($self, @ccflags) = @_;
374              
375 0           $self->_xs_initialize();
376              
377 0           my $mm = $self->makemaker_args;
378              
379 0   0       $mm->{CCFLAGS} ||= $Config{ccflags};
380 0           $mm->{CCFLAGS} .= q{ } . join q{ }, @ccflags;
381 0           return;
382             }
383              
384             sub cc_define{
385 0     0 1   my($self, @defines) = @_;
386              
387 0           $self->_xs_initialize();
388              
389 0           my $mm = $self->makemaker_args;
390 0 0         if(exists $mm->{DEFINE}){
391 0           $mm->{DEFINE} .= q{ } . join q{ }, @defines;
392             }
393             else{
394 0           $mm->{DEFINE} = join q{ }, @defines;
395             }
396 0           return;
397             }
398              
399             sub requires_xs_module {
400 0     0 0   my $self = shift;
401              
402 0 0         return $self->requires() unless @_;
403              
404 0           $self->_xs_initialize();
405              
406 0           my %added = $self->requires(@_);
407 0           my(@inc, @libs);
408              
409 0           my $rx_lib = qr{ \. (?: lib | a) \z}xmsi;
410 0           my $rx_dll = qr{ \. dll \z}xmsi; # for Cygwin
411              
412 0           while(my $module = each %added){
413 0           my $mod_basedir = File::Spec->join(split /::/, $module);
414 0           my $rx_header = qr{\A ( .+ \Q$mod_basedir\E ) .+ \. h(?:pp)? \z}xmsi;
415              
416 0           SCAN_INC: foreach my $inc_dir(@INC){
417 0           my @dirs = grep{ -e } File::Spec->join($inc_dir, 'auto', $mod_basedir), File::Spec->join($inc_dir, $mod_basedir);
  0            
418              
419 0 0         next SCAN_INC unless @dirs;
420              
421 0           my $n_inc = scalar @inc;
422             find(sub{
423 0 0   0     if(my($incdir) = $File::Find::name =~ $rx_header){
    0          
    0          
424 0           push @inc, $incdir;
425             }
426             elsif($File::Find::name =~ $rx_lib){
427 0           my($libname) = $_ =~ /\A (?:lib)? (\w+) /xmsi;
428 0           push @libs, [$libname, $File::Find::dir];
429             }
430             elsif($File::Find::name =~ $rx_dll){
431             # XXX: hack for Cygwin
432 0           my $mm = $self->makemaker_args;
433 0   0       $mm->{macro}->{PERL_ARCHIVE_AFTER} ||= '';
434 0           $mm->{macro}->{PERL_ARCHIVE_AFTER} .= ' ' . $File::Find::name;
435             }
436 0           }, @dirs);
437              
438 0 0         if($n_inc != scalar @inc){
439 0           last SCAN_INC;
440             }
441             }
442             }
443              
444 0           my %uniq = ();
445 0           $self->cc_append_to_inc (grep{ !$uniq{ $_ }++ } @inc);
  0            
446              
447 0           %uniq = ();
448 0           $self->cc_libs(grep{ !$uniq{ $_->[0] }++ } @libs);
  0            
449              
450 0           return %added;
451             }
452              
453             sub cc_src_paths{
454 0     0 1   my($self, @dirs) = @_;
455              
456 0           $self->_xs_initialize();
457              
458 0 0         return unless @dirs;
459              
460 0           my $mm = $self->makemaker_args;
461              
462 0   0       my $XS_ref = $mm->{XS} ||= {};
463 0   0       my $C_ref = $mm->{C} ||= [];
464              
465 0           my $_obj = $Config{_o};
466              
467 0           my @src_files;
468             find(sub{
469 0 0   0     if(/ \. (?: xs | c (?: c | pp | xx )? ) \z/xmsi){ # *.{xs, c, cc, cpp, cxx}
470 0           push @src_files, $File::Find::name;
471             }
472 0           }, @dirs);
473              
474 0 0         my $xs_to = $UseCplusplus ? '.cpp' : '.c';
475 0           foreach my $src_file(@src_files){
476 0           my $c = $src_file;
477 0 0         if($c =~ s/ \.xs \z/$xs_to/xms){
478 0           $XS_ref->{$src_file} = $c;
479              
480 0           _verbose "xs: $src_file" if _VERBOSE;
481             }
482             else{
483 0           _verbose "c: $c" if _VERBOSE;
484             }
485              
486 0 0         push @{$C_ref}, $c unless grep{ $_ eq $c } @{$C_ref};
  0            
  0            
  0            
487             }
488              
489 0           $self->clean_files(map{
490 0           File::Spec->catfile($_, '*.gcov'),
491             File::Spec->catfile($_, '*.gcda'),
492             File::Spec->catfile($_, '*.gcno'),
493             } @dirs);
494 0           $self->cc_append_to_inc('.');
495              
496 0           return;
497             }
498              
499             sub cc_include_paths{
500 0     0 1   my($self, @dirs) = @_;
501              
502 0           $self->_xs_initialize();
503              
504 0   0       push @{ $self->{xsu_include_paths} ||= []}, @dirs;
  0            
505              
506 0   0       my $h_map = $self->{xsu_header_map} ||= {};
507              
508 0           foreach my $dir(@dirs){
509 0           my $prefix = quotemeta( File::Spec->catfile($dir, '') );
510             find(sub{
511 0 0   0     return unless / \.h(?:pp)? \z/xms;
512              
513 0           (my $h_file = $File::Find::name) =~ s/ \A $prefix //xms;
514 0           $h_map->{$h_file} = $File::Find::name;
515 0           }, $dir);
516             }
517              
518 0           $self->cc_append_to_inc(@dirs);
519              
520 0           return;
521             }
522              
523             sub install_headers{
524 0     0 1   my $self = shift;
525 0           my $h_files;
526 0 0 0       if(@_ == 0){
    0          
527 0 0         $h_files = $self->{xsu_header_map} or die "install_headers: cc_include_paths not specified.\n";
528             }
529             elsif(@_ == 1 && ref($_[0]) eq 'HASH'){
530 0           $h_files = $_[0];
531             }
532             else{
533 0           $h_files = +{ map{ $_ => undef } @_ };
  0            
534             }
535              
536 0           $self->_xs_initialize();
537              
538 0           my @not_found;
539 0   0       my $h_map = $self->{xsu_header_map} || {};
540              
541 0           while(my($ident, $path) = each %{$h_files}){
  0            
542 0   0       $path ||= $h_map->{$ident} || File::Spec->join('.', $ident);
      0        
543 0           $path = File::Spec->canonpath($path);
544              
545 0 0 0       unless($path && -e $path){
546 0           push @not_found, $ident;
547 0           next;
548             }
549              
550 0           $ToInstall{$path} = File::Spec->join('$(INST_ARCHAUTODIR)', $ident);
551              
552 0           _verbose "install: $path as $ident" if _VERBOSE;
553 0           my @funcs = $self->_extract_functions_from_header_file($path);
554 0 0         if(@funcs){
555 0           $self->cc_append_to_funclist(@funcs);
556             }
557             }
558              
559 0 0         if(@not_found){
560 0           die "Header file(s) not found: @not_found\n";
561             }
562              
563 0           return;
564             }
565              
566             my $home_directory;
567              
568             sub _extract_functions_from_header_file{
569 0     0     my($self, $h_file) = @_;
570              
571 0           my @functions;
572              
573 0 0         ($home_directory) = <~> unless defined $home_directory;
574              
575             # get header file contents through cpp(1)
576 0           my $contents = do {
577 0           my $mm = $self->makemaker_args;
578              
579 0           my $cppflags = q{"-I}. File::Spec->join($Config{archlib}, 'CORE') . q{"};
580 0           $cppflags =~ s/~/$home_directory/g;
581              
582 0 0         $cppflags .= ' ' . $mm->{INC} if $mm->{INC};
583              
584 0   0       $cppflags .= ' ' . ($mm->{CCFLAGS} || $Config{ccflags});
585 0 0         $cppflags .= ' ' . $mm->{DEFINE} if $mm->{DEFINE};
586              
587 0 0         my $add_include = _is_msvc() ? '-FI' : '-include';
588 0           $cppflags .= ' ' . join ' ',
589 0           map{ qq{$add_include "$_"} } qw(EXTERN.h perl.h XSUB.h);
590              
591 0           my $cppcmd = qq{$Config{cpprun} $cppflags $h_file};
592             # remove all the -arch options to workaround gcc errors:
593             # "-E, -S, -save-temps and -M options are not allowed
594             # with multiple -arch flags"
595 0           $cppcmd =~ s/ -arch \s* \S+ //xmsg;
596 0           _verbose("extract functions from: $cppcmd") if _VERBOSE;
597 0           `$cppcmd`;
598             };
599              
600 0 0         unless(defined $contents){
601 0           die "Cannot call C pre-processor ($Config{cpprun}): $! ($?)";
602             }
603              
604             # remove other include file contents
605 0           my $chfile = q/\# (?:line)? \s+ \d+ /;
606 0           $contents =~ s{
607             ^$chfile \s+ (?!"\Q$h_file\E")
608             .*?
609             ^(?= $chfile)
610             }{}xmsig;
611              
612 0           if(_VERBOSE){
613             local *H;
614             open H, "> $h_file.out"
615             and print H $contents
616             and close H;
617             }
618              
619 0           while($contents =~ m{
620             ([^\\;\s]+ # type
621             \s+
622             ([a-zA-Z_][a-zA-Z0-9_]*) # function name
623             \s*
624             \( [^;#]* \) # argument list
625             [\w\s\(\)]* # attributes or something
626             ;) # end of declaration
627             }xmsg){
628 0           my $decl = $1;
629 0           my $name = $2;
630              
631 0 0         next if $decl =~ /\b typedef \b/xms;
632 0 0         next if $name =~ /^_/xms; # skip something private
633              
634 0           push @functions, $name;
635              
636 0           if(_VERBOSE){
637             $decl =~ tr/\n\r\t / /s;
638             $decl =~ s/ (\Q$name\E) /<$name>/xms;
639             _verbose("decl: $decl");
640             }
641             }
642              
643 0           return @functions;
644             }
645              
646              
647             sub cc_append_to_funclist{
648 0     0 1   my($self, @functions) = @_;
649              
650 0           $self->_xs_initialize();
651              
652 0           my $mm = $self->makemaker_args;
653              
654 0   0       push @{$mm->{FUNCLIST} ||= []}, @functions;
  0            
655 0   0       $mm->{DL_FUNCS} ||= { '$(NAME)' => [] };
656              
657 0           return;
658             }
659              
660             sub _xshelper_h {
661 0     0     my $h = <<'XSHELPER_H';
662             :/* THIS FILE IS AUTOMATICALLY GENERATED BY Module::Install::XSUtil $VERSION. */
663             :/*
664             :=head1 NAME
665             :
666             :xshelper.h - Helper C header file for XS modules
667             :
668             :=head1 DESCRIPTION
669             :
670             : // This includes all the perl header files and ppport.h
671             : #include "xshelper.h"
672             :
673             :=head1 SEE ALSO
674             :
675             :L, where this file is distributed as a part of
676             :
677             :=head1 AUTHOR
678             :
679             :Fuji, Goro (gfx) Egfuji at cpan.orgE
680             :
681             :=head1 LISENCE
682             :
683             :Copyright (c) 2010, Fuji, Goro (gfx). All rights reserved.
684             :
685             :This library is free software; you can redistribute it and/or modify
686             :it under the same terms as Perl itself.
687             :
688             :=cut
689             :*/
690             :
691             :#ifdef __cplusplus
692             :extern "C" {
693             :#endif
694             :
695             :#define PERL_NO_GET_CONTEXT /* we want efficiency */
696             :#include
697             :#include
698             :#define NO_XSLOCKS /* for exceptions */
699             :#include
700             :
701             :#ifdef __cplusplus
702             :} /* extern "C" */
703             :#endif
704             :
705             :#include "ppport.h"
706             :
707             :/* portability stuff not supported by ppport.h yet */
708             :
709             :#ifndef STATIC_INLINE /* from 5.13.4 */
710             :# if defined(__GNUC__) || defined(__cplusplus) || (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L))
711             :# define STATIC_INLINE static inline
712             :# else
713             :# define STATIC_INLINE static
714             :# endif
715             :#endif /* STATIC_INLINE */
716             :
717             :#ifndef __attribute__format__
718             :#define __attribute__format__(a,b,c) /* nothing */
719             :#endif
720             :
721             :#ifndef LIKELY /* they are just a compiler's hint */
722             :#define LIKELY(x) (!!(x))
723             :#define UNLIKELY(x) (!!(x))
724             :#endif
725             :
726             :#ifndef newSVpvs_share
727             :#define newSVpvs_share(s) Perl_newSVpvn_share(aTHX_ STR_WITH_LEN(s), 0U)
728             :#endif
729             :
730             :#ifndef get_cvs
731             :#define get_cvs(name, flags) get_cv(name, flags)
732             :#endif
733             :
734             :#ifndef GvNAME_get
735             :#define GvNAME_get GvNAME
736             :#endif
737             :#ifndef GvNAMELEN_get
738             :#define GvNAMELEN_get GvNAMELEN
739             :#endif
740             :
741             :#ifndef CvGV_set
742             :#define CvGV_set(cv, gv) (CvGV(cv) = (gv))
743             :#endif
744             :
745             :/* general utility */
746             :
747             :#if PERL_BCDVERSION >= 0x5008005
748             :#define LooksLikeNumber(x) looks_like_number(x)
749             :#else
750             :#define LooksLikeNumber(x) (SvPOKp(x) ? looks_like_number(x) : (I32)SvNIOKp(x))
751             :#endif
752             :
753             :#define newAV_mortal() (AV*)sv_2mortal((SV*)newAV())
754             :#define newHV_mortal() (HV*)sv_2mortal((SV*)newHV())
755             :#define newRV_inc_mortal(sv) sv_2mortal(newRV_inc(sv))
756             :#define newRV_noinc_mortal(sv) sv_2mortal(newRV_noinc(sv))
757             :
758             :#define DECL_BOOT(name) EXTERN_C XS(CAT2(boot_, name))
759             :#define CALL_BOOT(name) STMT_START { \
760             : PUSHMARK(SP); \
761             : CALL_FPTR(CAT2(boot_, name))(aTHX_ cv); \
762             : } STMT_END
763             XSHELPER_H
764 0           $h =~ s/^://xmsg;
765 0           $h =~ s/\$VERSION\b/$Module::Install::XSUtil::VERSION/xms;
766 0           return $h;
767             }
768              
769             package
770             MY;
771              
772             # XXX: We must append to PM inside ExtUtils::MakeMaker->new().
773             sub init_PM {
774 0     0     my $self = shift;
775              
776 0           $self->SUPER::init_PM(@_);
777              
778 0           while(my($k, $v) = each %ToInstall){
779 0           $self->{PM}{$k} = $v;
780             }
781 0           return;
782             }
783              
784             # append object file names to CCCMD
785             sub const_cccmd {
786 0     0     my $self = shift;
787              
788 0           my $cccmd = $self->SUPER::const_cccmd(@_);
789 0 0         return q{} unless $cccmd;
790              
791 0 0         if (Module::Install::XSUtil::_is_msvc()){
792 0           $cccmd .= ' -Fo$@';
793             }
794             else {
795 0           $cccmd .= ' -o $@';
796             }
797              
798 0           return $cccmd
799             }
800              
801             sub xs_c {
802 0     0     my($self) = @_;
803 0           my $mm = $self->SUPER::xs_c();
804 0 0         $mm =~ s/ \.c /.cpp/xmsg if $UseCplusplus;
805 0           return $mm;
806             }
807              
808             sub xs_o {
809 0     0     my($self) = @_;
810 0           my $mm = $self->SUPER::xs_o();
811 0 0         $mm =~ s/ \.c /.cpp/xmsg if $UseCplusplus;
812 0           return $mm;
813             }
814              
815             1;
816             __END__