Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:
In our development env, we have, for each release, a "version" of perl that is compliled to know about that version, and the @INC path associated with that. Now, going on release 4.0, and many intervening releases in between, it's getting unwieldy to have to change the interpreter calls in all our perl code as we spin a new release.
What we'd like to do is to link to the current release as /usr/local/OurPerl/bin/perl, but provide the ability to override that (for testing, bug fixing, sustaining maintenance, etc.) via a user ENV variable, say TEST_PERLROOT.
I've just started to muck about with some ideas, but each seems messier than the last.
Anyone else have to solve this problem, or have ideas?
Thoughts much appreciated,
- bill
Comment on how to invoke a different perl interpreter based on user ENV variable
Use #!/usr/bin/env perl -w as your invocation line, and then let people set their $PATH so that they pick up the version of perl that they want.
Alternately you could write a configuration module that you call in every script, which could right away figure out which Perl you wanted, figure out whether it is it, and if it isn't then replace itself with an exec.
Depending on your needs, the configuration module could also decide what lib invocations to import so that the same Perl interpreter can serve up different versions of modules and so on. (Useful for supporting multiple development environments on the same machine.)
If the versioning is very important to you down to the includes, may I suggest using par to bundle all of your code and requires together to have a bundled version locked application. for each build of your app par it give it a unique version number and then promote to released after all qa has been done. this gives you a very good reliable snapshot of all of the required dependancies so you know that the app (when distributed or released) will run in a known state. You may also use the same kit to bundle your app into a executable so that you do not need to track the version of perl that is used to run it.
This solution has the following serious shortcomings, listed in order of increasing seriousness:
It isn't in a BEGIN block, so will not protect you from trying to load modules that aren't there.
You lose @ARGV.
It gets into an endless loop - you need to test whether you have the *right* version of Perl, else when you get the right one, you will keep on thinking that you have the wrong one and exec again.
I just finished realizing #2 and #3 myself and reposted to fix those. My reposted version was enclosed within a BEGIN block to begin with but I removed it because I didn't really see the need for it. Thanks for mentioning that one for me :)
Of course that wouldn't work, silly me. You'd just be continually exec'ing, without passing arguments as well. You'd need to stretch it out with more code:
#!c:/perl/bin/perl -w
if (defined($ARGV[0]) and $ARGV[0] eq 'skip') {
shift @ARGV;
}
else {
exec $ENV{TEST_PERLROOT}, $0, 'skip', @ARGV
if $ENV{TEST_PERLROOT};
}
print 'My arguments: ', join(', ', @ARGV), $/;
excellent. this works.
I'll also look at par.
I wanted to avoid having users messing with their PATH unless that was the last option.
Thanks to all!
- bill
I tried stuff along that line first, to no avail - although I did get some variant of this to work if I invoked the script directly via the shellm, e.g.: sh ./foo.pl.
Unfortunately, that's not practical as some of these scripts are cgi, others called by other progs.