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