# from Dr.Ruud
# on Friday 19 January 2007 09:36 am:

>I am not currently using par, but I want to create a utility that
>generates a hash with a "use"-tree, starting at any module.
>Especially for detecting circles.
>The scandeps.pl seems like a nice start. If anybody knows a better way
>to generate such a tree, please reply.

Well, I've been playing with Devel::TraceDeps as a fork of chromatic's 
Devel::TraceUse which puts a hook in @INC to grab all of the require 
calls.  This is similar to Module::ScanDeps::DataFeed, which is what 
scandeps.pl is doing for the 'compile' and 'execute' steps.  The 
difference is that my approach tries to catch *all* of the require 
calls by deleting the %INC entry as soon as it is created where 
M::SD::DF only examines the final (aggregate of all dependencies) %INC, 
so it has less information about 'who wants what.'

However, I noticed that perl is somewhat tricky about how it handles 
circular dependency.  The @INC hook won't see another 'use foo' if 
foo.pm says 'use bar' and bar.pm says 'use foo'.  My guess is that it 
defers the compile until after all of the requires have returned 
filehandles.  So, at least with my current (pseudo-recursive: flag the 
current and call require($module) to send perl looking through the rest 
of @INC) implementation, I can't see the 'use foo' in bar.pm if 
starting at foo.pm

With some debugging info, you see this:

  $ perl -MDevel::TraceDeps -e 'use foo'
  want foo.pm
  want bar.pm
  want baz.pm
  done baz.pm
  done bar.pm
  done foo.pm

(bar.pm does "use baz", and baz.pm has a "require foo")

Though I might very well have a bug in the code atm.

Thus, to actually construct a correct dependency tree, you have to take 
one pass just to determine the aggregate list of dependencies, then 
take each of those as an entry point.  Unfortunately, if I can't tie 
%INC (*), I'm not sure even that will work in some circular cases.  
Maybe the compiling approach will ever be sure to hit all of the deps, 
thus some static scanning, PPI, or opcode examination may be necessary.

  http://scratchcomputing.com/svn/Devel-TraceDeps/trunk

* subrefs in @INC return a filehandle, after which perl sets an entry in 
%INC.  Because I depend on ! exists($INC{foo.pm}) to re-trigger the 
require(), I'm sort of stuck right now because if I don't set it, perl 
sets it to the subref which is the @INC hook.  I can use a DB hook, 
INIT block and other such stuff, but I have to think there's a gap in 
those approaches somewhere.

One thing that I've noticed is that no dep-finder system currently has 
any sort of caching mechanism.  We should probably checksum the file 
and store the known dependencies somewhere (that is, once we get it 
right.)

--Eric
-- 
But you can never get 3n from n, ever, and if you think you can, please
email me the stock ticker of your company so I can short it.
--Joel Spolsky
---------------------------------------------------
    http://scratchcomputing.com
---------------------------------------------------

Reply via email to