| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | =head1 NAME | 
| 2 |  |  |  |  |  |  |  | 
| 3 |  |  |  |  |  |  | ExtUtils::CXX - support C++ XS files | 
| 4 |  |  |  |  |  |  |  | 
| 5 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 6 |  |  |  |  |  |  |  | 
| 7 |  |  |  |  |  |  | use ExtUtils::CXX; | 
| 8 |  |  |  |  |  |  | use ExtUtils::MakeMaker; | 
| 9 |  |  |  |  |  |  |  | 
| 10 |  |  |  |  |  |  | # wrap calls to WriteMakefile or MakeMaker that are supposed to use | 
| 11 |  |  |  |  |  |  | # C++ XS files into extutils_cxx blocks: | 
| 12 |  |  |  |  |  |  |  | 
| 13 |  |  |  |  |  |  | extutils_cxx { | 
| 14 |  |  |  |  |  |  | WriteMakefile ( | 
| 15 |  |  |  |  |  |  | ...  put your normal args here | 
| 16 |  |  |  |  |  |  | ); | 
| 17 |  |  |  |  |  |  | }; | 
| 18 |  |  |  |  |  |  |  | 
| 19 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 20 |  |  |  |  |  |  |  | 
| 21 |  |  |  |  |  |  | This module enables XS extensions written in C++. It is meant to be useful | 
| 22 |  |  |  |  |  |  | for the users and installers of c++ modules, rather than the authors, by | 
| 23 |  |  |  |  |  |  | having a single central place where to patch things, rather than to have | 
| 24 |  |  |  |  |  |  | to patch every single module that overrides CC manually. That is, in the | 
| 25 |  |  |  |  |  |  | worst case, you need to patch this module for your environment before | 
| 26 |  |  |  |  |  |  | being able to CPAN-install further C++ modules; commonly, only setting a | 
| 27 |  |  |  |  |  |  | few ENV variables is enough; and in the best case, it just works out of | 
| 28 |  |  |  |  |  |  | the box. | 
| 29 |  |  |  |  |  |  |  | 
| 30 |  |  |  |  |  |  | (Comments on what to do and suggestions on how to achieve these things | 
| 31 |  |  |  |  |  |  | better are welcome). | 
| 32 |  |  |  |  |  |  |  | 
| 33 |  |  |  |  |  |  | At the moment, it works by changing the values in C<%Config::Config> | 
| 34 |  |  |  |  |  |  | temporarily. It does the following things: | 
| 35 |  |  |  |  |  |  |  | 
| 36 |  |  |  |  |  |  | =over 4 | 
| 37 |  |  |  |  |  |  |  | 
| 38 |  |  |  |  |  |  | =item 1. It tries to change C<$Config{cc}> and C<$Config{ld}> into a C++ compiler. | 
| 39 |  |  |  |  |  |  |  | 
| 40 |  |  |  |  |  |  | If the environment variable C<$CXX> is set, then it's value will be used | 
| 41 |  |  |  |  |  |  | to replace both (except if C<$PERL_CXXLD> is set, then that will be used for | 
| 42 |  |  |  |  |  |  | C<$Config{ld}>. | 
| 43 |  |  |  |  |  |  |  | 
| 44 |  |  |  |  |  |  | (There is also a C<$PERL_CXX> which takes precedence over C<$CXX>). | 
| 45 |  |  |  |  |  |  |  | 
| 46 |  |  |  |  |  |  | The important thing is that the chosen C++ compiler compiles files with | 
| 47 |  |  |  |  |  |  | a F<.c> ending as C++ - a generic compiler wrapper such as F that | 
| 48 |  |  |  |  |  |  | detects the lafguage by the file extension will I work. | 
| 49 |  |  |  |  |  |  |  | 
| 50 |  |  |  |  |  |  | In the absence of these variables, it will do the following | 
| 51 |  |  |  |  |  |  | transformations on what it guesses will be the compiler name: | 
| 52 |  |  |  |  |  |  |  | 
| 53 |  |  |  |  |  |  | gcc   => g++ | 
| 54 |  |  |  |  |  |  | clang => clang++ | 
| 55 |  |  |  |  |  |  | xlc   => xlC | 
| 56 |  |  |  |  |  |  | cc    => g++ | 
| 57 |  |  |  |  |  |  | c89   => g++ | 
| 58 |  |  |  |  |  |  |  | 
| 59 |  |  |  |  |  |  | =back | 
| 60 |  |  |  |  |  |  |  | 
| 61 |  |  |  |  |  |  | =over 4 | 
| 62 |  |  |  |  |  |  |  | 
| 63 |  |  |  |  |  |  | =cut | 
| 64 |  |  |  |  |  |  |  | 
| 65 |  |  |  |  |  |  | package ExtUtils::CXX; | 
| 66 |  |  |  |  |  |  |  | 
| 67 | 1 |  |  | 1 |  | 594 | use common::sense; | 
|  | 1 |  |  |  |  | 16 |  | 
|  | 1 |  |  |  |  | 8 |  | 
| 68 |  |  |  |  |  |  |  | 
| 69 |  |  |  |  |  |  | our $VERSION = 0.02; | 
| 70 |  |  |  |  |  |  |  | 
| 71 | 1 |  |  | 1 |  | 279 | use parent Exporter::; | 
|  | 1 |  |  |  |  | 221 |  | 
|  | 1 |  |  |  |  | 4 |  | 
| 72 |  |  |  |  |  |  |  | 
| 73 |  |  |  |  |  |  | our @EXPORT = qw(extutils_cxx); | 
| 74 |  |  |  |  |  |  |  | 
| 75 |  |  |  |  |  |  | =item extutils_cxx BLOCK; | 
| 76 |  |  |  |  |  |  |  | 
| 77 |  |  |  |  |  |  | This function temporarily does hideous things so you can call | 
| 78 |  |  |  |  |  |  | C or similar functions in the BLOCK normally. See the | 
| 79 |  |  |  |  |  |  | description, above, for more details. | 
| 80 |  |  |  |  |  |  |  | 
| 81 |  |  |  |  |  |  | =cut | 
| 82 |  |  |  |  |  |  |  | 
| 83 | 1 |  |  | 1 |  | 56 | use Config; | 
|  | 1 |  |  |  |  | 4 |  | 
|  | 1 |  |  |  |  | 410 |  | 
| 84 |  |  |  |  |  |  |  | 
| 85 |  |  |  |  |  |  | our %cc = ( | 
| 86 |  |  |  |  |  |  | gcc   => "g++", | 
| 87 |  |  |  |  |  |  | clang => "clang++", | 
| 88 |  |  |  |  |  |  | xlc   => "xlC", | 
| 89 |  |  |  |  |  |  | cc    => "g++", | 
| 90 |  |  |  |  |  |  | c89   => "g++", | 
| 91 |  |  |  |  |  |  | ); | 
| 92 |  |  |  |  |  |  |  | 
| 93 |  |  |  |  |  |  | sub _ccrepl { | 
| 94 | 2 |  |  | 2 |  | 4 | my ($cfgvar, $env) = @_; | 
| 95 |  |  |  |  |  |  |  | 
| 96 | 2 |  |  |  |  | 3 | my $tie = tied %Config; | 
| 97 |  |  |  |  |  |  |  | 
| 98 | 2 |  | 33 |  |  | 11 | my $env = $ENV{"PERL_$env"} || $ENV{$env}; | 
| 99 |  |  |  |  |  |  |  | 
| 100 | 2 |  |  |  |  | 3 | my $val = $tie->{$cfgvar}; | 
| 101 |  |  |  |  |  |  |  | 
| 102 | 2 | 50 |  |  |  | 5 | if ($env) { | 
| 103 | 0 |  |  |  |  | 0 | $val =~ s/^\S+/$env/; | 
| 104 |  |  |  |  |  |  | } else { | 
| 105 | 2 |  |  |  |  | 3 | keys %cc; | 
| 106 | 2 |  |  |  |  | 6 | while (my ($k, $v) = each %cc) { | 
| 107 | 7 | 100 |  |  |  | 155 | $val =~ s/^ (\S*[\/\\])? $k (-|\s|\d|$) /$1$v$2/x | 
| 108 |  |  |  |  |  |  | and goto done; | 
| 109 |  |  |  |  |  |  | } | 
| 110 |  |  |  |  |  |  |  | 
| 111 | 0 |  |  |  |  | 0 | $val =~ s/^\S+/g++/; | 
| 112 |  |  |  |  |  |  |  | 
| 113 | 2 |  |  |  |  | 5 | done: ; | 
| 114 |  |  |  |  |  |  | } | 
| 115 |  |  |  |  |  |  |  | 
| 116 | 2 |  |  |  |  | 5 | $tie->{$cfgvar} = $val; | 
| 117 |  |  |  |  |  |  | } | 
| 118 |  |  |  |  |  |  |  | 
| 119 |  |  |  |  |  |  | sub extutils_cxx(&) { | 
| 120 | 1 |  |  | 1 | 1 | 9 | my ($cb) = @_; | 
| 121 |  |  |  |  |  |  |  | 
| 122 |  |  |  |  |  |  | # make sure these exist | 
| 123 | 1 |  |  |  |  | 4 | @Config{qw(cc ld)}; | 
| 124 |  |  |  |  |  |  |  | 
| 125 | 1 |  |  |  |  | 3 | my $tie = tied %Config; | 
| 126 |  |  |  |  |  |  |  | 
| 127 |  |  |  |  |  |  | # now dive into internals of Config and temporarily patch those values | 
| 128 |  |  |  |  |  |  |  | 
| 129 | 1 |  |  |  |  | 4 | $tie->{ld} = "/uasr/bin/gcc-4.6 -O"; | 
| 130 | 1 |  |  |  |  | 9 | local $tie->{cc} = $Config{cc}; _ccrepl cc => "CXX"; | 
|  | 1 |  |  |  |  | 3 |  | 
| 131 | 1 | 50 |  |  |  | 6 | local $tie->{ld} = $Config{ld}; _ccrepl ld => ($ENV{PERL_CXXLD} ? "CXXLD" : "CXX"); | 
|  | 1 |  |  |  |  | 6 |  | 
| 132 |  |  |  |  |  |  |  | 
| 133 | 1 |  |  |  |  | 2 | eval { | 
| 134 | 1 |  |  |  |  | 3 | $cb->(); | 
| 135 |  |  |  |  |  |  | }; | 
| 136 | 1 | 50 |  |  |  | 5 | die if $@; | 
| 137 |  |  |  |  |  |  | } | 
| 138 |  |  |  |  |  |  |  | 
| 139 |  |  |  |  |  |  | =back | 
| 140 |  |  |  |  |  |  |  | 
| 141 |  |  |  |  |  |  | =head2 WHAT YOU HAVE TO DO | 
| 142 |  |  |  |  |  |  |  | 
| 143 |  |  |  |  |  |  | This module only makes your F<.xs> files compile as C++. It does not | 
| 144 |  |  |  |  |  |  | provide magic C++ support for objects and typemaps, and does not help with | 
| 145 |  |  |  |  |  |  | portability or writing your F<.xs> file. All of these you have to do - | 
| 146 |  |  |  |  |  |  | google is your friend. | 
| 147 |  |  |  |  |  |  |  | 
| 148 |  |  |  |  |  |  | =head2 LIMITATIONS | 
| 149 |  |  |  |  |  |  |  | 
| 150 |  |  |  |  |  |  | Combining C++ and C is an art form in itself, and there is simply no | 
| 151 |  |  |  |  |  |  | portable way to make it work - the platform might have a C compiler, but | 
| 152 |  |  |  |  |  |  | no C++ compiler. The C++ compiler might be binary incompatible to the C | 
| 153 |  |  |  |  |  |  | compiler, or might not run for other reasons, and in the end, C++ is more | 
| 154 |  |  |  |  |  |  | of a moving target than C. | 
| 155 |  |  |  |  |  |  |  | 
| 156 |  |  |  |  |  |  | =head2 SEE ALSO | 
| 157 |  |  |  |  |  |  |  | 
| 158 |  |  |  |  |  |  | There is a module called C that says it gives you C++ in | 
| 159 |  |  |  |  |  |  | XS, by changing XS in some ways. I don't know what exactly it's purpose | 
| 160 |  |  |  |  |  |  | is, but it might be a useful addition for C++ Xs development for you, | 
| 161 |  |  |  |  |  |  | so you might want to look at it. It doesn't have C | 
| 162 |  |  |  |  |  |  | support, and there is a companion module that only supports the obsolete | 
| 163 |  |  |  |  |  |  | (and very broken) C, sour YMMV. | 
| 164 |  |  |  |  |  |  |  | 
| 165 |  |  |  |  |  |  | =head1 AUTHOR/CONTACT | 
| 166 |  |  |  |  |  |  |  | 
| 167 |  |  |  |  |  |  | Marc Lehmann | 
| 168 |  |  |  |  |  |  | http://software.schmorp.de/pkg/extutils-cxx.html | 
| 169 |  |  |  |  |  |  |  | 
| 170 |  |  |  |  |  |  | =cut | 
| 171 |  |  |  |  |  |  |  | 
| 172 |  |  |  |  |  |  | 1 | 
| 173 |  |  |  |  |  |  |  |