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