checkpoint, minor cleanups
[nvi.git] / dist / ExtUtils / Embed.pm
blob14cf77778441393bc5c47ec1b99fa972bce52f28
1 # $Id: Embed.pm,v 10.2 1996/09/19 09:12:51 bostic Exp $
2 require 5.002;
4 package ExtUtils::Embed;
5 require Exporter;
6 require FileHandle;
7 use Config;
8 use Getopt::Std;
10 #Only when we need them
11 #require ExtUtils::MakeMaker;
12 #require ExtUtils::Liblist;
14 use vars qw(@ISA @EXPORT $VERSION
15 @Extensions $Verbose $lib_ext
16 $opt_o $opt_s
18 use strict;
20 $VERSION = sprintf("%d.%02d", q$Revision: 10.2 $ =~ /(\d+)\.(\d+)/);
21 #for the namespace change
22 $Devel::embed::VERSION = "99.99";
24 sub Version { $VERSION; }
26 @ISA = qw(Exporter);
27 @EXPORT = qw(&xsinit &ldopts
28 &ccopts &ccflags &ccdlflags &perl_inc
29 &xsi_header &xsi_protos &xsi_body);
31 #let's have Miniperl borrow from us instead
32 #require ExtUtils::Miniperl;
33 #*canon = \&ExtUtils::Miniperl::canon;
35 $Verbose = 0;
36 $lib_ext = $Config{lib_ext} || '.a';
38 sub xsinit {
39 my($file, $std, $mods) = @_;
40 my($fh,@mods,%seen);
41 $file ||= "perlxsi.c";
43 if (@_) {
44 @mods = @$mods if $mods;
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;
52 $std = 1 unless scalar @mods;
54 if ($file eq "STDOUT") {
55 $fh = \*STDOUT;
57 else {
58 $fh = new FileHandle "> $file";
61 push(@mods, static_ext()) if defined $std;
62 @mods = grep(!$seen{$_}++, @mods);
64 print $fh &xsi_header();
65 print $fh "EXTERN_C void xs_init _((void));\n\n";
66 print $fh &xsi_protos(@mods);
68 print $fh "\nEXTERN_C void\nxs_init()\n{\n";
69 print $fh &xsi_body(@mods);
70 print $fh "}\n";
74 sub xsi_header {
75 return <<EOF;
76 #ifdef __cplusplus
77 extern "C" {
78 #endif
80 #include <EXTERN.h>
81 #include <perl.h>
83 #ifdef __cplusplus
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
94 EOF
97 sub xsi_protos {
98 my(@exts) = @_;
99 my(@retval,%seen);
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);
110 return join '', @retval;
113 sub 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");
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}++;
135 return join '', @retval;
138 sub static_ext {
139 unless (scalar @Extensions) {
140 @Extensions = sort split /\s+/, $Config{static_ext};
141 unshift @Extensions, qw(DynaLoader);
143 @Extensions;
146 sub 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;
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, $_);
168 $std = 1 unless scalar @link_args;
169 @path = $path ? split(/:/, $path) : @INC;
171 push(@potential_libs, @link_args) if scalar @link_args;
172 push(@potential_libs, $Config{libs}) if defined $std;
174 push(@mods, static_ext()) if $std;
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);
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;
193 else {
194 warn "Couldn't open '$extra'";
197 last;
200 #print STDERR "\@potential_libs = @potential_libs\n";
202 my($extralibs, $bsloadlibs, $ldloadlibs, $ld_run_path) =
203 $MM->ext(join ' ',
204 $MM->catdir("-L$Config{archlib}", "CORE"), " -lperl",
205 @potential_libs);
207 my $ld_or_bs = $bsloadlibs || $ldloadlibs;
208 print STDERR "bs: $bsloadlibs ** ld: $ldloadlibs" if $Verbose;
209 my $linkage = "$Config{ldflags} @archives $ld_or_bs";
210 print STDERR "ldopts: '$linkage'\n" if $Verbose;
212 return $linkage if scalar @_;
213 print "$linkage\n";
216 sub ccflags {
217 print " $Config{ccflags} ";
220 sub ccdlflags {
221 print " $Config{ccdlflags} ";
224 sub perl_inc {
225 print " -I$Config{archlib}/CORE ";
228 sub ccopts {
229 ccflags;
230 ccdlflags;
231 perl_inc;
234 sub canon {
235 my($as, @ext) = @_;
236 foreach(@ext) {
237 # might be X::Y or lib/auto/X/Y/Y.a
238 next if s!::!/!g;
239 s:^(lib|ext)/(auto/)?::;
240 s:/\w+\.\w+$::;
242 grep(s:/:$as:, @ext) if ($as ne '/');
243 @ext;
246 __END__
248 =head1 NAME
250 ExtUtils::Embed - Utilities for embedding Perl in C/C++ applications
252 =head1 SYNOPSIS
255 perl -MExtUtils::Embed -e xsinit
256 perl -MExtUtils::Embed -e ldopts
258 =head1 DESCRIPTION
260 ExtUtils::Embed provides utility functions for embedding a Perl interpreter
261 and extensions in your C/C++ applications.
262 Typically, an application B<Makefile> will invoke ExtUtils::Embed
263 functions while building your application.
265 =head1 @EXPORT
267 ExtUtils::Embed exports the following functions:
269 L<xsinit()>, L<ldopts()>, L<ccopts()>, L<perl_inc()>, L<ccflags()>,
270 L<ccdlflags()>, L<xsi_header()>, L<xsi_protos()>, L<xsi_body()>
272 =head1 FUNCTIONS
274 =item xsinit()
276 Generate C/C++ code for the XS intializer function.
278 When invoked as C<`perl -MExtUtils::Embed -e xsinit --`>
279 the following options are recognized:
281 B<-o> <output filename> (Defaults to B<perlxsi.c>)
283 B<-o STDOUT> will print to STDOUT.
285 B<-std> (Write code for extensions that are linked with the current Perl.)
287 Any additional arguments are expected to be names of modules
288 to generate code for.
290 When invoked with parameters the following are accepted and optional:
292 C<xsinit($filename,$std,[@modules])>
294 Where,
296 B<$filename> is equivalent to the B<-o> option.
298 B<$std> is boolean, equivalent to the B<-std> option.
300 B<[@modules]> is an array ref, same as additional arguments mentioned above.
302 =item Examples
305 perl -MExtUtils::Embed -e xsinit -- -o xsinit.c Socket
308 This will generate code with an B<xs_init> function that glues the perl B<Socket::bootstrap> function
309 to the C B<boot_Socket> function and writes it to a file named "xsinit.c".
311 Note that B<DynaLoader> is a special case where it must call B<boot_DynaLoader> directly.
313 perl -MExtUtils::Embed -e xsinit
316 This will generate code for linking with B<DynaLoader> and
317 each static extension found in B<$Config{static_ext}>.
318 The code is written to the default file name B<perlxsi.c>.
321 perl -MExtUtils::Embed -e xsinit -- -o xsinit.c -std DBI DBD::Oracle
324 Here, code is written for all the currently linked extensions along with code
325 for B<DBI> and B<DBD::Oracle>.
327 If you have a working B<DynaLoader> then there is rarely any need to statically link in any
328 other extensions.
330 =item ldopts()
332 Output arguments for linking the Perl library and extensions to your
333 application.
335 When invoked as C<`perl -MExtUtils::Embed -e ldopts --`>
336 the following options are recognized:
338 B<-std>
340 Output arguments for linking the Perl library and any extensions linked
341 with the current Perl.
343 B<-I> <path1:path2>
345 Search path for ModuleName.a archives.
346 Default path is B<@INC>.
347 Library archives are expected to be found as
348 B</some/path/auto/ModuleName/ModuleName.a>
349 For example, when looking for B<Socket.a> relative to a search path,
350 we should find B<auto/Socket/Socket.a>
352 When looking for B<DBD::Oracle> relative to a search path,
353 we should find B<auto/DBD/Oracle/Oracle.a>
355 Keep in mind, you can always supply B</my/own/path/ModuleName.a>
356 as an additional linker argument.
358 B<--> <list of linker args>
360 Additional linker arguments to be considered.
362 Any additional arguments found before the B<--> token
363 are expected to be names of modules to generate code for.
365 When invoked with parameters the following are accepted and optional:
367 C<ldopts($std,[@modules],[@link_args],$path)>
369 Where,
371 B<$std> is boolean, equivalent to the B<-std> option.
373 B<[@modules]> is equivalent to additional arguments found before the B<--> token.
375 B<[@link_args]> is equivalent to arguments found after the B<--> token.
377 B<$path> is equivalent to the B<-I> option.
379 In addition, when ldopts is called with parameters, it will return the argument string
380 rather than print it to STDOUT.
382 =item Examples
385 perl -MExtUtils::Embed -e ldopts
388 This will print arguments for linking with B<libperl.a>, B<DynaLoader> and
389 extensions found in B<$Config{static_ext}>. This includes libraries
390 found in B<$Config{libs}> and the first ModuleName.a library
391 for each extension that is found by searching B<@INC> or the path
392 specifed by the B<-I> option.
393 In addition, when ModuleName.a is found, additional linker arguments
394 are picked up from the B<extralibs.ld> file in the same directory.
397 perl -MExtUtils::Embed -e ldopts -- -std Socket
400 This will do the same as the above example, along with printing additional arguments for linking with the B<Socket> extension.
403 perl -MExtUtils::Embed -e ldopts -- DynaLoader
406 This will print arguments for linking with just the B<DynaLoader> extension
407 and B<libperl.a>.
410 perl -MExtUtils::Embed -e ldopts -- -std Msql -- -L/usr/msql/lib -lmsql
413 Any arguments after the second '--' token are additional linker
414 arguments that will be examined for potential conflict. If there is no
415 conflict, the additional arguments will be part of the output.
418 =item perl_inc()
420 For including perl header files this function simply prints:
422 -I $Config{archlib}/CORE
424 So, rather than having to say:
426 perl -MConfig -e 'print "-I $Config{archlib}/CORE"'
428 Just say:
430 perl -MExtUtils::Embed -e perl_inc
432 =item ccflags(), ccdlflags()
434 These functions simply print $Config{ccflags} and $Config{ccdlflags}
436 =item ccopts()
438 This function combines perl_inc(), ccflags() and ccdlflags() into one.
440 =item xsi_header()
442 This function simply returns a string defining the same B<EXTERN_C> macro as
443 B<perlmain.c> along with #including B<perl.h> and B<EXTERN.h>.
445 =item xsi_protos(@modules)
447 This function returns a string of B<boot_$ModuleName> prototypes for each @modules.
449 =item xsi_body(@modules)
451 This function returns a string of calls to B<newXS()> that glue the module B<bootstrap>
452 function to B<boot_ModuleName> for each @modules.
454 B<xsinit()> uses the xsi_* functions to generate most of it's code.
456 =head1 EXAMPLES
458 For examples on how to use B<ExtUtils::Embed> for building C/C++ applications
459 with embedded perl, see the eg/ directory and the I<perlembed> man page.
461 =head1 SEE ALSO
463 the I<perlembed> man page
465 =head1 AUTHOR
467 Doug MacEachern <dougm@osf.org>
469 Based on ideas from Tim Bunce <Tim.Bunce@ig.co.uk> and
470 B<minimod.pl> by Andreas Koenig <k@anna.in-berlin.de> and Tim Bunce.
472 =cut