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