File Coverage

lib/ExtUtils/Mksymlists.pm
Criterion Covered Total %
statement 17 144 11.8
branch 0 72 0.0
condition 0 26 0.0
subroutine 6 12 50.0
pod 0 1 0.0
total 23 255 9.0


line stmt bran cond sub pod time code
1             package ExtUtils::Mksymlists;
2              
3 1     1   7260 use 5.006;
  1         3  
4 1     1   6 use strict qw[ subs refs ];
  1         1  
  1         35  
5             # no strict 'vars'; # until filehandles are exempted
6 1     1   5 use warnings;
  1         1  
  1         35  
7              
8 1     1   6 use Carp;
  1         2  
  1         89  
9 1     1   6 use Exporter;
  1         1  
  1         41  
10 1     1   4 use Config;
  1         2  
  1         2138  
11              
12             our @ISA = qw(Exporter);
13             our @EXPORT = qw(&Mksymlists);
14             our $VERSION = '7.70';
15             $VERSION =~ tr/_//d;
16              
17             sub Mksymlists {
18 0     0 0   my(%spec) = @_;
19 0           my($osname) = $^O;
20              
21             croak("Insufficient information specified to Mksymlists")
22             unless ( $spec{NAME} or
23 0 0 0       ($spec{FILE} and ($spec{DL_FUNCS} or $spec{FUNCLIST})) );
      0        
      0        
24              
25 0 0         $spec{DL_VARS} = [] unless $spec{DL_VARS};
26 0 0         ($spec{FILE} = $spec{NAME}) =~ s/.*::// unless $spec{FILE};
27 0 0         $spec{FUNCLIST} = [] unless $spec{FUNCLIST};
28             $spec{DL_FUNCS} = { $spec{NAME} => [] }
29 0           unless ( ($spec{DL_FUNCS} and keys %{$spec{DL_FUNCS}}) or
30 0 0 0       @{$spec{FUNCLIST}});
  0   0        
31 0 0         if (defined $spec{DL_FUNCS}) {
32 0           foreach my $package (sort keys %{$spec{DL_FUNCS}}) {
  0            
33 0           my($packprefix,$bootseen);
34 0           ($packprefix = $package) =~ s/\W/_/g;
35 0           foreach my $sym (@{$spec{DL_FUNCS}->{$package}}) {
  0            
36 0 0         if ($sym =~ /^boot_/) {
37 0           push(@{$spec{FUNCLIST}},$sym);
  0            
38 0           $bootseen++;
39             }
40             else {
41 0           push(@{$spec{FUNCLIST}},"XS_${packprefix}_$sym");
  0            
42             }
43             }
44 0 0         push(@{$spec{FUNCLIST}},"boot_$packprefix") unless $bootseen;
  0            
45             }
46             }
47              
48             # We'll need this if we ever add any OS which uses mod2fname
49             # not as pseudo-builtin.
50             # require DynaLoader;
51 0 0 0       if (defined &DynaLoader::mod2fname and not $spec{DLBASE}) {
52 0           $spec{DLBASE} = DynaLoader::mod2fname([ split(/::/,$spec{NAME}) ]);
53             }
54              
55 0 0         if ($osname eq 'aix') { _write_aix(\%spec); }
  0 0          
    0          
    0          
    0          
56 0           elsif ($osname eq 'MacOS'){ _write_aix(\%spec) }
57 0           elsif ($osname eq 'VMS') { _write_vms(\%spec) }
58 0           elsif ($osname eq 'os2') { _write_os2(\%spec) }
59 0           elsif ($osname eq 'MSWin32') { _write_win32(\%spec) }
60             else {
61 0           croak("Don't know how to create linker option file for $osname\n");
62             }
63             }
64              
65              
66             sub _write_aix {
67 0     0     my($data) = @_;
68              
69 0           rename "$data->{FILE}.exp", "$data->{FILE}.exp_old";
70              
71 0 0         open( my $exp, ">", "$data->{FILE}.exp")
72             or croak("Can't create $data->{FILE}.exp: $!\n");
73 0 0         print $exp join("\n",@{$data->{DL_VARS}}, "\n") if @{$data->{DL_VARS}};
  0            
  0            
74 0 0         print $exp join("\n",@{$data->{FUNCLIST}}, "\n") if @{$data->{FUNCLIST}};
  0            
  0            
75 0           close $exp;
76             }
77              
78              
79             sub _write_os2 {
80 0     0     my($data) = @_;
81 0           require Config;
82 0 0         my $threaded = ($Config::Config{archname} =~ /-thread/ ? " threaded" : "");
83              
84 0 0         if (not $data->{DLBASE}) {
85 0           ($data->{DLBASE} = $data->{NAME}) =~ s/.*:://;
86 0           $data->{DLBASE} = substr($data->{DLBASE},0,7) . '_';
87             }
88 0   0       my $distname = $data->{DISTNAME} || $data->{NAME};
89 0           $distname = "Distribution $distname";
90 0   0       my $patchlevel = " pl$Config{perl_patchlevel}" || '';
91             my $comment = sprintf "Perl (v%s%s%s) module %s",
92 0           $Config::Config{version}, $threaded, $patchlevel, $data->{NAME};
93 0           chomp $comment;
94 0 0 0       if ($data->{INSTALLDIRS} and $data->{INSTALLDIRS} eq 'perl') {
95 0           $distname = 'perl5-porters@perl.org';
96 0           $comment = "Core $comment";
97             }
98 0           $comment = "$comment (Perl-config: $Config{config_args})";
99 0 0         $comment = substr($comment, 0, 200) . "...)" if length $comment > 203;
100 0           rename "$data->{FILE}.def", "$data->{FILE}_def.old";
101              
102 0 0         open(my $def, ">", "$data->{FILE}.def")
103             or croak("Can't create $data->{FILE}.def: $!\n");
104 0           print $def "LIBRARY '$data->{DLBASE}' INITINSTANCE TERMINSTANCE\n";
105 0           print $def "DESCRIPTION '\@#$distname:$data->{VERSION}#\@ $comment'\n";
106 0           print $def "CODE LOADONCALL\n";
107 0           print $def "DATA LOADONCALL NONSHARED MULTIPLE\n";
108 0           print $def "EXPORTS\n ";
109 0 0         print $def join("\n ",@{$data->{DL_VARS}}, "\n") if @{$data->{DL_VARS}};
  0            
  0            
110 0 0         print $def join("\n ",@{$data->{FUNCLIST}}, "\n") if @{$data->{FUNCLIST}};
  0            
  0            
111 0           _print_imports($def, $data);
112 0           close $def;
113             }
114              
115             sub _print_imports {
116 0     0     my ($def, $data)= @_;
117             my $imports= $data->{IMPORTS}
118 0 0         or return;
119 0 0         if ( keys %$imports ) {
120 0           print $def "IMPORTS\n";
121 0           foreach my $name (sort keys %$imports) {
122 0           print $def " $name=$imports->{$name}\n";
123             }
124             }
125             }
126              
127             sub _write_win32 {
128 0     0     my($data) = @_;
129              
130 0           require Config;
131 0 0         if (not $data->{DLBASE}) {
132 0           ($data->{DLBASE} = $data->{NAME}) =~ s/.*:://;
133 0           $data->{DLBASE} = substr($data->{DLBASE},0,7) . '_';
134             }
135 0           rename "$data->{FILE}.def", "$data->{FILE}_def.old";
136              
137 0 0         open( my $def, ">", "$data->{FILE}.def" )
138             or croak("Can't create $data->{FILE}.def: $!\n");
139             # put library name in quotes (it could be a keyword, like 'Alias')
140 0 0         if ($Config::Config{'cc'} !~ /\bgcc/i) {
141 0           print $def "LIBRARY \"$data->{DLBASE}\"\n";
142             }
143 0           print $def "EXPORTS\n ";
144 0           my @syms;
145             # Export public symbols both with and without underscores to
146             # ensure compatibility between DLLs from Borland C and Visual C
147             # NOTE: DynaLoader itself only uses the names without underscores,
148             # so this is only to cover the case when the extension DLL may be
149             # linked to directly from C. GSAR 97-07-10
150              
151             #bcc dropped in 5.16, so dont create useless extra symbols for export table
152 0 0         unless("$]" >= 5.016) {
153 0 0         if ($Config::Config{'cc'} =~ /^bcc/i) {
154             push @syms, "_$_", "$_ = _$_"
155 0           for (@{$data->{DL_VARS}}, @{$data->{FUNCLIST}});
  0            
  0            
156             }
157             else {
158             push @syms, "$_", "_$_ = $_"
159 0           for (@{$data->{DL_VARS}}, @{$data->{FUNCLIST}});
  0            
  0            
160             }
161             } else {
162             push @syms, "$_"
163 0           for (@{$data->{DL_VARS}}, @{$data->{FUNCLIST}});
  0            
  0            
164             }
165 0 0         print $def join("\n ",@syms, "\n") if @syms;
166 0           _print_imports($def, $data);
167 0           close $def;
168             }
169              
170              
171             sub _write_vms {
172 0     0     my($data) = @_;
173              
174 0           require Config; # a reminder for once we do $^O
175 0           require ExtUtils::XSSymSet;
176              
177 0           my($isvax) = $Config::Config{'archname'} =~ /VAX/i;
178 0           my($set) = new ExtUtils::XSSymSet;
179              
180 0           rename "$data->{FILE}.opt", "$data->{FILE}.opt_old";
181              
182 0 0         open(my $opt,">", "$data->{FILE}.opt")
183             or croak("Can't create $data->{FILE}.opt: $!\n");
184              
185             # Options file declaring universal symbols
186             # Used when linking shareable image for dynamic extension,
187             # or when linking PerlShr into which we've added this package
188             # as a static extension
189             # We don't do anything to preserve order, so we won't relax
190             # the GSMATCH criteria for a dynamic extension
191              
192             print $opt "case_sensitive=yes\n"
193 0 0         if $Config::Config{d_vms_case_sensitive_symbols};
194              
195 0           foreach my $sym (@{$data->{FUNCLIST}}) {
  0            
196 0           my $safe = $set->addsym($sym);
197 0 0         if ($isvax) { print $opt "UNIVERSAL=$safe\n" }
  0            
198 0           else { print $opt "SYMBOL_VECTOR=($safe=PROCEDURE)\n"; }
199             }
200              
201 0           foreach my $sym (@{$data->{DL_VARS}}) {
  0            
202 0           my $safe = $set->addsym($sym);
203 0           print $opt "PSECT_ATTR=${sym},PIC,OVR,RD,NOEXE,WRT,NOSHR\n";
204 0 0         if ($isvax) { print $opt "UNIVERSAL=$safe\n" }
  0            
205 0           else { print $opt "SYMBOL_VECTOR=($safe=DATA)\n"; }
206             }
207              
208 0           close $opt;
209             }
210              
211             1;
212              
213             __END__
214              
215             =head1 NAME
216              
217             ExtUtils::Mksymlists - write linker options files for dynamic extension
218              
219             =head1 SYNOPSIS
220              
221             use ExtUtils::Mksymlists;
222             Mksymlists( NAME => $name ,
223             DL_VARS => [ $var1, $var2, $var3 ],
224             DL_FUNCS => { $pkg1 => [ $func1, $func2 ],
225             $pkg2 => [ $func3 ] );
226              
227             =head1 DESCRIPTION
228              
229             C<ExtUtils::Mksymlists> produces files used by the linker under some OSs
230             during the creation of shared libraries for dynamic extensions. It is
231             normally called from a MakeMaker-generated Makefile when the extension
232             is built. The linker option file is generated by calling the function
233             C<Mksymlists>, which is exported by default from C<ExtUtils::Mksymlists>.
234             It takes one argument, a list of key-value pairs, in which the following
235             keys are recognized:
236              
237             =over 4
238              
239             =item DLBASE
240              
241             This item specifies the name by which the linker knows the
242             extension, which may be different from the name of the
243             extension itself (for instance, some linkers add an '_' to the
244             name of the extension). If it is not specified, it is derived
245             from the NAME attribute. It is presently used only by OS2 and Win32.
246              
247             =item DL_FUNCS
248              
249             This is identical to the DL_FUNCS attribute available via MakeMaker,
250             from which it is usually taken. Its value is a reference to an
251             associative array, in which each key is the name of a package, and
252             each value is an a reference to an array of function names which
253             should be exported by the extension. For instance, one might say
254             C<DL_FUNCS =E<gt> { Homer::Iliad =E<gt> [ qw(trojans greeks) ],
255             Homer::Odyssey =E<gt> [ qw(travellers family suitors) ] }>. The
256             function names should be identical to those in the XSUB code;
257             C<Mksymlists> will alter the names written to the linker option
258             file to match the changes made by F<xsubpp>. In addition, if
259             none of the functions in a list begin with the string B<boot_>,
260             C<Mksymlists> will add a bootstrap function for that package,
261             just as xsubpp does. (If a B<boot_E<lt>pkgE<gt>> function is
262             present in the list, it is passed through unchanged.) If
263             DL_FUNCS is not specified, it defaults to the bootstrap
264             function for the extension specified in NAME.
265              
266             =item DL_VARS
267              
268             This is identical to the DL_VARS attribute available via MakeMaker,
269             and, like DL_FUNCS, it is usually specified via MakeMaker. Its
270             value is a reference to an array of variable names which should
271             be exported by the extension.
272              
273             =item FILE
274              
275             This key can be used to specify the name of the linker option file
276             (minus the OS-specific extension), if for some reason you do not
277             want to use the default value, which is the last word of the NAME
278             attribute (I<e.g.> for C<Tk::Canvas>, FILE defaults to C<Canvas>).
279              
280             =item FUNCLIST
281              
282             This provides an alternate means to specify function names to be
283             exported from the extension. Its value is a reference to an
284             array of function names to be exported by the extension. These
285             names are passed through unaltered to the linker options file.
286             Specifying a value for the FUNCLIST attribute suppresses automatic
287             generation of the bootstrap function for the package. To still create
288             the bootstrap name you have to specify the package name in the
289             DL_FUNCS hash:
290              
291             Mksymlists( NAME => $name ,
292             FUNCLIST => [ $func1, $func2 ],
293             DL_FUNCS => { $pkg => [] } );
294              
295              
296             =item IMPORTS
297              
298             This attribute is used to specify names to be imported into the
299             extension. It is currently only used by OS/2 and Win32.
300              
301             =item NAME
302              
303             This gives the name of the extension (I<e.g.> C<Tk::Canvas>) for which
304             the linker option file will be produced.
305              
306             =back
307              
308             When calling C<Mksymlists>, one should always specify the NAME
309             attribute. In most cases, this is all that's necessary. In
310             the case of unusual extensions, however, the other attributes
311             can be used to provide additional information to the linker.
312              
313             =head1 AUTHOR
314              
315             Charles Bailey I<E<lt>bailey@newman.upenn.eduE<gt>>
316              
317             =head1 REVISION
318              
319             Last revised 14-Feb-1996, for Perl 5.002.