How do I find all the modules used by a Perl script? - perl

I'm getting ready to try to deploy some code to multiple machines. As far as I know, using a Makefile.pm to track dependencies is the best way to ensure they are installed everywhere. The problem I have is I'm not sure our Makefile.pm has been updated as this application has passed through a few different developers.
Is there any way to automatically parse through either my source or a few full runs of my program to determine exactly what versions of what modules my application is depending on? On top of that, is there any way to filter it based on CPAN packages? (So that I only depend on Moose instead of every single module that comes with Moose.)
A third related question is, if you depend on a version of a module that is not the latest, what is the best way to have someone else install it? Should I start including entire localized Perl installations with my application?

Just to be clear - you can not generically get a list of modules that the app depends on by code analysis alone. E.g. if your apps does eval { require $module; $module->import() }, where $module is passed via command line, then this can ONLY be detected by actually running the specific command line version with ALL the module values.
If you do wish to do this, you can figure out every module used by a combination of runs via:
Devel::Cover. Coverage reports would list 100% of modules used. But you don't get version #s.
Print %INC at every single possible exit point in the code as slu's answer said. This should probably be done in END{} block as well as __DIE__ handler to cover all possible exit points, and even then may be not fully 100% covering in generic case if somewhere within the program your __DIE__ handler gets overwritten.
Devel::Modlist (also mentioned by slu's answer) - the downside compared to Devel::Cover is that it does NOT seem to be able to aggregate a database across multiple sample runs like Devel::Cover does. On the plus side, it's purpose-built, so has a lot of very useful options (CPAN paths, versions).
Please note that the other module (Module::ScanDeps) does NOT seem to allow you to do runtime analysis based on arbitrary command line arguments (e.g. it seems at first glance to only allow you to execute the program with no arguments) and if that's true, is inferior to all the above 3 methods for any code that may possibly load modules dynamically.

Module::ScanDeps - Recursively scan Perl code for dependencies
Does both static and runtime scanning. Just modules, I don't know of any exact way of verifying what versions from what distributions. You could get old packages from BackPan, or just package your entire chain of local dependencies up with PAR.

You could look at %INC, see http://www.perlmonks.org/?node_id=681911 which also mentions Devel::Modlist

I would definitely use Devel::TraceUse, which also shows a tree of the modules, so it's easy to guess where they are being loaded.

Related

More than one V4L-DVB driver on the same host machine

I have a question related to V4L-DVB drivers. Following the
Building/Compiling the Latest V4L-DVB Source Code link, there are 3 ways to
compile. I am curious about the last approach (More "Manually
Intensive" Approach). It allows me to choose the components that I
wish to build and install using the "make menuconfig". Some of these components (i.e. "CONFIG_MEDIA_ATTACH") are used in pre-processor directives that define a function in one shape if defined, and a function in another if not defined (i.e.
dvb_attach, dvb_detach) in the resulting modules (i.e. dvb_core.ko)
that will be loaded by most of the DVB drivers. What happens if there are two
drivers (*.ko modules) on the same host machine, one that needs dvb_core.ko with
CONFIG_MEDIA_ATTACH defined and another that needs dvb_core.ko with
CONFIG_MEDIA_ATTACH undefined, is there a clean way to handle this?
What is also not clear to me is: Since the V4L compilation environment seems very customizable (by setting the .config file), if I develop a driver using V4L-DVB structures, there is a big chance that it has conflicts with other drivers since each driver has its own custom settings. Is my understanding correct?
Thanks!
Dave

Using classes in TCL using Simple Agent Pro

I am using this software called Simple Agent Pro, and it primarily uses TCL code. I was wondering anybody familiar with TCL or Sapro would be kind enough to tell me how to import the modules into the .tel file for Sapro.
When I try this:
package require tclOO.h
The program stops working.
Any help would be appreciated.
I don't know Simple Agent Pro at all, but if you're doing a “guerilla install” of TclOO then you need a few things:
Make sure you're using Tcl 8.5 (see what package require Tcl returns).
If you're using 8.4 (note: 8.4 EOLed this month), TclOO will not work at all (and it cannot be backported).
If you're using 8.6, it already provides the TclOO package and you shouldn't need to fuss around with all this.
Do a build of TclOO and install it to a location you prefer.
This will require Tcl's internal source files; TclOO explicitly pokes its nose into places where most code shouldn't.
You probably don't need to have a custom build of 8.5; just the configured sources somewhere will do. (You might need to hack the configure scripts a little bit.)
Add the location that you installed TclOO to to the search path inside your Tcl 8.5 program.
lappend auto_path /the_dir/you_put/it_in
If you're using Windows, it's probably easiest to use forward slashes for this path anyway (this is a directory name that is always highly protected before it hits the OS, so that's OK).
Now you should be able to require/use the package.
package require TclOO
oo::class create Foo {
# etc.
}
Note that the case and exactly how you write it matters. The version you get ought to be at least 1.0 (earlier versions were for development only) which corresponds exactly with the API as supported in Tcl 8.6 (modulo a few things that require 8.6 for other reasons, such as being able to yield inside a method which only works in 8.6 because that's where yield was first defined).
You probably mean
package require TclOO
Case and other stuff is important there.
Next time you should also include the stack trace. If the program stops working, it should display that either as dialog or on stdout.

Perl shallow syntax check? ie. do not check syntax of imports

How can I perform a "shallow" syntax check on perl files. The standard perl -c is useful but it checks the syntax of imports. This is sometimes nice but not great when you work in a code repository and push to a running environment and you have a function defined in the repository but not yet pushed to the running environment. It fails checking a function because the imports reference system paths (ie. use Custom::Project::Lib qw(foo bar baz)).
It can't practically be done, because imports have the ability to influence the parsing of the code that follows. For example use strict makes it so that barewords aren't parsed as strings (and changes the rules for how variable names can be used), use constant causes constant subs to be defined, and use Try::Tiny changes the parse of expressions involving try, catch, or finally (by giving them & prototypes). More generally, any module that exports anything into the caller's namespace can influence parsing because the perl parser resolves ambiguity in different ways when a name refers to an existing subroutine than when it doesn't.
There are two problems with this:
How to not fail -c if the required modules are missing?
There are two solutions:
A. Add a fake/stub module in production
B. In all your modules, use a special catch-all #INC subroutine entry (using subs in #INC is explained here). This obviously has a problem of having the module NOT fail in real production runtime if the libraries are missing - DoublePlusNotGood in my book.
Even if you could somehow skip failing on missing modules, you would STILL fail on any use of the identifiers imported from the missing module or used explicitly from that module's namespace.
The only realistic solution to this is to go back to #1a and use a fake stub module, but this time one that has a declared and (as needed) exported identifier for every public interface. E.g. do-nothing subs or dummy variables.
However, even that will fail for some advanced modules that dynamically determine what to create in their own namespace and what to export in runtime (and the caller code could dynamically determine which subs to call - heck, sometimes which modules to import).
But this approach would work just fine for normal "Java/C-like" OO or procedural code that only calls statically named predefined public subs, methods and accesses exported variables.
I would suggest that it's better to include your code repository in your syntax check. perl -I/path/to/working/code/repo/local_perl/ -c or set PERL5LIB=/path/to/working/code/repo/local_perl/ prior to running perl -c. Either option should allow you to check against your working code, assuming you have it in a directory structure similar to your live code.
I guess you could make stubs for the missing libraries in your home folder.
Have you looked into PPI? I think it does follow imports, however it could perhaps be more easily modified to guess what looks like a function name.

Dependencies in Perl code

I've been assigned to pick up a webapplication written in some old Perl Legacy code, get it working on our server to later extend it. The code was written 10 years ago by a solitary self-taught developer...
The code has weird stuff going on - they are not afraid to do lib-param.pl on line one, and later in the file do /lib-pl/lib-param.pl - which is offcourse a different file.
Including a.pl with methods b() and c() and later including d.pl with methods c() and e() seems to be quite popular too... Packages appear to be unknown, so you'll just find &c() somewhere in the code later.
Interesting questions:
Is there a tool that can draw relations between perl-files? Show a list of files used by each other file?
The same for MySQL databases and tables? Can it show which schema's/tables are used by which files?
Is there an IDE that knows which c() is called - the one in a.pl or the one in d.pl?
How would you start to try to understand the code?
I'm inclined to go through each file and refactor it, but am not allowed to do that - only the strict minimum to get the code working. (But since the code never uses strict, I don't know if I'm gonna...)
Not using strict is a mistake -- don't continue it. Move the stuff in d.pl to D.pm (or perhaps a better name alltogether), and if the code is procedural use Sub::Exporter to get those subs back into the calling package. strict is lexical, you can turn it on for just one package. Such as your new package D;. To find out which code is being called, use Devel::SimpleTrace.
perl -MDevel::SimpleTrace ./foo.pl
Now any warnings will be accompanied by a full back-log -- sprinkle warnings around the code and run it.
I think the MySQL question should be removed, from this. Schema Table mappings have nothing to do with perl, it seems an out of place distraction on this question.
I would write a utility to scan a complete list of all subs and which file they live in; then I would write a utility to give me a list of all function calls and which file they come from.
By the way - it is not terribly hard to write a fairly mindless static analysis tool to generate a call graph.
For many cases, in well-written code, that will be enough to help me out...

What can make Class::Loader fail where "use" and "new" do not?

I'm working on a very large CGI application that uses Crypt::RSA, which is properly installed. I get a "attempted to call a null reference as a function" type of error (I can't go back to get the exact error right now because we had to rollback for a release date) when I try to run any the embedded library. I trace the null reference to Crypt::RSA's constructor, which uses Class::Loader to enable Crypt::RSA::ES::OAEP.
I replaced the class loader with a "use" and a "new", and that part works fine, though the library still fails in many points. Obviously something is wrong with my environment. I'm just not certain as to what. Can anyone give me any leads?
Ok, after 12 hours of digging into it, I got this working.
Here's what was going on (but not why). Whenever I called eval() on a quoted use or require statement (as occurs in Class::Loader, but also in other locations in the Crypt:: framwork), it failed to see paths that were otherwise included as Perl classpaths. Since most quoted use/require objects simply assume the class will be there, very few useful errors were thrown out at me. I would dump #INC to file, outside an eval block, and everything would be there.
Ironically, I used the same setup in dev vs staging, and it worked in dev, but not in staging. I must also point out that FindBin (I shouldn't be using it in CGI, I know, but Crypt uses it) was flailing up and down about /dev/null in staging, but not in development.
Since I can't easily compare versions or global configs, that's where my quest ends.
How I resolved the issue for myself in Crypt::RSA was to disable all commands tied to FindBin, and hard-code require references for anything my code would ever access. I did a require in Crypt::RSA for Crypt::RSA::ES::OAEP and one in Crypt::Random::Generator for Crypt::Random::Provider::rand
Hope this helps anyone in the future who has the problem. Anyone who can suggest the why of it, please respond and I'll add it to complete the post.