Michael G Schwern wrote:
If it has to scan the filesystem to figure out what's in inc/ then there could be problems. A simple work around for non-case preserving file systems might be a patch to Module::Install::Base to peek inside the .pm file for a package statement which matches (case- insensitively) the name of the file and using that to correct the case.
I've done something like that in the attached patch, basically cribbing from what AutoInstall does to scan for package names.
I tried modifying several places that seemed to be doing something similar to that (to no avail), but I don't understand the code duplication between inc/ and lib/
My guess is Module::Install is deliberately using itself to install itself so as to better eat its own dog food.
MakeMaker eats its own dog food, but it doesn't require the maintenance of two versions of the same code. I'm guessing (and hoping) the stuff under inc/ is automatically derived somehow from what's under lib/. The POD is stripped and there are line numbers squirted in, kinda like what xsubpp does when generating C from XS, but heck if I know what the process is or can find anything documented that explains it. So the patch makes the same modifications twice, once under inc/ and once under lib/. This is less than optimal, since it looks like only the inc/ stuff gets tested but only the lib/ stuff (or blib/lib/) gets installed.
Here are the changes:
1.) When hacking the internals of a generated Makefile, use the $(NOECHO) macro instead of just '@' and always leave whitespace after it. The whitespace is mandatory on VMS; without it, the '@' is considered part of the command that gets passed to the shell.
2.) Use '_author' instead of '.author' when on VMS since a dot in a directory name is usually invalid and always awkward.
3.) Be case blind when searching @INC for $self-{prefix}.
4.) When finding extensions, obtain case-preserved package names from inside the file when necessary.
5.) When rewriting the guts of a generated Makefile, use MM->{FIRST_MAKEFILE} as the name of the file rather than just 'Makefile', which is highly unlikely to be the correct name on VMS.
6.) When rewriting the guts of a generated Makefile to add -Iinc to all the Perl commands, surround the switch in double quotes to preserve case on the command line.
After the patch, Module::Install will build and passes its very minimal test suite using Perl 5.8.4 on OpenVMS Alpha v7.3-1.
--- inc/ExtUtils/AutoInstall.pm;-0 Thu Sep 9 10:01:43 2004 +++ inc/ExtUtils/AutoInstall.pm Fri Mar 25 22:53:28 2005 @@ -585,7 +585,7 @@ sub _make_args { $PostambleActions = ( $missing ? "\$(PERL) $0 --config=$config --installdeps=$missing" - : "[EMAIL PROTECTED](NOOP)" + : "\$(NOECHO) \$(NOOP)" ); return %args; @@ -626,7 +626,7 @@ sub postamble { return << "."; config :: installdeps [EMAIL PROTECTED](NOOP) +\t\$(NOECHO) \$(NOOP) checkdeps :: \t\$(PERL) $0 --checkdeps --- inc/Module/Install.pm;-0 Thu Sep 9 10:01:42 2004 +++ inc/Module/Install.pm Fri Mar 25 22:53:28 2005 @@ -73,7 +73,7 @@ sub new { $args{dispatch} ||= 'Admin'; $args{prefix} ||= 'inc'; - $args{author} ||= '.author'; + $args{author} ||= ($^O eq 'VMS' ? '_author' : '.author'); $args{bundle} ||= 'inc/BUNDLES'; $class =~ s/^\Q$args{prefix}\E:://; @@ -130,7 +130,7 @@ sub load_extensions { my ($self, $path, $top_obj) = @_; unshift @INC, $self->{prefix} - unless grep { $_ eq $self->{prefix} } @INC; + unless grep { lc($_) eq lc($self->{prefix}) } @INC; local @INC = ($path, @INC); foreach my $rv ($self->find_extensions($path)) { @@ -152,10 +152,31 @@ sub find_extensions { File::Find::find(sub { my $file = $File::Find::name; return unless $file =~ m!^\Q$path\E/(.+)\.pm\Z!is; - return if $1 eq $self->{dispatch}; + return if lc($1) eq lc($self->{dispatch}); $file = "$self->{path}/$1.pm"; my $pkg = "$self->{name}::$1"; $pkg =~ s!/!::!g; + + # If we have a mixed-case package name, assume case has been preserved + # correctly. Otherwise, root through the file to locate the case-preserved + # version of the package name. + + if ($1 eq lc($1) || $1 eq uc($1)) { + open PKGFILE, "<$1.pm" or die "find_extensions: Can't open $1.pm: $!"; + my $in_pod = 0; + while (<PKGFILE>) { + $in_pod = 1 if /^=\w/; + $in_pod = 0 if /^=cut/; + next if ($in_pod || /^=cut/); # skip pod text + next if /^\s*#/; # and comments + + if (m/^\s*package\s+($pkg)\s*;/i) { + $pkg = $1; + last; + } + } + close PKGFILE; + } push @found, [$file, $pkg]; }, $path) if -d $path; --- inc/Module/Install/Makefile.pm;-0 Thu Sep 9 10:01:46 2004 +++ inc/Module/Install/Makefile.pm Fri Mar 25 23:24:49 2005 @@ -90,13 +90,14 @@ sub write { $args{dist} = $self->admin->preop; } - ExtUtils::MakeMaker::WriteMakefile(%args); + my $mm = ExtUtils::MakeMaker::WriteMakefile(%args); - $self->fix_up_makefile(); + $self->fix_up_makefile($mm->{FIRST_MAKEFILE}); } sub fix_up_makefile { my $self = shift; + my $makefile_name = shift; my $top_class = ref($self->_top) || ''; my $top_version = $self->_top->VERSION || ''; @@ -106,7 +107,7 @@ sub fix_up_makefile { my $postamble = "# Postamble by $top_class $top_version\n" . ($self->postamble || ''); - open MAKEFILE, '< Makefile' or die $!; + open MAKEFILE, "< $makefile_name" or die "fix_up_makefile: Couldn't open $makefile_name: $!"; my $makefile = do { local $/; <MAKEFILE> }; close MAKEFILE; @@ -114,10 +115,10 @@ sub fix_up_makefile { $makefile =~ s/( -I\$\(INST_ARCHLIB\))/ -Iinc$1/g; $makefile =~ s/( "-I\$\(INST_LIB\)")/ "-Iinc"$1/g; - $makefile =~ s/^(FULLPERL = .*)/$1 -Iinc/m; - $makefile =~ s/^(PERL = .*)/$1 -Iinc/m; + $makefile =~ s/^(FULLPERL = .*)/$1 "-Iinc"/m; + $makefile =~ s/^(PERL = .*)/$1 "-Iinc"/m; - open MAKEFILE, '> Makefile' or die $!; + open MAKEFILE, "> $makefile_name" or die "fix_up_makefile: Couldn't open $makefile_name: $!"; print MAKEFILE "$preamble$makefile$postamble"; close MAKEFILE; } --- inc/Module/Install/PAR.pm;-0 Thu Sep 9 10:01:46 2004 +++ inc/Module/Install/PAR.pm Fri Mar 25 22:53:29 2005 @@ -39,18 +39,18 @@ sub par_base { # --- $class section: all :: [EMAIL PROTECTED] -M$inc_class -e \"extract_par(q($file))\" +\t\$(NOECHO) $perl -\"M$inc_class\" -e \"extract_par(q($file))\" END $self->postamble(<<"END"); # --- $class section: -$file: all test [EMAIL PROTECTED](PERL) -M$inc_class -e \"make_par(q($file))\" +$file : all test +\t\$(NOECHO) \$(PERL) -\"M$inc_class\" -e \"make_par(q($file))\" par :: $file [EMAIL PROTECTED](NOOP) +\t\$(NOECHO) \$(NOOP) par-upload :: $file \tcpan-upload -verbose $file --- lib/Module/Install/Makefile.pm;-0 Thu Sep 9 08:26:15 2004 +++ lib/Module/Install/Makefile.pm Fri Mar 25 23:25:23 2005 @@ -89,13 +89,14 @@ sub write { $args{dist} = $self->admin->preop; } - ExtUtils::MakeMaker::WriteMakefile(%args); + my $mm = ExtUtils::MakeMaker::WriteMakefile(%args); - $self->fix_up_makefile(); + $self->fix_up_makefile($mm->{FIRST_MAKEFILE}); } sub fix_up_makefile { my $self = shift; + my $makefile_name = shift; my $top_class = ref($self->_top) || ''; my $top_version = $self->_top->VERSION || ''; @@ -105,7 +106,7 @@ sub fix_up_makefile { my $postamble = "# Postamble by $top_class $top_version\n" . ($self->postamble || ''); - open MAKEFILE, '< Makefile' or die $!; + open MAKEFILE, "< $makefile_name" or die "fix_up_makefile: Couldn't open $makefile_name: $!"; my $makefile = do { local $/; <MAKEFILE> }; close MAKEFILE; @@ -113,10 +114,10 @@ sub fix_up_makefile { $makefile =~ s/( -I\$\(INST_ARCHLIB\))/ -Iinc$1/g; $makefile =~ s/( "-I\$\(INST_LIB\)")/ "-Iinc"$1/g; - $makefile =~ s/^(FULLPERL = .*)/$1 -Iinc/m; - $makefile =~ s/^(PERL = .*)/$1 -Iinc/m; + $makefile =~ s/^(FULLPERL = .*)/$1 "-Iinc"/m; + $makefile =~ s/^(PERL = .*)/$1 "-Iinc"/m; - open MAKEFILE, '> Makefile' or die $!; + open MAKEFILE, "> $makefile_name" or die "fix_up_makefile: Couldn't open $!"; print MAKEFILE "$preamble$makefile$postamble"; close MAKEFILE; } --- lib/Module/Install/PAR.pm;-0 Thu Sep 9 08:26:15 2004 +++ lib/Module/Install/PAR.pm Fri Mar 25 22:53:29 2005 @@ -38,18 +38,18 @@ sub par_base { # --- $class section: all :: [EMAIL PROTECTED] -M$inc_class -e \"extract_par(q($file))\" +\t\$(NOECHO) $perl -\"M$inc_class\" -e \"extract_par(q($file))\" END $self->postamble(<<"END"); # --- $class section: -$file: all test [EMAIL PROTECTED](PERL) -M$inc_class -e \"make_par(q($file))\" +$file : all test +\t\$(NOECHO) \$(PERL) -\"M$inc_class\" -e \"make_par(q($file))\" par :: $file [EMAIL PROTECTED](NOOP) +\t\$(NOECHO) \$(NOOP) par-upload :: $file \tcpan-upload -verbose $file