This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Remove MacOS classic support from File::{Copy,DosGlob,Find,Glob,stat}.
[perl5.git] / lib / ExtUtils / Embed.pm
CommitLineData
39234879 1# $Id: Embed.pm,v 1.1.1.1 2002/01/16 19:27:19 schwern Exp $
a2c6f8f1 2require 5.002;
3
4package ExtUtils::Embed;
5require Exporter;
6require FileHandle;
7use Config;
8use Getopt::Std;
9bbedd82 9use File::Spec;
a2c6f8f1 10
11#Only when we need them
12#require ExtUtils::MakeMaker;
13#require ExtUtils::Liblist;
14
15use vars qw(@ISA @EXPORT $VERSION
16 @Extensions $Verbose $lib_ext
17 $opt_o $opt_s
18 );
19use strict;
20
7975e7c1 21# This is not a dual-life module, so no need for development version numbers
d8528f07 22$VERSION = '1.28';
a2c6f8f1 23
24@ISA = qw(Exporter);
25@EXPORT = qw(&xsinit &ldopts
26 &ccopts &ccflags &ccdlflags &perl_inc
27 &xsi_header &xsi_protos &xsi_body);
28
29#let's have Miniperl borrow from us instead
30#require ExtUtils::Miniperl;
31#*canon = \&ExtUtils::Miniperl::canon;
32
33$Verbose = 0;
34$lib_ext = $Config{lib_ext} || '.a';
35
7e24002c
DM
36sub is_cmd { $0 eq '-e' }
37
38sub my_return {
39 my $val = shift;
40 if(is_cmd) {
41 print $val;
42 }
43 else {
44 return $val;
45 }
46}
47
a2c6f8f1 48sub xsinit {
49 my($file, $std, $mods) = @_;
50 my($fh,@mods,%seen);
51 $file ||= "perlxsi.c";
acfe0abc 52 my $xsinit_proto = "pTHX";
a2c6f8f1 53
54 if (@_) {
55 @mods = @$mods if $mods;
56 }
57 else {
58 getopts('o:s:');
59 $file = $opt_o if defined $opt_o;
60 $std = $opt_s if defined $opt_s;
61 @mods = @ARGV;
62 }
63 $std = 1 unless scalar @mods;
64
65 if ($file eq "STDOUT") {
66 $fh = \*STDOUT;
67 }
68 else {
69 $fh = new FileHandle "> $file";
70 }
71
72 push(@mods, static_ext()) if defined $std;
73 @mods = grep(!$seen{$_}++, @mods);
74
75 print $fh &xsi_header();
20ce7b12 76 print $fh "EXTERN_C void xs_init ($xsinit_proto);\n\n";
a2c6f8f1 77 print $fh &xsi_protos(@mods);
78
8bdb6b78 79 print $fh "\nEXTERN_C void\nxs_init($xsinit_proto)\n{\n";
a2c6f8f1 80 print $fh &xsi_body(@mods);
81 print $fh "}\n";
82
83}
84
85sub xsi_header {
86 return <<EOF;
a2c6f8f1 87#include <EXTERN.h>
88#include <perl.h>
a2c6f8f1 89
90EOF
91}
92
93sub xsi_protos {
94 my(@exts) = @_;
95 my(@retval,%seen);
acfe0abc 96 my $boot_proto = "pTHX_ CV* cv";
a2c6f8f1 97 foreach $_ (@exts){
98 my($pname) = canon('/', $_);
99 my($mname, $cname);
100 ($mname = $pname) =~ s!/!::!g;
101 ($cname = $pname) =~ s!/!__!g;
20ce7b12 102 my($ccode) = "EXTERN_C void boot_${cname} ($boot_proto);\n";
a2c6f8f1 103 next if $seen{$ccode}++;
104 push(@retval, $ccode);
105 }
106 return join '', @retval;
107}
108
109sub xsi_body {
110 my(@exts) = @_;
111 my($pname,@retval,%seen);
112 my($dl) = canon('/','DynaLoader');
a3c8358c 113 push(@retval, "\tchar *file = __FILE__;\n");
a2c6f8f1 114 push(@retval, "\tdXSUB_SYS;\n") if $] > 5.002;
a3c8358c 115 push(@retval, "\n");
a2c6f8f1 116
117 foreach $_ (@exts){
118 my($pname) = canon('/', $_);
119 my($mname, $cname, $ccode);
120 ($mname = $pname) =~ s!/!::!g;
121 ($cname = $pname) =~ s!/!__!g;
122 if ($pname eq $dl){
123 # Must NOT install 'DynaLoader::boot_DynaLoader' as 'bootstrap'!
124 # boot_DynaLoader is called directly in DynaLoader.pm
125 $ccode = "\t/* DynaLoader is a special case */\n\tnewXS(\"${mname}::boot_${cname}\", boot_${cname}, file);\n";
126 push(@retval, $ccode) unless $seen{$ccode}++;
127 } else {
128 $ccode = "\tnewXS(\"${mname}::bootstrap\", boot_${cname}, file);\n";
129 push(@retval, $ccode) unless $seen{$ccode}++;
130 }
131 }
132 return join '', @retval;
133}
134
135sub static_ext {
136 unless (scalar @Extensions) {
d0cbb09d
RU
137 my $static_ext = $Config{static_ext};
138 $static_ext =~ s/^\s+//;
139 @Extensions = sort split /\s+/, $static_ext;
a2c6f8f1 140 unshift @Extensions, qw(DynaLoader);
141 }
142 @Extensions;
143}
144
03f2ffd8
JH
145sub _escape {
146 my $arg = shift;
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