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