A stated objective of Inline 0.50 is to allow modules using Inline to
work even if the user doesn't have Inline.
Here is one implementation idea - the distribution contains
pre-computed Inline files, and creates a dual-use (with or without
Inline) object file installation, which is accessed by a very small
and simple Inline::Everywhere reflector.
A module wishing this functionality might say
use Inline::Everywhere ...;
instead of
use Inline ...;
Or perhaps
use Inline::Everywere ..., BUT_DONT_USE_INLINE_BY_DEFAULT => 1;
if one wished to insulate the module from the vagaries of the user's
Inline installation.
When Inline is unavailable, or the module writer has requested it not
be used, then Inline::Everywere does a normal, non-Inline, dynamic load.
Otherwise, it hands off to Inline.
The distribution would need to install Inline::Everywhere if the user
doesn't already have it.
For the user to utilize an Inline-based module without having Inline,
Inline must have been run as part of the distribution creation process,
and the portable (XS or C) result captured in the distribution.
The .inl file and extra compiler options as well. Perhaps using a
perl -MInline=MAKE_DIST. The user's "make install" would then unpack
this information, and create files which could be used both with and
without Inline.
Inline::Everywhere might look something like this (completely bogus
untested code)...
package Inline::Everywhere;
sub import {
shift;
my($pkg) = caller;
my $Inline_is_available = eval("use Inline; 1");
my $use_Inline = $Inline_is_available;
# $use_Inline = 0 if ... module says so.
if($use_Inline) {
local $Inline::Everywhere::_args_tmp = \@_;
eval("package $pkg;".
"Inline->import(\@{\$Inline::Everywhere::_args_tmp});");
} elsif(!$Inline::Everywhere::_is_done_with_package{$pkg}) {
return if !@_;
$Inline::Everywhere::_is_done_with_package{$pkg} = 1;
eval <<" END";
package $pkg;
require DynaLoader;
INIT {
push(\@ISA,'DynaLoader') if !grep(/^DynaLoader\$/,\@ISA);
bootstrap $pkg;
}
END
die "eval failed $@" if $@;
}
}
sub bind { croak "Inline::Everywhere doesn't support bind"; }
For simplicity, one might only support a subset of Inline's
functionality. Eg, no bind, only a single object file per .pm,
no hairy use of BEGIN to create site-specific compiler options, etc.
The only Inline vs non-Inline conflict in the .so/.dll files might be
the boot_ variable (package name or code hash). So one might just add
a package name boot var alias to all Inline object files.
I don't have Inline::Everything doing hash code stuff, because that
seems insufficiently stable.
Basically, Inline is being used as an XS generator. And with
Inline::Everywhere being kept trivially simple, reliability comparable
to current XS-based modules might be achieved. Which was one
objective of the exercise.
Of course, just using the existing Inline normally, with a
ExtUtils::MakeMaker PREREQ_PM to trigger installation of Inline from
CPAN, is sooo much simpler. But that wasn't the objective.
Just an idea,
Mitchell Charity