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