This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Trivial patch to make ExtUtils::Install more -w clean
[perl5.git] / lib / ExtUtils / Embed.pm
CommitLineData
f86702cc 1# $Id: Embed.pm,v 1.22 1997/01/30 00:37:09 dougm Exp $
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
f86702cc 20$VERSION = sprintf("%d.%02d", q$Revision: 1.22 $ =~ /(\d+)\.(\d+)/);
a2c6f8f1 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
202 my($extralibs, $bsloadlibs, $ldloadlibs, $ld_run_path) =
203 $MM->ext(join ' ',
36477c24 204 $MM->catdir("-L$Config{archlibexp}", "CORE"), " -lperl",
a2c6f8f1 205 @potential_libs);
206
207 my $ld_or_bs = $bsloadlibs || $ldloadlibs;
208 print STDERR "bs: $bsloadlibs ** ld: $ldloadlibs" if $Verbose;
f86702cc 209 my $linkage = "$Config{ccdlflags} $Config{ldflags} @archives $ld_or_bs";
a2c6f8f1 210 print STDERR "ldopts: '$linkage'\n" if $Verbose;
211
212 return $linkage if scalar @_;
213 print "$linkage\n";
214}
215
216sub ccflags {
217 print " $Config{ccflags} ";
218}
219
220sub ccdlflags {
221 print " $Config{ccdlflags} ";
222}
223
224sub perl_inc {
ff68c719 225 print " -I$Config{archlibexp}/CORE ";
a2c6f8f1 226}
227
228sub ccopts {
229 ccflags;
a2c6f8f1 230 perl_inc;
231}
232
233sub canon {
234 my($as, @ext) = @_;
235 foreach(@ext) {
236 # might be X::Y or lib/auto/X/Y/Y.a
237 next if s!::!/!g;
238 s:^(lib|ext)/(auto/)?::;
239 s:/\w+\.\w+$::;
240 }
241 grep(s:/:$as:, @ext) if ($as ne '/');
242 @ext;
243}
244
245__END__
246
247=head1 NAME
248
249ExtUtils::Embed - Utilities for embedding Perl in C/C++ applications
250
251=head1 SYNOPSIS
252
253
254 perl -MExtUtils::Embed -e xsinit
255 perl -MExtUtils::Embed -e ldopts
256
257=head1 DESCRIPTION
258
259ExtUtils::Embed provides utility functions for embedding a Perl interpreter
260and extensions in your C/C++ applications.
261Typically, an application B<Makefile> will invoke ExtUtils::Embed
262functions while building your application.
263
264=head1 @EXPORT
265
266ExtUtils::Embed exports the following functions:
a6006777 267
4e864201
JM
268xsinit(), ldopts(), ccopts(), perl_inc(), ccflags(),
269ccdlflags(), xsi_header(), xsi_protos(), xsi_body()
a2c6f8f1 270
271=head1 FUNCTIONS
272
273=item xsinit()
274
4e864201 275Generate C/C++ code for the XS initializer function.
a2c6f8f1 276
277When invoked as C<`perl -MExtUtils::Embed -e xsinit --`>
278the following options are recognized:
279
4e864201 280B<-o> E<lt>output filenameE<gt> (Defaults to B<perlxsi.c>)
a2c6f8f1 281
282B<-o STDOUT> will print to STDOUT.
283
284B<-std> (Write code for extensions that are linked with the current Perl.)
285
286Any additional arguments are expected to be names of modules
287to generate code for.
288
289When invoked with parameters the following are accepted and optional:
290
291C<xsinit($filename,$std,[@modules])>
292
293Where,
294
295B<$filename> is equivalent to the B<-o> option.
296
297B<$std> is boolean, equivalent to the B<-std> option.
298
299B<[@modules]> is an array ref, same as additional arguments mentioned above.
300
301=item Examples
302
a6006777 303
a2c6f8f1 304 perl -MExtUtils::Embed -e xsinit -- -o xsinit.c Socket
305
306
307This will generate code with an B<xs_init> function that glues the perl B<Socket::bootstrap> function
308to the C B<boot_Socket> function and writes it to a file named "xsinit.c".
309
310Note that B<DynaLoader> is a special case where it must call B<boot_DynaLoader> directly.
311
312 perl -MExtUtils::Embed -e xsinit
313
314
315This will generate code for linking with B<DynaLoader> and
316each static extension found in B<$Config{static_ext}>.
317The code is written to the default file name B<perlxsi.c>.
318
319
320 perl -MExtUtils::Embed -e xsinit -- -o xsinit.c -std DBI DBD::Oracle
321
322
323Here, code is written for all the currently linked extensions along with code
324for B<DBI> and B<DBD::Oracle>.
325
326If you have a working B<DynaLoader> then there is rarely any need to statically link in any
327other extensions.
328
329=item ldopts()
330
331Output arguments for linking the Perl library and extensions to your
332application.
333
334When invoked as C<`perl -MExtUtils::Embed -e ldopts --`>
335the following options are recognized:
336
337B<-std>
338
339Output arguments for linking the Perl library and any extensions linked
340with the current Perl.
341
4e864201 342B<-I> E<lt>path1:path2E<gt>
a2c6f8f1 343
344Search path for ModuleName.a archives.
345Default path is B<@INC>.
346Library archives are expected to be found as
347B</some/path/auto/ModuleName/ModuleName.a>
348For example, when looking for B<Socket.a> relative to a search path,
349we should find B<auto/Socket/Socket.a>
350
351When looking for B<DBD::Oracle> relative to a search path,
352we should find B<auto/DBD/Oracle/Oracle.a>
353
354Keep in mind, you can always supply B</my/own/path/ModuleName.a>
355as an additional linker argument.
356
4e864201 357B<--> E<lt>list of linker argsE<gt>
a2c6f8f1 358
359Additional linker arguments to be considered.
360
361Any additional arguments found before the B<--> token
362are expected to be names of modules to generate code for.
363
364When invoked with parameters the following are accepted and optional:
365
366C<ldopts($std,[@modules],[@link_args],$path)>
367
368Where,
369
370B<$std> is boolean, equivalent to the B<-std> option.
371
372B<[@modules]> is equivalent to additional arguments found before the B<--> token.
373
374B<[@link_args]> is equivalent to arguments found after the B<--> token.
375
376B<$path> is equivalent to the B<-I> option.
377
378In addition, when ldopts is called with parameters, it will return the argument string
379rather than print it to STDOUT.
380
381=item Examples
382
383
384 perl -MExtUtils::Embed -e ldopts
385
386
387This will print arguments for linking with B<libperl.a>, B<DynaLoader> and
388extensions found in B<$Config{static_ext}>. This includes libraries
389found in B<$Config{libs}> and the first ModuleName.a library
390for each extension that is found by searching B<@INC> or the path
391specifed by the B<-I> option.
392In addition, when ModuleName.a is found, additional linker arguments
393are picked up from the B<extralibs.ld> file in the same directory.
394
395
396 perl -MExtUtils::Embed -e ldopts -- -std Socket
a6006777 397
a2c6f8f1 398
399This will do the same as the above example, along with printing additional arguments for linking with the B<Socket> extension.
400
401
402 perl -MExtUtils::Embed -e ldopts -- DynaLoader
403
404
405This will print arguments for linking with just the B<DynaLoader> extension
406and B<libperl.a>.
407
408
409 perl -MExtUtils::Embed -e ldopts -- -std Msql -- -L/usr/msql/lib -lmsql
410
411
412Any arguments after the second '--' token are additional linker
413arguments that will be examined for potential conflict. If there is no
414conflict, the additional arguments will be part of the output.
415
416
417=item perl_inc()
418
419For including perl header files this function simply prints:
420
36477c24 421 -I$Config{archlibexp}/CORE
a2c6f8f1 422
423So, rather than having to say:
424
36477c24 425 perl -MConfig -e 'print "-I$Config{archlibexp}/CORE"'
a2c6f8f1 426
427Just say:
428
429 perl -MExtUtils::Embed -e perl_inc
430
431=item ccflags(), ccdlflags()
432
433These functions simply print $Config{ccflags} and $Config{ccdlflags}
434
435=item ccopts()
436
437This function combines perl_inc(), ccflags() and ccdlflags() into one.
438
439=item xsi_header()
440
441This function simply returns a string defining the same B<EXTERN_C> macro as
442B<perlmain.c> along with #including B<perl.h> and B<EXTERN.h>.
443
444=item xsi_protos(@modules)
445
446This function returns a string of B<boot_$ModuleName> prototypes for each @modules.
447
448=item xsi_body(@modules)
449
450This function returns a string of calls to B<newXS()> that glue the module B<bootstrap>
451function to B<boot_ModuleName> for each @modules.
452
453B<xsinit()> uses the xsi_* functions to generate most of it's code.
454
455=head1 EXAMPLES
456
457For examples on how to use B<ExtUtils::Embed> for building C/C++ applications
4e864201 458with embedded perl, see the eg/ directory and L<perlembed>.
a6006777 459
a2c6f8f1 460=head1 SEE ALSO
461
4e864201 462L<perlembed>
a2c6f8f1 463
464=head1 AUTHOR
465
4e864201 466Doug MacEachern E<lt>F<dougm@osf.org>E<gt>
a2c6f8f1 467
4e864201
JM
468Based on ideas from Tim Bunce E<lt>F<Tim.Bunce@ig.co.uk>E<gt> and
469B<minimod.pl> by Andreas Koenig E<lt>F<k@anna.in-berlin.de>E<gt> and Tim Bunce.
a2c6f8f1 470
471=cut
472