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