.\" -*- mode: troff; coding: utf-8 -*- .\" Automatically generated by Pod::Man v6.0.2 (Pod::Simple 3.45) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" \*(C` and \*(C' are quotes in nroff, nothing in troff, for use with C<>. .ie n \{\ . ds C` "" . ds C' "" 'br\} .el\{\ . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Required to disable full justification in groff 1.23.0. .if n .ds AD l .\" ======================================================================== .\" .IX Title "Module::ScanDeps 3" .TH Module::ScanDeps 3 2025-12-14 "perl v5.42.0" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH NAME Module::ScanDeps \- Recursively scan Perl code for dependencies .SH SYNOPSIS .IX Header "SYNOPSIS" Via the command\-line program scandeps.pl: .PP .Vb 4 \& % scandeps.pl *.pm # Print PREREQ_PM section for *.pm \& % scandeps.pl \-e "use utf8" # Read script from command line \& % scandeps.pl \-B *.pm # Include core modules \& % scandeps.pl \-V *.pm # Show autoload/shared/data files .Ve .PP Used in a program; .PP .Vb 1 \& use Module::ScanDeps; \& \& # standard usage \& my $hash_ref = scan_deps( \& files => [ \*(Aqa.pl\*(Aq, \*(Aqb.pl\*(Aq ], \& recurse => 1, \& ); \& \& # shorthand; assume recurse == 1 \& my $hash_ref = scan_deps( \*(Aqa.pl\*(Aq, \*(Aqb.pl\*(Aq ); \& \& # App::Packer::Frontend compatible interface \& # see App::Packer::Frontend for the structure returned by get_files \& my $scan = Module::ScanDeps\->new; \& $scan\->set_file( \*(Aqa.pl\*(Aq ); \& $scan\->set_options( add_modules => [ \*(AqTest::More\*(Aq ] ); \& $scan\->calculate_info; \& my $files = $scan\->get_files; .Ve .SH DESCRIPTION .IX Header "DESCRIPTION" This module scans potential modules used by perl programs, and returns a hash reference; its keys are the module names as appears in \f(CW%INC\fR (e.g. \f(CW\*(C`Test/More.pm\*(C'\fR); the values are hash references with this structure: .PP .Vb 7 \& { \& file => \*(Aq/usr/local/lib/perl5/5.8.0/Test/More.pm\*(Aq, \& key => \*(AqTest/More.pm\*(Aq, \& type => \*(Aqmodule\*(Aq, # or \*(Aqautoload\*(Aq, \*(Aqdata\*(Aq, \*(Aqshared\*(Aq \& used_by => [ \*(AqTest/Simple.pm\*(Aq, ... ], \& uses => [ \*(AqTest/Other.pm\*(Aq, ... ], \& } .Ve .PP One function, \f(CW\*(C`scan_deps\*(C'\fR, is exported by default. Other functions such as (\f(CW\*(C`scan_line\*(C'\fR, \f(CW\*(C`scan_chunk\*(C'\fR, \f(CW\*(C`add_deps\*(C'\fR, \f(CW\*(C`path_to_inc_name\*(C'\fR) are exported upon request. .PP Users of \fBApp::Packer\fR may also use this module as the dependency\-checking frontend, by tweaking their \fIp2e.pl\fR like below: .PP .Vb 4 \& use Module::ScanDeps; \& ... \& my $packer = App::Packer\->new( frontend => \*(AqModule::ScanDeps\*(Aq ); \& ... .Ve .PP Please see App::Packer::Frontend for detailed explanation on the structure returned by \f(CW\*(C`get_files\*(C'\fR. .SS \fBscan_deps\fP .IX Subsection "scan_deps" .Vb 6 \& $rv_ref = scan_deps( \& files => \e@files, recurse => $recurse, \& rv => \e%rv, skip => \e%skip, \& compile => $compile, execute => $execute, \& ); \& $rv_ref = scan_deps(@files); # shorthand, with recurse => 1 .Ve .PP This function scans each file in \f(CW@files\fR, registering their dependencies into \f(CW%rv\fR, and returns a reference to the updated \&\f(CW%rv\fR. The meaning of keys and values are explained above. .PP If \f(CW$recurse\fR is true, \f(CW\*(C`scan_deps\*(C'\fR will call itself recursively, to perform a breadth\-first search on text files (as defined by the \&\-T operator) found in \f(CW%rv\fR. .PP If the \f(CW\*(C`\e%skip\*(C'\fR is specified, files that exists as its keys are skipped. This is used internally to avoid infinite recursion. .PP If \f(CW$compile\fR or \f(CW$execute\fR is true, runs \f(CW\*(C`files\*(C'\fR in either compile\-only or normal mode, then inspects their \f(CW%INC\fR after termination to determine additional runtime dependencies. .PP If \f(CW$execute\fR is an array reference, passes \f(CW@$execute\fR as arguments to each file in \f(CW@files\fR when it is run. .PP If performance of the scanning process is a concern, \f(CW\*(C`cache_file\*(C'\fR can be set to a filename. The scanning results will be cached and written to the file. This will speed up the scanning process on subsequent runs. .PP Additionally, an option \f(CW\*(C`warn_missing\*(C'\fR is recognized. If set to true, \&\f(CW\*(C`scan_deps\*(C'\fR issues a warning to STDERR for every module file that the scanned code depends but that wasn\*(Aqt found. Please note that this may also report numerous false positives. That is why by default, the heuristic silently drops all dependencies it cannot find. .SS \fBscan_deps_runtime\fP .IX Subsection "scan_deps_runtime" Like \fBscan_deps\fR, but skips the static scanning part. .SS \fBscan_line\fP .IX Subsection "scan_line" .Vb 1 \& @modules = scan_line($line); .Ve .PP Splits a line into chunks (currently with the semicolon characters), and return the union of \f(CW\*(C`scan_chunk\*(C'\fR calls of them. .PP If the line is \f(CW\*(C`_\|_END_\|_\*(C'\fR or \f(CW\*(C`_\|_DATA_\|_\*(C'\fR, a single \f(CW\*(C`_\|_END_\|_\*(C'\fR element is returned to signify the end of the program. .PP Similarly, it returns a single \f(CW\*(C`_\|_POD_\|_\*(C'\fR if the line matches \f(CW\*(C`/^=\ew/\*(C'\fR; the caller is responsible for skipping appropriate number of lines until \f(CW\*(C`=cut\*(C'\fR, before calling \f(CW\*(C`scan_line\*(C'\fR again. .SS \fBscan_chunk\fP .IX Subsection "scan_chunk" .Vb 2 \& $module = scan_chunk($chunk); \& @modules = scan_chunk($chunk); .Ve .PP Apply various heuristics to \f(CW$chunk\fR to find and return the module name(s) it contains. In scalar context, returns only the first module or \f(CW\*(C`undef\*(C'\fR. .SS \fBadd_deps\fP .IX Subsection "add_deps" .Vb 2 \& $rv_ref = add_deps( rv => \e%rv, modules => \e@modules ); \& $rv_ref = add_deps( @modules ); # shorthand, without rv .Ve .PP Resolves a list of module names to its actual on\-disk location, by finding in \f(CW@INC\fR and \f(CW@Module::ScanDeps::IncludeLibs\fR; modules that cannot be found are skipped. .PP This function populates the \f(CW%rv\fR hash with module/filename pairs, and returns a reference to it. .SS \fBpath_to_inc_name\fP .IX Subsection "path_to_inc_name" .Vb 1 \& $perl_name = path_to_inc_name($path, $warn) .Ve .PP Assumes \f(CW$path\fR refers to a perl file and does it\*(Aqs best to return the name as it would appear in \f(CW%INC\fR. Returns undef if no match was found and a prints a warning to STDERR if \f(CW$warn\fR is true. .PP E.g. if \f(CW$path\fR = perl/site/lib/Module/ScanDeps.pm then \f(CW$perl_name\fR will be Module/ScanDeps.pm. .SH NOTES .IX Header "NOTES" .ie n .SS \fB\fP\fB@Module::ScanDeps::IncludeLibs\fP\fB\fP .el .SS \fB\fP\f(CB@Module::ScanDeps::IncludeLibs\fP\fB\fP .IX Subsection "@Module::ScanDeps::IncludeLibs" You can set this global variable to specify additional directories in which to search modules without modifying \f(CW@INC\fR itself. .ie n .SS \fB\fP\fB$Module::ScanDeps::ScanFileRE\fP\fB\fP .el .SS \fB\fP\f(CB$Module::ScanDeps::ScanFileRE\fP\fB\fP .IX Subsection "$Module::ScanDeps::ScanFileRE" You can set this global variable to specify a regular expression to identify what files to scan. By default it includes all files of the following types: .pm, .pl, .t and .al. Additionally, all files without a suffix are considered. .PP For instance, if you want to scan all files then use the following: .PP \&\f(CW\*(C`$Module::ScanDeps::ScanFileRE = qr/./\*(C'\fR .SH CAVEATS .IX Header "CAVEATS" This module intentionally ignores the \fBBSDPAN\fR hack on FreeBSD \-\- the additional directory is removed from \f(CW@INC\fR altogether. .PP The static\-scanning heuristic is not likely to be 100% accurate, especially on modules that dynamically load other modules. .PP Chunks that span multiple lines are not handled correctly. For example, this one works: .PP .Vb 1 \& use base \*(AqFoo::Bar\*(Aq; .Ve .PP But this one does not: .PP .Vb 2 \& use base \& \*(AqFoo::Bar\*(Aq; .Ve .SH "SEE ALSO" .IX Header "SEE ALSO" scandeps.pl is a bundled utility that writes \f(CW\*(C`PREREQ_PM\*(C'\fR section for a number of files. .PP An application of \fBModule::ScanDeps\fR is to generate executables from scripts that contains prerequisite modules; this module supports two such projects, PAR and App::Packer. Please see their respective documentations on CPAN for further information. .PP Other modules which accomplish the same goal with different approach: Module::ExtractUse, Perl::PrereqScanner, Perl::PrereqScanner::Lite, Perl::PrereqScanner::NotQuiteLite. .SH AUTHORS .IX Header "AUTHORS" Audrey Tang .PP To a lesser degree: Steffen Mueller .PP Parts of heuristics were deduced from: .IP \(bu 4 \&\fBPerlApp\fR by ActiveState Tools Corp .IP \(bu 4 \&\fBPerl2Exe\fR by IndigoStar, Inc .PP The \fBscan_deps_runtime\fR function is contributed by Edward S. Peschko. .PP You can write to the mailing list at , or send an empty mail to to participate in the discussion. Archives of the mailing list are available at or . .PP Please submit bug reports to . .SH COPYRIGHT .IX Header "COPYRIGHT" Copyright 2002\-2008 by Audrey Tang ; 2005\-2010 by Steffen Mueller . .PP This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. .PP See