CleanCode Perl Libraries |
Home | Perl | Java | PowerShell | C# | SQL | Index | Tools | Download | What's New |
Multi-Lingual Library | Maintainability | ||||||||||||
Perl | Java | JavaScript | Certified Class |
Testable Class |
Standalone Mode |
Diagnostic Enabled |
plumb - Static Perl include file analyzer: plumb the depths of the included module hierarchy for specified Perl files.
plumb [ -esdhH ] [ -l<level> ] assignments perl files
Print a detailed report, itemizing source file, line number, and package, instead of the default hierarchical report.
Expand output to show all occurrences of a file
Limit the probe to the depth specified (default is unlimited).
Sort output by file name (first field).
Option help.
Long help (manual page).
variable_name=value - plugs in values for specified variables before running.
One or more files to plumb.
Perl5.005, Getopt::Std, Pod::Usage, File::Basename, Data::Handy
Plumb the depths of the included module hierarchy for specified Perl files, providing a simple way to determine a module dependency tree. For a simple program, this won't reveal too much, but once you have dozens or hundreds of interlinked files, this can help track down dependency issues. This program is adapted from a version for C code I created when I worked at one firm which used a few libraries. Checking the dependencies on a single file produced a list of 17,000+ dependent files (with duplication, though)!
Use this module to:
When I was new to a project (and a company) I needed to see who was calling a particular module because that module was invoking a second module when I didn't think it should be. Going to my ~/web/cgi-bin
directory, and invoking plumb codedir/*
showed me immediately where that first module was being called from, answering my question.
Run plumb
, filter out the lines which refer to system files, then you've got a list of the files being used.
Perhaps of more academic curiousity, plumb
doesn't stop at user files. It will also show you Perl system file dependencies.
Your current directory, command-line file specification, and how your use lib
directives are written may affect your output.
While the following two commands might appear to be equivalent, I get different results:
(A1) cd ~/web/cgi-bin; plumb codedir/*
(A2) cd ~/web/cgi-bin/codedir; plumb *
By "different", I mean that some include files won't be found, denoted as ???
/path/file in the output, and therefore won't be expanded further.
Why? Plumb
traverses included files by examining the use lib
directives. Consider these two lines:
(B1) use lib "../../foo::bar"
(B2) use lib "foo::bar"', etc.
While they may resolve to the same library path (depending on @INC
), they may cause some differences in plumb
output. If you use relative paths as in line (B1) above, you need to sit in the same directory as your target when you run plumb
.
So if you have a lot of ???
items showing up, make sure you're in the same directory as your target, as in line (A2) above.
If you use only static include directives, (i.e. hardcoded lines like use File::stat
) then invoking plumb
with a single file name is usually sufficient, as in:
plumb myfile.pl
But if you use dynamic module loading, there are a couple things you could do. If you use a require
statement with a variable name, as in:
require $newModule;
plumb
lets you specify a value for the variable $newModule
on the command line:
plumb newModule=lexScanner.pm myfile.pl
Then lexScanner.pm
will be substituted in each file before examining it. You may specify multiple name/value pairs, but only one value per variable name. So if you have a loop which invokes require on several modules, you can only tell plumb
about one of them. In this latter case, your next best solution is to invoke plumb
with multiple files as in, for example:
plumb myfile.pl libs/lex*.pm
So if scanning myfile.pl statically won't connect to the other library files, simply ask plumb to scan them as well.
In this first example, we want to find out what is included in the file ExecJava.pm, both its direct descendants and every nested descendant. The output shows the hierarchy by the indentation. That is, strict, vars, and Data::Diagnostic may all be found as explicitly included in this file. We further observe that vars.pm includes register.pm, which includes warnings.pm, which includes Carp.pm, and so forth. Note that the next time vars.pm is encountered (just under Data/Diagnostic.pm) it is not further plumbed -- there's no need, as we have already done it once. This keeps the list as concise as possible.
% plumb.pl ExecJava.pm
C:/Perl/lib/strict.pm
C:/Perl/lib/vars.pm
C:/Perl/lib/warnings/register.pm
C:/Perl/lib/warnings.pm
C:/Perl/lib/Carp.pm
C:/Perl/lib/Exporter.pm
C:/Perl/lib/Exporter/Heavy.pm
C:/Perl/lib/strict.pm
C:/Perl/lib/Exporter.pm
C:/Perl/lib/Carp.pm
C:/Perl/lib/strict.pm
C:/Perl/lib/Carp.pm
C:/usr/ms/devel/perl/lib/Data/Diagnostic.pm
C:/Perl/lib/strict.pm
C:/Perl/lib/vars.pm
C:/usr/ms/devel/perl/lib/Data/Handy.pm
C:/Perl/lib/strict.pm
C:/Perl/lib/vars.pm
C:/Perl/lib/File/stat.pm
C:/Perl/lib/strict.pm
C:/Perl/lib/warnings.pm
C:/Perl/lib/Exporter.pm
C:/Perl/lib/vars.pm
C:/Perl/lib/Class/Struct.pm
C:/Perl/lib/strict.pm
C:/Perl/lib/warnings/register.pm
C:/Perl/lib/Carp.pm
C:/Perl/lib/Exporter.pm
(another 150 lines follow...)
The file run.pl contains a line require $itemName.pm
so we instantiate the variable. Also, we know that run.pl uses all the .pm files under codedir/ but it uses an indirect method, so we just enumerate codedir/*.pm on the command line to cover them all. In this example, we illustrate the other format available with the -d
option. Here, rather than show the visual hierarchy, the program shows a textual hierarchy.
% plumb.pl -d itemName=codedir run.pl codedir/*.pm
run.pl (line 5, pkg main ) ==> ../../libs/Mod.pm
../../libs/Mod.pm (line 74, pkg Node ) ==> ../../libs/DEBUG.pm
../../libs/Mod.pm (line 195, pkg Mod ) ==> ../../libs/HTML_Page.pm
../../libs/HTML_Page.pm (line 2, pkg HTML_Page) ==> ../../libs/perl5/lib/HTML/Template.pm
../../libs/Mod.pm (line 196, pkg Mod ) ==> ../../libs/perl5/lib/Time/HiRes.pm
../../libs/perl5/lib/Time/HiRes.pm (line 6, pkg main ) ==> /usr/local/lib/perl5/Exporter.pm
/usr/local/lib/perl5/Exporter.pm (line 19, pkg Exporter ) ==> /usr/local/lib/perl5/Carp.pm
/usr/local/lib/perl5/Carp.pm (line 55, pkg Carp ) ==> /usr/local/lib/perl5/Exporter.pm
. . .
Normal exit.
Missing file name argument(s).
None
Michael Sorens
$Revision: 8 $ $Date: 2006-12-19 21:13:43 -0800 (Tue, 19 Dec 2006) $
CleanCode 0.9
Home | Perl | Java | PowerShell | C# | SQL | Index | Tools | Download | What's New |
CleanCode Perl Libraries | Copyright © 2001-2013 Michael Sorens - Revised 2013.06.30 |