Is there a way in perl, to get the source file location of a method ? For example if method - "myMathod" from module "methodModule" is invoked from perl script - "myScript" . And lets say 'myModule' resides in path : /path/to/myModule, so is there a way to do something like this : getSourceFileLocationOf("methodModule") == "/path/to/myModule"
-
You can check the `%INC` hash which has the full file path of each used module: `perl -e 'use Data::Dumper; print Dumper(\%INC);'` – xxfelixxx Feb 05 '18 at 09:32
-
Another example: `perl -e 'use WWW::Mechanize; print $INC{"WWW/Mechanize.pm"} . "\n";'` – xxfelixxx Feb 05 '18 at 09:35
2 Answers
You can check inside the %INC
hash as documented in perldoc perlvar:
%INC
The hash %INC contains entries for each filename included via the do, require, or use operators. The key is the filename you specified (with module names converted to pathnames), and the value is the location of the file found. The require operator uses this hash to determine whether a particular file has already been included.
If the file was loaded via a hook (e.g. a subroutine reference, see require for a description of these hooks), this hook is by default inserted into %INC in place of a filename. Note, however, that the hook may have set the %INC entry by itself to provide some more specific info.
Here is a simple example:
perl -e 'use WWW::Mechanize; print $ENV{"WWW/Mechanize.pm"} . "\n";
output
/usr/local/share/perl5/WWW/Mechanize.pm
As suggested by @zdim, there is also the rather user-friendly Sub::Identify which can be used:
use Sub::Identify qw( :all );
use WWW::Mechanize;
my ($file, $line) = get_code_location( \&WWW::Mechanize::get );
print "File $file, Line $line\n";'
output
File /usr/local/share/perl5/WWW/Mechanize.pm, Line 106
-
While you can find the module's name from the sub's name [using `Devel::Peek`](https://stackoverflow.com/a/3684995/4653379) – zdim Feb 05 '18 at 09:48
-
This doesn't tell you which source file contains the definition of a given method unless there is no inheritance. – Borodin Feb 05 '18 at 09:48
-
And there is also [Sub::Identify](http://search.cpan.org/~rgarcia/Sub-Identify-0.14/lib/Sub/Identify.pm) and, better yet, [Sub::Util](http://search.cpan.org/~pevans/Scalar-List-Utils-1.49/lib/Sub/Util.pm) – zdim Feb 05 '18 at 09:51
-
With `Sub::Identify` and `Sub::Util` it's one simple call, `sub_name` or `subname`. So they can query with the sub name, and then do the `%INC` bit. (`Devel::Peek` does involve more.) – zdim Feb 05 '18 at 09:57
-
Thank you very much ! and if the method is from another perl file (.pl) and not module , will these solutions also work ? – nadavgam Feb 05 '18 at 10:08
To find the package in which the method was found:
use mro qw( );
use Scalar::Util qw( blessed );
sub get_method_package {
my ($obj, $method_name) = @_;
defined( my $class = blessed($obj) )
or return undef;
for my $pkg_name (@{ mro::get_linear_isa($class) }) {
my $pkg = do {
no strict qw( refs );
*{ $pkg_name.'::'.$method_name }
};
return $pkg_name if *{$pkg}{CODE};
}
return undef;
}
Note: Doesn't work if the method is autoloaded.
To find the package in which the method was compiled:
use B qw( svref_2object );
sub get_method_package {
my ($obj, $method_name) = @_;
my $method_ref = $obj->can($method_name)
or return undef;
return svref_2object($method_ref)->GV->STASH->NAME;
}
Note: Only works for autoloaded methods if can is properly overridden.
Note: Works for methods implemented in XS.
To find the file in which the method was compiled:
use B qw( svref_2object );
sub get_method_file {
my ($obj, $method_name) = @_;
my $method_ref = $obj->can($method_name)
or return undef;
return svref_2object($method_ref)->FILE;
}
Note: Only works for autoloaded methods if can is properly overridden.
Note: Only works well for Perl methods. For methods implemented in XS, it returns the name of the .c file with no path. For example, returns XS.c
for JSON::XS->encode
. (This may vary by system, and by XS loader.)

- 367,544
- 15
- 269
- 518