Devel::Hook::INC - Hook into loading and unloading Perl library files.
unshift @INC, My::INC->new;
package My::INC;
use strict;
use warnings;
use base qw( Devel::Hook::INC );
sub before
{
my( $self, $S ) = @_;
warn "Loading $S->{filename}";
}
sub after
{
my( $self, $S ) = @_;
warn "Loaded $S->{filename}";
}
Devel::Hook::INC implements hooks that are called before and after a library file is loaded with "require" in perlfunc or "use" in perlfunc. It is intended for versions of Perl that don't have "%{^HOOK}" in perlvar.
The perl interpreter includes a library file, it looks through a list of places in @INC where the file might be stored. While this is would easily allow us to know when the interpreter starts reading a file, knowing when the interpreter stopped reading a file is harder.
Devel::Hook::INC works by also scanning each line of the library file when it is read. POD is removed and replaced by a #line directive. The perl interpreter stops reading when it sees __END__
and __DATA__
, so Devel::Hook::INC counts those as EOF.
Devel::Hook::INC was written to discover modules that were very slow to load. The goal was to then load those modules only when needed.
push @INC, My::INC->new;
Create the object that will be put into @INC. No parameters.
sub before
{
my( $self, $S ) = @_;
print "Loading $S->{filename}\n";
}
Called before each library file is read and parsed by the perl interpreter. $S
is the "LOADING CONTEXT".
sub after
{
my( $self, $S ) = @_;
print "Loaded $S->{filename}\n";
}
Called after each library file is read but before the perl interpreter finishes parsing it. $S
is the "LOADING CONTEXT".
The "before" and "after" methods are called with a single parameter: a loading context. This context is a hashref with the following keys.
Filename of the library file. This is the string passed to require
or, in the case of use
, the module name is converted to a filename - .pm
appended and ::
is replaced with the directory seperator (/
). Note that this transformation is done by the perl interpreter itself.
Fully qualified filename of the library file being loaded. This is "filename" prefixed with the first relevant directory from @INC
.
Current line number.
Arrayref containing the location the package was first included from. See "caller" in perlfunc.
The filehandle of the package being loaded. Note that this might be at EOF during "after".
The following is a full list of the methods implmented by Devel::Hook::INC. It is intended for advanced use. The API might change. For more details on these methods, read Devel::Hook::INC's source code.
Called by the perl interpreter when a library file is to be loaded. For some undocumented reason the full package name is required.
Builds and returns the loading context. Adds it to the stack.
Removes the current loading context from the stack.
Returns the perl calling context a library file was loaded from. Uses "__reject" to make sure the calling context is relevant. See "caller" in perlfunc.
The calls using @INC hooks tend to be obsucred by Perl - that is, they are wrapped in eval{} or __ANON__ subs. This method is used to filter out those calling contexts and only use relevant ones.
Returns true if this calling context isn't relevant and we should look futher up the stack. Returns false if we should use this calling context.
Opens the file to be parsed and returns a file handle.
Returns the #line
directive that is then passed to the Perl interpreter. Used to skip over POD. See "Plain-Old-Comments-(Not!)" in perlsyn
Debug function.
Returns the current loading context.
Current depth of includes.
Read one line of the package being loaded. Skips over POD. Detects the end of a file and __END__ or __DATA__. This is called by perl interpreter.
Read and return one line of the library file.
Philip Gwyn, <gwyn -AT- cpan.org >
Copyright (C) 2023 by Philip Gwyn
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.26.3 or, at your option, any later version of Perl 5 you may have available.