Reputation: 445
I'm writing an extension for Mo*se class system and I need to get the list, from inside a package, of all modules required by the package using the "use" statement. I tried to inspect the %INC data struct, but I get the list of ALL modules loaded at compile time, and I cannot filter out the modules loaded by my package. I guess I have to deal with the Perl debugger, but any suggestion will be really appreciated :-)
Eg:
package MyApp 0.001 ;
use Module1 ;
use Module2 ;
...
sub list_requested_modules {
...HOW TO DO IT ???
}
Upvotes: 1
Views: 318
Reputation: 9296
Another option, if you're only interested in knowing what modules the current file will load/has loaded would be PPI:
use warnings;
use strict;
use Data::Dumper;
use PPI;
require Mock::Sub;
my $ppi_doc = PPI::Document->new(__FILE__);
my $ppi_deps = $ppi_doc->find('PPI::Statement::Include');
for (@$ppi_deps){
print $_->module . "\n";
}
Output:
warnings
strict
Data::Dumper
PPI
Mock::Sub
Upvotes: 1
Reputation: 9231
You can't distinguish between modules loaded in the current file or modules that were already loaded. Consider if you have "use Module1;" but Module1 was already loaded, so all that does is import to the current package from the already-loaded module. Where would you then consider that module was loaded from?
Two things you can do depending what you are trying to figure out: you can parse a file to guess what modules it requires (though it doesn't guarantee they'll be loaded from there, they could be already loaded as I mentioned before). A good tool for this is Perl::PrereqScanner::Lite. You can use the __FILE__
literal to get the name of the current file.
use Perl::PrereqScanner::Lite;
my @required = Perl::PrereqScanner::Lite->new->scan_file(__FILE__)->required_modules;
The other option is to track what modules are loaded yourself. At the very beginning of the file put this:
my %original_inc;
BEGIN { %original_inc = %INC }
Then either immediately afterward, to find any modules loaded during compile time (including use
statements), or in a later subroutine, you can compare how %INC changed:
my @newly_loaded = grep { !exists $original_inc{$_} } keys %INC;
In addition to the previously mentioned caveat that modules may have already been previously required and thus already present in %INC, modules you load may load other modules in turn, so the difference is probably not going to exactly match what use
statements are in the file.
EDIT: Personally I would avoid both of these methods by obviating the need for such logic in the first place. Instead of loading your modules with use
, write a subroutine that loads them using Module::Runtime and keeps track of what you load with it in some manner, and call that for each module in a BEGIN block. But note that this would defeat automated prereq scanning such as the PrereqScanner module I mentioned above.
Upvotes: 3