This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Perldelta entry for the updated links
[perl5.git] / lib / ExtUtils / Embed.pm
CommitLineData
a2c6f8f1 1package ExtUtils::Embed;
2require Exporter;
a2c6f8f1 3use Config;
566e3efe 4require File::Spec;
a2c6f8f1 5
cc01160e 6our ( @Extensions, $opt_o, $opt_s );
a2c6f8f1 7use strict;
8
7975e7c1 9# This is not a dual-life module, so no need for development version numbers
cc01160e 10our $VERSION = '1.35';
a2c6f8f1 11
cc01160e
N
12our @ISA = qw(Exporter);
13our @EXPORT = qw(&xsinit &ldopts
a2c6f8f1 14 &ccopts &ccflags &ccdlflags &perl_inc
15 &xsi_header &xsi_protos &xsi_body);
16
cc01160e
N
17our $Verbose = 0;
18our $lib_ext = $Config{lib_ext} || '.a';
a2c6f8f1 19
7e24002c
DM
20sub is_cmd { $0 eq '-e' }
21
22sub my_return {
23 my $val = shift;
24 if(is_cmd) {
25 print $val;
26 }
27 else {
28 return $val;
29 }
30}
31
a2c6f8f1 32sub xsinit {
33 my($file, $std, $mods) = @_;
34 my($fh,@mods,%seen);
35 $file ||= "perlxsi.c";
acfe0abc 36 my $xsinit_proto = "pTHX";
a2c6f8f1 37
38 if (@_) {
39 @mods = @$mods if $mods;
40 }
41 else {
566e3efe
NC
42 require Getopt::Std;
43 Getopt::Std::getopts('o:s:');
a2c6f8f1 44 $file = $opt_o if defined $opt_o;
45 $std = $opt_s if defined $opt_s;
46 @mods = @ARGV;
47 }
48 $std = 1 unless scalar @mods;
49
50 if ($file eq "STDOUT") {
51 $fh = \*STDOUT;
52 }
53 else {
566e3efe
NC
54 open $fh, '>', $file
55 or die "Can't open '$file': $!";
a2c6f8f1 56 }
57
58 push(@mods, static_ext()) if defined $std;
59 @mods = grep(!$seen{$_}++, @mods);
60
61 print $fh &xsi_header();
5ec3aaed 62 print $fh "\nEXTERN_C void xs_init ($xsinit_proto);\n\n";
a2c6f8f1 63 print $fh &xsi_protos(@mods);
64
8bdb6b78 65 print $fh "\nEXTERN_C void\nxs_init($xsinit_proto)\n{\n";
a2c6f8f1 66 print $fh &xsi_body(@mods);
67 print $fh "}\n";
68
69}
70
71sub xsi_header {
72 return <<EOF;
5ec3aaed
NC
73#include "EXTERN.h"
74#include "perl.h"
75#include "XSUB.h"
a2c6f8f1 76EOF
77}
78
79sub xsi_protos {
2d7ce4f0
NC
80 my @exts = @_;
81 my %seen;
82 my $retval = '';
8d68a8a5 83 foreach my $cname (canon('__', @exts)) {
2d7ce4f0
NC
84 my $ccode = "EXTERN_C void boot_${cname} (pTHX_ CV* cv);\n";
85 $retval .= $ccode
86 unless $seen{$ccode}++;
a2c6f8f1 87 }
2d7ce4f0 88 return $retval;
a2c6f8f1 89}
90
91sub xsi_body {
2d7ce4f0
NC
92 my @exts = @_;
93 my %seen;
94 my $retval;
95 $retval .= " static const char file[] = __FILE__;\n"
5ec3aaed 96 if @exts;
2d7ce4f0
NC
97 $retval .= <<'EOT';
98 dXSUB_SYS;
99 PERL_UNUSED_CONTEXT;
100EOT
101 $retval .= "\n"
5ec3aaed 102 if @exts;
a2c6f8f1 103
8d68a8a5 104 foreach my $pname (canon('/', @exts)) {
2d7ce4f0
NC
105 next
106 if $seen{$pname}++;
107 (my $mname = $pname) =~ s!/!::!g;
108 (my $cname = $pname) =~ s!/!__!g;
109 my $fname;
8d68a8a5 110 if ($pname eq 'DynaLoader'){
a2c6f8f1 111 # Must NOT install 'DynaLoader::boot_DynaLoader' as 'bootstrap'!
112 # boot_DynaLoader is called directly in DynaLoader.pm
2d7ce4f0
NC
113 $retval .= " /* DynaLoader is a special case */\n";
114 $fname = "${mname}::boot_DynaLoader";
a2c6f8f1 115 } else {
2d7ce4f0 116 $fname = "${mname}::bootstrap";
a2c6f8f1 117 }
2d7ce4f0 118 $retval .= " newXS(\"$fname\", boot_${cname}, file);\n"
a2c6f8f1 119 }
2d7ce4f0 120 return $retval;
a2c6f8f1 121}
122
123sub static_ext {
8d68a8a5
NC
124 @Extensions = ('DynaLoader', sort $Config{static_ext} =~ /(\S+)/g)
125 unless @Extensions;
a2c6f8f1 126 @Extensions;
127}
128
03f2ffd8
JH
129sub _escape {
130 my $arg = shift;
0ab03fee 131 return $$arg if $^O eq 'VMS'; # parens legal in qualifier lists
03f2ffd8
JH
132 $$arg =~ s/([\(\)])/\\$1/g;
133}
134
f0595bdd
JH
135sub _ldflags {
136 my $ldflags = $Config{ldflags};
03f2ffd8 137 _escape(\$ldflags);
f0595bdd
JH
138 return $ldflags;
139}
140
141sub _ccflags {
142 my $ccflags = $Config{ccflags};
03f2ffd8 143 _escape(\$ccflags);
f0595bdd
JH
144 return $ccflags;
145}
146
147sub _ccdlflags {
148 my $ccdlflags = $Config{ccdlflags};
03f2ffd8 149 _escape(\$ccdlflags);
f0595bdd
JH
150 return $ccdlflags;
151}
152
a2c6f8f1 153sub ldopts {
154 require ExtUtils::MakeMaker;
155 require ExtUtils::Liblist;
156 my($std,$mods,$link_args,$path) = @_;
157 my(@mods,@link_args,@argv);
158 my($dllib,$config_libs,@potential_libs,@path);
159 local($") = ' ' unless $" eq ' ';
a2c6f8f1 160 if (scalar @_) {
161 @link_args = @$link_args if $link_args;
162 @mods = @$mods if $mods;
163 }
164 else {
165 @argv = @ARGV;
166 #hmm
167 while($_ = shift @argv) {
168 /^-std$/ && do { $std = 1; next; };
169 /^--$/ && do { @link_args = @argv; last; };
170 /^-I(.*)/ && do { $path = $1 || shift @argv; next; };
171 push(@mods, $_);
172 }
173 }
174 $std = 1 unless scalar @link_args;
9bbedd82
JH
175 my $sep = $Config{path_sep} || ':';
176 @path = $path ? split(/\Q$sep/, $path) : @INC;
a2c6f8f1 177
178 push(@potential_libs, @link_args) if scalar @link_args;
9bbedd82
JH
179 # makemaker includes std libs on windows by default
180 if ($^O ne 'MSWin32' and defined($std)) {
181 push(@potential_libs, $Config{perllibs});
182 }
a2c6f8f1 183
184 push(@mods, static_ext()) if $std;
185
186 my($mod,@ns,$root,$sub,$extra,$archive,@archives);
187 print STDERR "Searching (@path) for archives\n" if $Verbose;
188 foreach $mod (@mods) {
3ab83790 189 @ns = split(/::|\/|\\/, $mod);
a2c6f8f1 190 $sub = $ns[-1];
56c2fb36 191 $root = File::Spec->catdir(@ns);
a2c6f8f1 192
193 print STDERR "searching for '$sub${lib_ext}'\n" if $Verbose;
194 foreach (@path) {
56c2fb36 195 next unless -e ($archive = File::Spec->catdir($_,"auto",$root,"$sub$lib_ext"));
a2c6f8f1 196 push @archives, $archive;
56c2fb36 197 if(-e ($extra = File::Spec->catdir($_,"auto",$root,"extralibs.ld"))) {
a2c6f8f1 198 local(*FH);
1ae6ead9 199 if(open(FH, '<', $extra)) {
a2c6f8f1 200 my($libs) = <FH>; chomp $libs;
201 push @potential_libs, split /\s+/, $libs;
202 }
203 else {
204 warn "Couldn't open '$extra'";
205 }
206 }
207 last;
208 }
209 }
210 #print STDERR "\@potential_libs = @potential_libs\n";
211
9bbedd82
JH
212 my $libperl;
213 if ($^O eq 'MSWin32') {
214 $libperl = $Config{libperl};
215 }
2f3efc97
JH
216 elsif ($^O eq 'os390' && $Config{usedl}) {
217 # Nothing for OS/390 (z/OS) dynamic.
218 } else {
9720141b
MR
219 $libperl = (grep(/^-l\w*perl\w*$/, @link_args))[0]
220 || ($Config{libperl} =~ /^lib(\w+)(\Q$lib_ext\E|\.\Q$Config{dlext}\E)$/
221 ? "-l$1" : '')
2f3efc97 222 || "-lperl";
9bbedd82 223 }
af248097 224
9bbedd82
JH
225 my $lpath = File::Spec->catdir($Config{archlibexp}, 'CORE');
226 $lpath = qq["$lpath"] if $^O eq 'MSWin32';
a2c6f8f1 227 my($extralibs, $bsloadlibs, $ldloadlibs, $ld_run_path) =
5de3f0da 228 MM->ext(join ' ', "-L$lpath", $libperl, @potential_libs);
a2c6f8f1 229
230 my $ld_or_bs = $bsloadlibs || $ldloadlibs;
231 print STDERR "bs: $bsloadlibs ** ld: $ldloadlibs" if $Verbose;
f0595bdd
JH
232 my $ccdlflags = _ccdlflags();
233 my $ldflags = _ldflags();
234 my $linkage = "$ccdlflags $ldflags @archives $ld_or_bs";
a2c6f8f1 235 print STDERR "ldopts: '$linkage'\n" if $Verbose;
236
237 return $linkage if scalar @_;
7e24002c 238 my_return("$linkage\n");
a2c6f8f1 239}
240
241sub ccflags {
f0595bdd
JH
242 my $ccflags = _ccflags();
243 my_return(" $ccflags ");
a2c6f8f1 244}
245
246sub ccdlflags {
f0595bdd
JH
247 my $ccdlflags = _ccdlflags();
248 my_return(" $ccdlflags ");
a2c6f8f1 249}
250
251sub perl_inc {
9bbedd82
JH
252 my $dir = File::Spec->catdir($Config{archlibexp}, 'CORE');
253 $dir = qq["$dir"] if $^O eq 'MSWin32';
254 my_return(" -I$dir ");
a2c6f8f1 255}
256
257sub ccopts {
7e24002c 258 ccflags . perl_inc;
a2c6f8f1 259}
260
261sub canon {
262 my($as, @ext) = @_;
263 foreach(@ext) {
8d68a8a5
NC
264 # might be X::Y or lib/auto/X/Y/Y.a
265 next
266 if s!::!/!g;
267 s!^(?:lib|ext|dist|cpan)/(?:auto/)?!!;
268 s!/\w+\.\w+$!!;
269 }
270 if ($as ne '/') {
1eb53836 271 s!/!$as!g
8d68a8a5 272 foreach @ext;
a2c6f8f1 273 }
a2c6f8f1 274 @ext;
275}
276
277__END__
278
279=head1 NAME
280
281ExtUtils::Embed - Utilities for embedding Perl in C/C++ applications
282
283=head1 SYNOPSIS
284
a2c6f8f1 285 perl -MExtUtils::Embed -e xsinit
9bbedd82 286 perl -MExtUtils::Embed -e ccopts
a2c6f8f1 287 perl -MExtUtils::Embed -e ldopts
288
289=head1 DESCRIPTION
290
c6c89521 291C<ExtUtils::Embed> provides utility functions for embedding a Perl interpreter
a2c6f8f1 292and extensions in your C/C++ applications.
c6c89521 293Typically, an application F<Makefile> will invoke C<ExtUtils::Embed>
a2c6f8f1 294functions while building your application.
295
296=head1 @EXPORT
297
c6c89521 298C<ExtUtils::Embed> exports the following functions:
a6006777 299
4e864201
JM
300xsinit(), ldopts(), ccopts(), perl_inc(), ccflags(),
301ccdlflags(), xsi_header(), xsi_protos(), xsi_body()
a2c6f8f1 302
303=head1 FUNCTIONS
304
bbc7dcd2 305=over 4
2ae324a7 306
a2c6f8f1 307=item xsinit()
308
4e864201 309Generate C/C++ code for the XS initializer function.
a2c6f8f1 310
311When invoked as C<`perl -MExtUtils::Embed -e xsinit --`>
312the following options are recognized:
313
4e864201 314B<-o> E<lt>output filenameE<gt> (Defaults to B<perlxsi.c>)
a2c6f8f1 315
316B<-o STDOUT> will print to STDOUT.
317
318B<-std> (Write code for extensions that are linked with the current Perl.)
319
320Any additional arguments are expected to be names of modules
321to generate code for.
322
323When invoked with parameters the following are accepted and optional:
324
325C<xsinit($filename,$std,[@modules])>
326
327Where,
328
329B<$filename> is equivalent to the B<-o> option.
330
331B<$std> is boolean, equivalent to the B<-std> option.
332
333B<[@modules]> is an array ref, same as additional arguments mentioned above.
334
335=item Examples
336
a2c6f8f1 337 perl -MExtUtils::Embed -e xsinit -- -o xsinit.c Socket
338
c6c89521
NC
339This will generate code with an C<xs_init> function that glues the perl C<Socket::bootstrap> function
340to the C C<boot_Socket> function and writes it to a file named F<xsinit.c>.
a2c6f8f1 341
c6c89521 342Note that L<DynaLoader> is a special case where it must call C<boot_DynaLoader> directly.
a2c6f8f1 343
344 perl -MExtUtils::Embed -e xsinit
345
c6c89521
NC
346This will generate code for linking with C<DynaLoader> and
347each static extension found in C<$Config{static_ext}>.
348The code is written to the default file name F<perlxsi.c>.
a2c6f8f1 349
e46aa1dd
KW
350 perl -MExtUtils::Embed -e xsinit -- -o xsinit.c \
351 -std DBI DBD::Oracle
a2c6f8f1 352
a2c6f8f1 353Here, code is written for all the currently linked extensions along with code
c6c89521 354for C<DBI> and C<DBD::Oracle>.
a2c6f8f1 355
c6c89521 356If you have a working C<DynaLoader> then there is rarely any need to statically link in any
a2c6f8f1 357other extensions.
358
359=item ldopts()
360
361Output arguments for linking the Perl library and extensions to your
362application.
363
364When invoked as C<`perl -MExtUtils::Embed -e ldopts --`>
365the following options are recognized:
366
367B<-std>
368
369Output arguments for linking the Perl library and any extensions linked
370with the current Perl.
371
4e864201 372B<-I> E<lt>path1:path2E<gt>
a2c6f8f1 373
374Search path for ModuleName.a archives.
c6c89521 375Default path is C<@INC>.
a2c6f8f1 376Library archives are expected to be found as
c6c89521
NC
377F</some/path/auto/ModuleName/ModuleName.a>
378For example, when looking for F<Socket.a> relative to a search path,
379we should find F<auto/Socket/Socket.a>
a2c6f8f1 380
c6c89521
NC
381When looking for C<DBD::Oracle> relative to a search path,
382we should find F<auto/DBD/Oracle/Oracle.a>
a2c6f8f1 383
c6c89521 384Keep in mind that you can always supply F</my/own/path/ModuleName.a>
a2c6f8f1 385as an additional linker argument.
386
4e864201 387B<--> E<lt>list of linker argsE<gt>
a2c6f8f1 388
389Additional linker arguments to be considered.
390
391Any additional arguments found before the B<--> token
392are expected to be names of modules to generate code for.
393
394When invoked with parameters the following are accepted and optional:
395
396C<ldopts($std,[@modules],[@link_args],$path)>
397
a7665c5e 398Where:
a2c6f8f1 399
400B<$std> is boolean, equivalent to the B<-std> option.
401
402B<[@modules]> is equivalent to additional arguments found before the B<--> token.
403
404B<[@link_args]> is equivalent to arguments found after the B<--> token.
405
406B<$path> is equivalent to the B<-I> option.
407
408In addition, when ldopts is called with parameters, it will return the argument string
409rather than print it to STDOUT.
410
411=item Examples
412
a2c6f8f1 413 perl -MExtUtils::Embed -e ldopts
414
c6c89521
NC
415This will print arguments for linking with C<libperl> and
416extensions found in C<$Config{static_ext}>. This includes libraries
417found in C<$Config{libs}> and the first ModuleName.a library
418for each extension that is found by searching C<@INC> or the path
419specified by the B<-I> option.
a2c6f8f1 420In addition, when ModuleName.a is found, additional linker arguments
c6c89521 421are picked up from the F<extralibs.ld> file in the same directory.
a2c6f8f1 422
423 perl -MExtUtils::Embed -e ldopts -- -std Socket
a6006777 424
e46aa1dd
KW
425This will do the same as the above example, along with printing additional
426arguments for linking with the C<Socket> extension.
a2c6f8f1 427
e46aa1dd
KW
428 perl -MExtUtils::Embed -e ldopts -- -std Msql -- \
429 -L/usr/msql/lib -lmsql
a2c6f8f1 430
a2c6f8f1 431Any arguments after the second '--' token are additional linker
432arguments that will be examined for potential conflict. If there is no
433conflict, the additional arguments will be part of the output.
434
a2c6f8f1 435=item perl_inc()
436
437For including perl header files this function simply prints:
438
36477c24 439 -I$Config{archlibexp}/CORE
a2c6f8f1 440
441So, rather than having to say:
442
36477c24 443 perl -MConfig -e 'print "-I$Config{archlibexp}/CORE"'
a2c6f8f1 444
445Just say:
446
447 perl -MExtUtils::Embed -e perl_inc
448
449=item ccflags(), ccdlflags()
450
451These functions simply print $Config{ccflags} and $Config{ccdlflags}
452
453=item ccopts()
454
c6c89521 455This function combines C<perl_inc()>, C<ccflags()> and C<ccdlflags()> into one.
a2c6f8f1 456
457=item xsi_header()
458
c6c89521
NC
459This function simply returns a string defining the same C<EXTERN_C> macro as
460F<perlmain.c> along with #including F<perl.h> and F<EXTERN.h>.
a2c6f8f1 461
462=item xsi_protos(@modules)
463
c6c89521 464This function returns a string of C<boot_$ModuleName> prototypes for each @modules.
a2c6f8f1 465
466=item xsi_body(@modules)
467
c6c89521
NC
468This function returns a string of calls to C<newXS()> that glue the module I<bootstrap>
469function to I<boot_ModuleName> for each @modules.
a2c6f8f1 470
c6c89521 471C<xsinit()> uses the xsi_* functions to generate most of its code.
a2c6f8f1 472
2ae324a7 473=back
474
a2c6f8f1 475=head1 EXAMPLES
476
c6c89521 477For examples on how to use C<ExtUtils::Embed> for building C/C++ applications
0325b4c4 478with embedded perl, see L<perlembed>.
a6006777 479
a2c6f8f1 480=head1 SEE ALSO
481
4e864201 482L<perlembed>
a2c6f8f1 483
484=head1 AUTHOR
485
c6c89521 486Doug MacEachern E<lt>C<dougm@osf.org>E<gt>
a2c6f8f1 487
c6c89521
NC
488Based on ideas from Tim Bunce E<lt>C<Tim.Bunce@ig.co.uk>E<gt> and
489F<minimod.pl> by Andreas Koenig E<lt>C<k@anna.in-berlin.de>E<gt> and Tim Bunce.
a2c6f8f1 490
491=cut