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