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