8

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

Jeffrey Fuller
  • 300
  • 1
  • 2
  • 8

3 Answers3

16

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
Community
  • 1
  • 1
draegtun
  • 22,441
  • 5
  • 48
  • 71
  • 2
    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 Sep 28 '10 at 18:05
  • 1
    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 Sep 28 '10 at 18:09
  • 1
    @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 Sep 28 '10 at 18:43
  • 4
    @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 Sep 28 '10 at 18:54
  • 1
    @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. – Jeffrey Fuller Sep 28 '10 at 19:43
  • 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 Sep 28 '10 at 21:12
  • We need to know loading order engineering. – aartist Sep 28 '10 at 22:16
5

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
  • 53,118
  • 13
  • 86
  • 159
4

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
  • 29,660
  • 2
  • 47
  • 102