Move ExtUtils::CBuilder from ext/ to cpan/
[p5sagit/p5-mst-13.2.git] / cpan / ExtUtils-CBuilder / lib / ExtUtils / CBuilder / Platform / VMS.pm
CommitLineData
6b09c160 1package ExtUtils::CBuilder::Platform::VMS;
2
3use strict;
4use ExtUtils::CBuilder::Base;
5
6use vars qw($VERSION @ISA);
9ef43512 7$VERSION = '0.2602';
6b09c160 8@ISA = qw(ExtUtils::CBuilder::Base);
9
cdccec0e 10use File::Spec::Functions qw(catfile catdir);
11
12# We do prelink, but don't want the parent to redo it.
13
4629f7b1 14sub need_prelink { 0 }
6b09c160 15
ea2e6518 16sub arg_defines {
17 my ($self, %args) = @_;
18
19 s/"/""/g foreach values %args;
20
a314697d 21 my @config_defines;
ea2e6518 22
23 # VMS can only have one define qualifier; add the one from config, if any.
a314697d 24 if ($self->{config}{ccflags} =~ s{/ def[^=]+ =+ \(? ([^\/\)]*) } {}ix) {
25 push @config_defines, $1;
ea2e6518 26 }
27
a314697d 28 return '' unless keys(%args) || @config_defines;
ea2e6518 29
30 return ('/define=('
ea2e6518 31 . join(',',
a314697d 32 @config_defines,
ea2e6518 33 map "\"$_" . ( length($args{$_}) ? "=$args{$_}" : '') . "\"",
34 keys %args)
35 . ')');
36}
37
6b09c160 38sub arg_include_dirs {
2bd31f1a 39 my ($self, @dirs) = @_;
40
41 # VMS can only have one include list, add the one from config.
42 if ($self->{config}{ccflags} =~ s{/inc[^=]+(?:=)+(?:\()?([^\/\)]*)} {}i) {
43 unshift @dirs, $1;
44 }
45 return unless @dirs;
46
47 return ('/include=(' . join(',', @dirs) . ')');
48}
49
50sub _do_link {
51 my ($self, $type, %args) = @_;
52
53 my $objects = delete $args{objects};
54 $objects = [$objects] unless ref $objects;
55
2bd31f1a 56 if ($args{lddl}) {
2bd31f1a 57
cdccec0e 58 # prelink will call Mksymlists, which creates the extension-specific
59 # linker options file and populates it with the boot symbol.
60
61 my @temp_files = $self->prelink(%args, dl_name => $args{module_name});
2bd31f1a 62
cdccec0e 63 # We now add the rest of what we need to the linker options file. We
64 # should replicate the functionality of C<ExtUtils::MM_VMS::dlsyms>,
65 # but there is as yet no infrastructure for handling object libraries,
66 # so for now we depend on object files being listed individually on the
67 # command line, which should work for simple cases. We do bring in our
68 # own version of C<ExtUtils::Liblist::Kid::ext> so that any additional
69 # libraries (including PERLSHR) can be added to the options file.
70
71 my @optlibs = $self->_liblist_ext( $args{'libs'} );
72
73 my $optfile = 'sys$disk:[]' . $temp_files[0];
74 open my $opt_fh, '>>', $optfile
75 or die "_do_link: Unable to open $optfile: $!";
76 for my $lib (@optlibs) {print $opt_fh "$lib\n" if length $lib }
77 close $opt_fh;
78
79 $objects->[-1] .= ',';
80 push @$objects, $optfile . '/OPTIONS,';
2bd31f1a 81
cdccec0e 82 # This one not needed for DEC C, but leave for completeness.
83 push @$objects, $self->perl_inc() . 'perlshr_attr.opt/OPTIONS';
2bd31f1a 84 }
85
86 return $self->SUPER::_do_link($type, %args, objects => $objects);
6b09c160 87}
88
89sub arg_nolink { return; }
90
91sub arg_object_file {
92 my ($self, $file) = @_;
93 return "/obj=$file";
94}
95
96sub arg_exec_file {
97 my ($self, $file) = @_;
98 return ("/exe=$file");
99}
100
101sub arg_share_object_file {
102 my ($self, $file) = @_;
103 return ("$self->{config}{lddlflags}=$file");
104}
105
2bd31f1a 106
107sub lib_file {
108 my ($self, $dl_file) = @_;
109 $dl_file =~ s/\.[^.]+$//;
110 $dl_file =~ tr/"//d;
111 $dl_file = $dl_file .= '.' . $self->{config}{dlext};
112
113 # Need to create with the same name as DynaLoader will load with.
114 if (defined &DynaLoader::mod2fname) {
115 my ($dev,$dir,$file) = File::Spec->splitpath($dl_file);
116 $file = DynaLoader::mod2fname([$file]);
117 $dl_file = File::Spec->catpath($dev,$dir,$file);
118 }
119 return $dl_file;
120}
121
cdccec0e 122# The following is reproduced almost verbatim from ExtUtils::Liblist::Kid::_vms_ext.
123# We can't just call that because it's tied up with the MakeMaker object hierarchy.
124
125sub _liblist_ext {
126 my($self, $potential_libs,$verbose,$give_libs) = @_;
127 $verbose ||= 0;
128
129 my(@crtls,$crtlstr);
130 @crtls = ( ($self->{'config'}{'ldflags'} =~ m-/Debug-i ? $self->{'config'}{'dbgprefix'} : '')
131 . 'PerlShr/Share' );
132 push(@crtls, grep { not /\(/ } split /\s+/, $self->{'config'}{'perllibs'});
133 push(@crtls, grep { not /\(/ } split /\s+/, $self->{'config'}{'libc'});
134 # In general, we pass through the basic libraries from %Config unchanged.
135 # The one exception is that if we're building in the Perl source tree, and
136 # a library spec could be resolved via a logical name, we go to some trouble
92760223 137 # to ensure that the copy in the local tree is used, rather than one to
cdccec0e 138 # which a system-wide logical may point.
139 if ($self->perl_src) {
140 my($lib,$locspec,$type);
141 foreach $lib (@crtls) {
142 if (($locspec,$type) = $lib =~ m{^([\w\$-]+)(/\w+)?} and $locspec =~ /perl/i) {
143 if (lc $type eq '/share') { $locspec .= $self->{'config'}{'exe_ext'}; }
144 elsif (lc $type eq '/library') { $locspec .= $self->{'config'}{'lib_ext'}; }
145 else { $locspec .= $self->{'config'}{'obj_ext'}; }
146 $locspec = catfile($self->perl_src, $locspec);
147 $lib = "$locspec$type" if -e $locspec;
148 }
149 }
150 }
151 $crtlstr = @crtls ? join(' ',@crtls) : '';
152
153 unless ($potential_libs) {
154 warn "Result:\n\tEXTRALIBS: \n\tLDLOADLIBS: $crtlstr\n" if $verbose;
155 return ('', '', $crtlstr, '', ($give_libs ? [] : ()));
156 }
157
158 my(@dirs,@libs,$dir,$lib,%found,@fndlibs,$ldlib);
159 my $cwd = cwd();
160 my($so,$lib_ext,$obj_ext) = @{$self->{'config'}}{'so','lib_ext','obj_ext'};
161 # List of common Unix library names and their VMS equivalents
162 # (VMS equivalent of '' indicates that the library is automatically
163 # searched by the linker, and should be skipped here.)
164 my(@flibs, %libs_seen);
165 my %libmap = ( 'm' => '', 'f77' => '', 'F77' => '', 'V77' => '', 'c' => '',
166 'malloc' => '', 'crypt' => '', 'resolv' => '', 'c_s' => '',
167 'socket' => '', 'X11' => 'DECW$XLIBSHR',
168 'Xt' => 'DECW$XTSHR', 'Xm' => 'DECW$XMLIBSHR',
169 'Xmu' => 'DECW$XMULIBSHR');
170 if ($self->{'config'}{'vms_cc_type'} ne 'decc') { $libmap{'curses'} = 'VAXCCURSE'; }
171
172 warn "Potential libraries are '$potential_libs'\n" if $verbose;
173
174 # First, sort out directories and library names in the input
175 foreach $lib (split ' ',$potential_libs) {
176 push(@dirs,$1), next if $lib =~ /^-L(.*)/;
177 push(@dirs,$lib), next if $lib =~ /[:>\]]$/;
178 push(@dirs,$lib), next if -d $lib;
179 push(@libs,$1), next if $lib =~ /^-l(.*)/;
180 push(@libs,$lib);
181 }
182 push(@dirs,split(' ',$self->{'config'}{'libpth'}));
183
184 # Now make sure we've got VMS-syntax absolute directory specs
185 # (We don't, however, check whether someone's hidden a relative
186 # path in a logical name.)
187 foreach $dir (@dirs) {
188 unless (-d $dir) {
189 warn "Skipping nonexistent Directory $dir\n" if $verbose > 1;
190 $dir = '';
191 next;
192 }
193 warn "Resolving directory $dir\n" if $verbose;
194 if (!File::Spec->file_name_is_absolute($dir)) {
195 $dir = catdir($cwd,$dir);
196 }
197 }
198 @dirs = grep { length($_) } @dirs;
199 unshift(@dirs,''); # Check each $lib without additions first
200
201 LIB: foreach $lib (@libs) {
202 if (exists $libmap{$lib}) {
203 next unless length $libmap{$lib};
204 $lib = $libmap{$lib};
205 }
206
207 my(@variants,$variant,$cand);
208 my($ctype) = '';
209
210 # If we don't have a file type, consider it a possibly abbreviated name and
211 # check for common variants. We try these first to grab libraries before
212 # a like-named executable image (e.g. -lperl resolves to perlshr.exe
213 # before perl.exe).
214 if ($lib !~ /\.[^:>\]]*$/) {
215 push(@variants,"${lib}shr","${lib}rtl","${lib}lib");
216 push(@variants,"lib$lib") if $lib !~ /[:>\]]/;
217 }
218 push(@variants,$lib);
219 warn "Looking for $lib\n" if $verbose;
220 foreach $variant (@variants) {
221 my($fullname, $name);
222
223 foreach $dir (@dirs) {
224 my($type);
225
226 $name = "$dir$variant";
227 warn "\tChecking $name\n" if $verbose > 2;
228 $fullname = VMS::Filespec::rmsexpand($name);
229 if (defined $fullname and -f $fullname) {
230 # It's got its own suffix, so we'll have to figure out the type
231 if ($fullname =~ /(?:$so|exe)$/i) { $type = 'SHR'; }
232 elsif ($fullname =~ /(?:$lib_ext|olb)$/i) { $type = 'OLB'; }
233 elsif ($fullname =~ /(?:$obj_ext|obj)$/i) {
234 warn "Note (probably harmless): "
235 ."Plain object file $fullname found in library list\n";
236 $type = 'OBJ';
237 }
238 else {
239 warn "Note (probably harmless): "
240 ."Unknown library type for $fullname; assuming shared\n";
241 $type = 'SHR';
242 }
243 }
244 elsif (-f ($fullname = VMS::Filespec::rmsexpand($name,$so)) or
245 -f ($fullname = VMS::Filespec::rmsexpand($name,'.exe'))) {
246 $type = 'SHR';
247 $name = $fullname unless $fullname =~ /exe;?\d*$/i;
248 }
249 elsif (not length($ctype) and # If we've got a lib already,
250 # don't bother
251 ( -f ($fullname = VMS::Filespec::rmsexpand($name,$lib_ext)) or
252 -f ($fullname = VMS::Filespec::rmsexpand($name,'.olb')))) {
253 $type = 'OLB';
254 $name = $fullname unless $fullname =~ /olb;?\d*$/i;
255 }
256 elsif (not length($ctype) and # If we've got a lib already,
257 # don't bother
258 ( -f ($fullname = VMS::Filespec::rmsexpand($name,$obj_ext)) or
259 -f ($fullname = VMS::Filespec::rmsexpand($name,'.obj')))) {
260 warn "Note (probably harmless): "
261 ."Plain object file $fullname found in library list\n";
262 $type = 'OBJ';
263 $name = $fullname unless $fullname =~ /obj;?\d*$/i;
264 }
265 if (defined $type) {
266 $ctype = $type; $cand = $name;
267 last if $ctype eq 'SHR';
268 }
269 }
270 if ($ctype) {
271 # This has to precede any other CRTLs, so just make it first
272 if ($cand eq 'VAXCCURSE') { unshift @{$found{$ctype}}, $cand; }
273 else { push @{$found{$ctype}}, $cand; }
274 warn "\tFound as $cand (really $fullname), type $ctype\n"
275 if $verbose > 1;
276 push @flibs, $name unless $libs_seen{$fullname}++;
277 next LIB;
278 }
279 }
280 warn "Note (probably harmless): "
281 ."No library found for $lib\n";
282 }
283
284 push @fndlibs, @{$found{OBJ}} if exists $found{OBJ};
285 push @fndlibs, map { "$_/Library" } @{$found{OLB}} if exists $found{OLB};
286 push @fndlibs, map { "$_/Share" } @{$found{SHR}} if exists $found{SHR};
287 $lib = join(' ',@fndlibs);
288
289 $ldlib = $crtlstr ? "$lib $crtlstr" : $lib;
290 warn "Result:\n\tEXTRALIBS: $lib\n\tLDLOADLIBS: $ldlib\n" if $verbose;
291 wantarray ? ($lib, '', $ldlib, '', ($give_libs ? \@flibs : ())) : $lib;
292}
293
6b09c160 2941;