1 package Module::Build::Platform::VMS;
6 $VERSION = eval $VERSION;
7 use Module::Build::Base;
10 @ISA = qw(Module::Build::Base);
16 Module::Build::Platform::VMS - Builder class for VMS platforms
20 This module inherits from C<Module::Build::Base> and alters a few
21 minor details of its functionality. Please see L<Module::Build> for
24 =head2 Overridden Methods
30 Change $self->{build_script} to 'Build.com' so @Build works.
36 $self->SUPER::_set_defaults(@_);
38 $self->{properties}{build_script} = 'Build.com';
44 '@Build foo' on VMS will not preserve the case of 'foo'. Rather than forcing
45 people to write '@Build "foo"' we'll dispatch case-insensitively.
51 my($action, $args) = $self->SUPER::cull_args(@_);
52 my @possible_actions = grep { lc $_ eq lc $action } $self->known_actions;
54 die "Ambiguous action '$action'. Could be one of @possible_actions"
55 if @possible_actions > 1;
57 return ($possible_actions[0], $args);
61 =item manpage_separator
63 Use '__' instead of '::'.
67 sub manpage_separator {
74 Prefixify taking into account VMS' filepath syntax.
78 # Translated from ExtUtils::MM_VMS::prefixify()
80 my($self, $path, $sprefix, $type) = @_;
81 my $rprefix = $self->prefix;
83 $self->log_verbose(" prefixify $path from $sprefix to $rprefix\n");
85 # Translate $(PERLPREFIX) to a real path.
86 $rprefix = VMS::Filespec::vmspath($rprefix) if $rprefix;
87 $sprefix = VMS::Filespec::vmspath($sprefix) if $sprefix;
89 $self->log_verbose(" rprefix translated to $rprefix\n".
90 " sprefix translated to $sprefix\n");
92 if( length $path == 0 ) {
93 $self->log_verbose(" no path to prefixify.\n")
95 elsif( !File::Spec->file_name_is_absolute($path) ) {
96 $self->log_verbose(" path is relative, not prefixifying.\n");
98 elsif( $sprefix eq $rprefix ) {
99 $self->log_verbose(" no new prefix.\n");
102 my($path_vol, $path_dirs) = File::Spec->splitpath( $path );
103 my $vms_prefix = $self->config('vms_prefix');
104 if( $path_vol eq $vms_prefix.':' ) {
105 $self->log_verbose(" $vms_prefix: seen\n");
107 $path_dirs =~ s{^\[}{\[.} unless $path_dirs =~ m{^\[\.};
108 $path = $self->_catprefix($rprefix, $path_dirs);
111 $self->log_verbose(" cannot prefixify.\n");
112 return $self->prefix_relpaths($self->installdirs, $type);
116 $self->log_verbose(" now $path\n");
123 Command-line arguments (but not the command itself) must be quoted
124 to ensure case preservation.
129 # Returns a string that can become [part of] a command line with
130 # proper quoting so that the subprocess sees this same list of args,
131 # or if we get a single arg that is an array reference, quote the
132 # elements of it and return the reference.
133 my ($self, @args) = @_;
134 my $got_arrayref = (scalar(@args) == 1
135 && UNIVERSAL::isa($args[0], 'ARRAY'))
139 # Do not quote qualifiers that begin with '/'.
141 $_ =~ s/\"/""/g; # escape C<"> by doubling
145 ($got_arrayref ? @{$args[0]}
149 return $got_arrayref ? $args[0]
155 There is no native fork(), so some constructs depending on it are not
160 sub have_forkpipe { 0 }
164 Override to ensure that we quote the arguments but not the command.
169 # The command must not be quoted but the arguments to it must be.
170 my ($self, @cmd) = @_;
171 my $cmd = shift @cmd;
172 my $args = $self->_quote_args(@cmd);
178 Override to ensure that we quote the arguments but not the command.
183 # The command must not be quoted but the arguments to it must be.
184 my ($self, @cmd) = @_;
185 $self->log_info("@cmd\n");
186 my $cmd = shift @cmd;
187 my $args = $self->_quote_args(@cmd);
188 return !system("$cmd $args");
193 Override to ensure that we do not quote the command.
199 my $oneliner = $self->SUPER::oneliner(@_);
201 $oneliner =~ s/^\"\S+\"//;
203 return "MCR $^X $oneliner";
208 Inherit the standard version but tweak the library file name to be
209 something Dynaloader can find.
217 my $spec = $self->SUPER::_infer_xs_spec($file);
219 # Need to create with the same name as DynaLoader will load with.
220 if (defined &DynaLoader::mod2fname) {
221 my $file = $$spec{module_name} . '.' . $self->{config}->get('dlext');
223 $file = DynaLoader::mod2fname([$file]);
224 $$spec{lib_file} = File::Spec->catfile($$spec{archdir}, $file);
232 Inherit the standard version but remove dots at end of name.
233 If the extended character set is in effect, do not remove dots from filenames
234 with Unix path delimiters.
239 my ($self, $dir, $pattern) = @_;
241 my $result = $self->SUPER::rscan_dir( $dir, $pattern );
243 for my $file (@$result) {
244 if (!_efs() && ($file =~ m#/#)) {
253 Inherit the standard version but replace embedded dots with underscores because
254 a dot is the directory delimiter on VMS.
261 my $dist_dir = $self->SUPER::dist_dir;
262 $dist_dir =~ s/\./_/g unless _efs();
268 Inherit the standard version but chop the extra manpage delimiter off the front if
269 there is one. The VMS version of splitdir('[.foo]') returns '', 'foo'.
276 my $mpname = $self->SUPER::man3page_name( shift );
277 my $sep = $self->manpage_separator;
278 $mpname =~ s/^$sep//;
282 =item expand_test_dir
284 Inherit the standard version but relativize the paths as the native glob() doesn't
289 sub expand_test_dir {
290 my ($self, $dir) = @_;
292 my @reldirs = $self->SUPER::expand_test_dir( $dir );
294 for my $eachdir (@reldirs) {
295 my ($v,$d,$f) = File::Spec->splitpath( $eachdir );
296 my $reldir = File::Spec->abs2rel( File::Spec->catpath( $v, $d, '' ) );
297 $eachdir = File::Spec->catfile( $reldir, $f );
304 The home-grown glob() does not currently handle tildes, so provide limited support
305 here. Expect only UNIX format file specifications for now.
310 my ($self, $arg) = @_;
312 # Apparently double ~ are not translated.
313 return $arg if ($arg =~ /^~~/);
315 # Apparently ~ followed by whitespace are not translated.
316 return $arg if ($arg =~ /^~ /);
324 # Remove any slash following the tilde if present.
327 # break up the paths for the merge
328 my $home = VMS::Filespec::unixify($ENV{HOME});
330 # In the default VMS mode, the trailing slash is present.
331 # In Unix report mode it is not. The parsing logic assumes that
333 $home .= '/' unless $home =~ m#/$#;
335 # Trivial case of just ~ by it self
341 my ($hvol, $hdir, $hfile) = File::Spec::Unix->splitpath($home);
343 # Someone has tampered with $ENV{HOME}
344 # So hfile is probably the directory since this should be
349 my ($vol, $dir, $file) = File::Spec::Unix->splitpath($spec);
351 my @hdirs = File::Spec::Unix->splitdir($hdir);
352 my @dirs = File::Spec::Unix->splitdir($dir);
356 # Two cases of tilde handling
357 if ($arg =~ m#^~/#) {
359 # Simple case, just merge together
360 $newdirs = File::Spec::Unix->catdir(@hdirs, @dirs);
364 # Complex case, need to add an updir - No delimiters
365 my @backup = File::Spec::Unix->splitdir(File::Spec::Unix->updir);
367 $newdirs = File::Spec::Unix->catdir(@hdirs, @backup, @dirs);
371 # Now put the two cases back together
372 $arg = File::Spec::Unix->catpath($hvol, $newdirs, $file);
379 =item find_perl_interpreter
381 On VMS, $^X returns the fully qualified absolute path including version
382 number. It's logically impossible to improve on it for getting the perl
383 we're currently running, and attempting to manipulate it is usually
388 sub find_perl_interpreter {
389 return VMS::Filespec::vmsify($^X);
392 =item localize_file_path
394 Convert the file path to the local syntax
398 sub localize_file_path {
399 my ($self, $path) = @_;
400 $path = VMS::Filespec::vmsify($path);
405 =item localize_dir_path
407 Convert the directory path to the local syntax
411 sub localize_dir_path {
412 my ($self, $path) = @_;
413 return VMS::Filespec::vmspath($path);
418 The home-grown glob() expands a bit too aggressively when given a bare name,
419 so default in a zero-length extension.
425 foreach my $item (map glob(VMS::Filespec::rmsexpand($_, '.;0')), $self->cleanup) {
426 $self->delete_filetree($item);
431 # Need to look up the feature settings. The preferred way is to use the
432 # VMS::Feature module, but that may not be available to dual life modules.
436 if (eval { local $SIG{__DIE__}; require VMS::Feature; }) {
441 # Need to look up the UNIX report mode. This may become a dynamic mode
446 $unix_rpt = VMS::Feature::current("filename_unix_report");
448 my $env_unix_rpt = $ENV{'DECC$FILENAME_UNIX_REPORT'} || '';
449 $unix_rpt = $env_unix_rpt =~ /^[ET1]/i;
454 # Need to look up the EFS character set mode. This may become a dynamic
455 # mode in the future.
459 $efs = VMS::Feature::current("efs_charset");
461 my $env_efs = $ENV{'DECC$EFS_CHARSET'} || '';
462 $efs = $env_efs =~ /^[ET1]/i;
471 Michael G Schwern <schwern@pobox.com>
472 Ken Williams <kwilliams@cpan.org>
473 Craig A. Berry <craigberry@mac.com>
477 perl(1), Module::Build(3), ExtUtils::MakeMaker(3)