jwd has asked for the wisdom of the Perl Monks concerning the following question:

I have script that makes heavy use of temp files, developed on a Perl 5.6.1 system. Not suprisingly, I use the File::Temp module to make life simpler and safer. Now I need to make things run on older systems (e.g., 5.005_03).

The first thing I need to do is add File::Temp to the older system, since it didn't become a core module until 5.6.1. I also need to add an updated version of File::Spec, since Perl 5.005_03 includes 0.6 and File::Temp wants 0.8. As I can't muck about with the system's Perl installation, I need to install these modules into a local directory I can access.

So my code looks something like this:

#!/usr/bin/perl -w use strict; use FindBin; use lib "$FindBin::Bin/../lib/perl"; use File::Temp qw(tempfile); # ... remainder snipped ...

Obviously, I've installed the modules into a "cousin" directory at the same level as the script, hence the use of FindBin. But when I run the script, it generates the following type of error:

File::Spec version 0.8 required--this is only version 0.6 at /wonko/sh +are/jwd/lib/perl/File/Temp.pm line 124. BEGIN failed--compilation aborted at /wonko/share/jwd/lib/perl/File/Te +mp.pm line 124. BEGIN failed--compilation aborted at ./foo line 34.

If I toss the "use FindBin;" statement and hardcode the "use lib ...;" statement to a particular path, then all is well. But unfortunately, as I can't predetermine where this will be installed, I really need the FindBin (or something like it).

What seems to be happening is that the system's default (0.6) version of File::Spec is being pulled in by the "use FindBin;" statement (I checked FindBin.pm and it does use File::Spec), effectively masking the local (0.8) version I've so carefully installed into my local "../lib/perl" directory.

So how do I get around this? Is there any method to force Perl to flush (or some such thing) all loaded modules after the "use lib ..." statement? Other alternatives? Setting the PERL5LIB environment variable before invoking the Perl script would work, I guess, but that's a bit much to ask in this environment.

Replies are listed 'Best First'.
Re: Forcing use of newer (local) version of core module
by Abigail (Deacon) on Jul 06, 2001 at 02:21 UTC
    Start your program with something like:
    #!/opt/perl/bin/perl -w use strict; use warnings; use FindBin; BEGIN { delete $INC {'File/Spec.pm'}; delete $INC {'File/Spec/Unix.pm'}; } use vars '$old_W'; BEGIN {$old_W = $^W; $^W = 0} use libs '....'; # The 'cousin' directory here. use File::Spec; BEGIN {$^W = $old_W}
    File::Spec might pull in something else on a different OS. Experiment. The key thing here is the deletion from %INC, which if we leave %INC as it is, will prevent use and require from recompiling a module.

    Note that you'll get warnings if File::Spec would do a use warnings.

    -- Abigail

      Abigail's solution works -- mostly.

      I had to toss the use warnings; pragma, as the module isn't included in Perl 5.005_03.

      The situation now stands as follows:

      • On a 5.005_03 installation, the script runs to completion with no nasty messages.
      • On a 5.6.0 installation, the script yields this warning message:
        Prototype mismatch: sub File::Spec::Unix::rel2abs ($;$;) vs none at /w +onko/share/jwd/lib/perl/File/Spec/Unix.pm line 447.
      Any suggestion as to how to eliminate this? Explanation as to its cause? The mucking about with $^W nukes all the other warnings, save this one.

      FWIW, I didn't really get your closing remark " Note that you'll get warnings if File::Spec would do a use warnings." Care to elaborate?

Re (tilly) 1: Forcing use of newer (local) version of core module
by tilly (Archbishop) on Jul 05, 2001 at 23:48 UTC
    First of all complain to the author of File::Temp. The older versions did not have problems with File::Spec, and core modules shouldn't force people to upgrade without good cause.

    However you can do the following trick. Copy the current File::Spec to Overwrite/File/Spec.pm somewhere, and then at the beginning of it put the following bad hack:

    my $old_warn; BEGIN {$old_warn = $^W;} $^W = $old_warn;
    Now "use Overwrite::File::Spec" will replace all of the methods in File::Spec with the more recent stuff, and avoid the warning.

    You may need appropriate modifications to overwrite modules pulled in by File::Spec as well...

    BTW the above hack? I would document why it is being done. It is bad, and when you upgrade you want to document why it is being done. In fact inside the private copy you might put a VERSION check that will die if it is overwriting something recent, just so you don't forget about this kludge...