in reply to Re: version based compilation
in thread version based compilation

Very cool. That works. Assign everything but the piece you don't want. That's one I didn't try. And it's so obvious once you see it.

Since you solved that one, how about the bigger question that started me down this path: When a module's VERSION method is called, is there a way to stop compilation of the module at that point and switch to another one? This all started with an experimental piece of code like this:

use Carp; sub UNIVERSAL::VERSION { my $class = shift; my $wanted_version = shift; my $fixed_version = $wanted_version; my $caller = caller(); my $version_class; $fixed_version =~ s/\./_/g; $version_class = "${class}_${fixed_version}"; eval <<"END_EVAL"; package $caller; no $class; require $version_class; $version_class->import(); END_EVAL croak "Version $wanted_version of $class not found ($version_class +): $@" if ($@); }

I believe this works because the eval code runs after the BEGIN code (from use) that invoked the VERSION method. So the versioned copy of the module loads after, overwriting aliases. But ideally I'd want to just stop compilation of the non-versioned module so there are no BEGIN, CHECK, END type blocks pulled in.

Thanks for the help on the one above. Most people I start talking typeglobs and symbol tables to just glaze over.

Replies are listed 'Best First'.
Re: Re: Re: version based compilation
by robin (Chaplain) on Dec 30, 2001 at 04:19 UTC
    Sadly, it's impossible to stop compilation of the module from a VERSION sub, because the module has already been compiled before the VERSION sub is invoked! You can check that by writing a BEGIN block which prints something -- you'll see that the BEGIN block is called before the VERSION sub.

    If you think about it, it has to be done that way. The module needs to be compiled first, otherwise the import() and VERSION() subs wouldn't be defined. Even though CHECK blocks are called later, it's still too late to stop them either: when a CHECK block is compiled, it's added to an internal list of routines to call at the end of compile time, and there's no way to modify that list without writing some hairy C code.

    If you have my Want module installed, you can stop the module use process dead from within the VERSION method: There's an undocumented internal routine Want::double_return which diddles perl's internal data structures so that when you return from the sub you're in, the sub that called you immediately returns as well. So if your VERSION routine contains:

    use Want (); Want::double_return(); return;
    then the use process will be stopped right there, and the import routine will never be called. Unfortunately that still won't stop BEGIN or CHECK blocks, and anyway it's rather too much like black magic for everyday use. Fun though :-)

      Very good info. Your Want package does about as much as I can do here it seems. I'll probably play around with that. I've learned quite a bit more about Perl today which is the Good Thing. Good point about compilation needing to be done for the subs to be defined, etc. I knew my thinking had holes in it. Thanks.