views:

76

answers:

3

I am trying to figure out which module in my CGI::Application is loading Moose. I attempted to overload "require" but I don't seem to have the syntax quite right. If someone could clean up the following code I would appreciate it:

use strict;
use warnings;
use Carp qw//;

BEGIN {
  *CORE::GLOBAL::require = sub (*) { 
    warn "Requiring $_[0] at: " . Carp::longmess();
    CORE::require (@_);
  };
}

Basically, the problem with this script is that it isn't actually loading anything. When CORE::require(@) is called is doesn't "do" anything. I tried just passing it the script name directly using $[0], but that just resulted in the script deadlocking until it timed out.

NOTE: The above script is at the beginning of my start up script

+6  A: 

You can find out who is loading a particular module, by inserting a few lines at the start of the module to get the "caller". Find Moose.pm in your library tree (perl -mMoose -wle'print $INC{"Moose.pm"}', and edit it to:

package Moose;

use Data::Dumper;
warn "!!! Moose is being loaded by: ", Dumper([caller]);

This is quick and dirty, but it sounds like it's all you need. (Don't forget to unedit the changes to Moose.pm when you are done!)

Ether
+12  A: 

Hows about:

BEGIN {
  unshift @INC, sub {
    printf "Moose first called by pkg %s at line %d in %s\n", (caller)[0,2,1]
      if $_[1] eq 'Moose.pm';
  };
}

This "works" because subroutine references in @INC are called and passed the coderef and filename as arguments. See require perldoc:

As mentioned by phaylon, you can also use Devel::TraceLoad to get a summary of all modules loaded while your application ran (and what line of what file loaded them) with

perl -MDevel::TraceLoad=summary my_progam.pl

/I3az/

draegtun
Excellent answer! I like this one particularly because you avoid patching Moose.pm in any way. Instead you take advantage of a rarely used, but very cool feature of `@INC`.
daotoad
If you put that inside an import method into a 'wholoads.pm' and check against the first argument to the method you could use it as 'perl -Mwholoads=Moose yourscript.pl'. I'd also consider using Carp::cluck() to get at stacktraces, since this would also cover lazy-loading modules at runtime.
phaylon
@phaylon: Great idea. Though I wouldn't be surprised if there was a module that already did all this on CPAN? If not it sounds like a new project!
draegtun
@draegtun: After some more searching, there's Devel-TraceLoad which seems quite suitable. It doesn't look for a specific package, but gives a summary.
phaylon
@draegtun, great answer. I ended up using Devel-TraceLoad that did the trick, but I like the idea with @INC so I might try that out when I have some more time.
jjafuller
You're very welcome. I see that `Devel::TraceLoad` does wrap `require` so definitely room for playing with a @INC solution. PS. phaylon++ for good CPAN search foo!
draegtun
We need to know loading order engineering.
aartist
+4  A: 

In *Nix:

mkdir dummy
echo > dummy/Moose.pm
perl -I./dummy /path/to/my_script.pl

The concept would be the same in Windows.

You should get:

Moose.pm did not return a true value at ...
Axeman