Sponsoring The Perl Toolchain Summit 2025: Help make this important event another success Learn more

#!perl
use strict;
use SPVM();
use FindBin;
SPVM::Builder::Util::getopt
# spvm,spvmcc, spvmdeps shared
'h|help' => \my $help,
'v|version' => \my $show_version,
'I|include-dir=s' => \my @include_dirs,
# spvmdeps only
'json' => \my $json_option_on,
'cpanm' => \my $cpanm_option_on,
'cpanfile' => \my $cpanfile_option_on,
'with-version' => \my $with_version_option_on,
'exclude=s' => \my @excluded_class_names,
'resource-info' => \my $show_resource_info,
;
if ($help) {
print SPVM::Builder::Util::extract_usage;
exit 0;
}
elsif ($show_version) {
my $version_string = "spvmdeps v$SPVM::VERSION";
print "$version_string\n";
exit 0;
}
my $script_name = shift;
my $source = "";
$0 = $script_name;
FindBin::again();
eval { $source = SPVM::Builder::Util::slurp_binary($script_name); };
my $include_dirs_by_lib_directive = SPVM::Builder::Util::parse_lib_directive($source, $FindBin::Bin);
unshift @INC, map { $_ =~ s/[\\\/]SPVM$//; $_; } @include_dirs, @$include_dirs_by_lib_directive;
my $dependency_analyzer = SPVM::Builder::DependencyAnalyzer->new(
script_name => $script_name,
with_version => $with_version_option_on,
excluded_class_names => \@excluded_class_names,
);
unless (defined $script_name) {
die "[spvmdeps command]spvmdeps command needs SCRIPT_NAME."
}
if ($show_resource_info) {
my $resource_info = $dependency_analyzer->dump_resource_info;
print $resource_info;
}
elsif ($cpanm_option_on) {
my $cpanm_commands = $dependency_analyzer->to_cpanm_commands;
my $cpanm_commands_lines = SPVM::Builder::DependencyAnalyzer->to_lines($cpanm_commands);
print $cpanm_commands_lines;
}
elsif ($cpanfile_option_on) {
my $cpanfile_commands = $dependency_analyzer->to_cpanfile_commands;
my $cpanfile_commands_lines = SPVM::Builder::DependencyAnalyzer->to_lines($cpanfile_commands);
print $cpanfile_commands_lines;
}
elsif ($json_option_on) {
my $json = $dependency_analyzer->to_json;
print $json;
}
else {
my $class_names = $dependency_analyzer->to_class_names;
my $class_names_lines = SPVM::Builder::DependencyAnalyzer->to_lines($class_names);
print $class_names_lines;
}
=encoding utf8
=head1 Name
spvmdeps - Class Dependencies Analyzer
=head1 Description
C<spvmdeps> command is a class dependencies analyzer.
=head1 Usage
Usage: spvmdeps [OPTIONS] SCRIPT_NAME
spvmdeps myapp.spvm
spvmdeps --with-version myapp.spvm
spvmdeps --cpanm --with-version myapp.spvm
spvmdeps --cpanfile --with-version myapp.spvm
Options:
-h, --help Shows this message
-v, --version Shows the version
-I, --include-dir DIRECTORY Adds a include directory
--json Prints JSON that contains all dependent class information.
--cpanm Prints cpanm commands that contains dependent cpan modules
--cpanfile Prints cpanfile that contains dependent cpan modules
--with-version Output(default, --cpanm, --json) contains version information.
--exclude CLASS_NAME Excludes a class name. This option can be used repeatedly.
--resource-info Shows config files of dependent resources
=head1 Details
spvmdeps [OPTIONS] SCRIPT_NAME
The C<spvmdeps> command prints class dependency information.
Output Examples:
Sys
Regex
Foo
Bar
# --with-version
Sys 1.201
Regex 0.980
Foo (version_from Sys)
Bar
I<OPTIONS> are L<options|/"Options">.
I<SCRIPT_NAME> is a script name that contains a L<bootstrap method|SPVM::Document::Language::Class/"Bootstrap Method"> in an L<anon class|SPVM::Document::Language::Class/"Anon Class">.
class {
static method main : void () {
}
}
See L<Class Search Directories|SPVM::Document::Language::Class/"Class Search Directories"> about default class search directories.
See L<SPVM::Document::EnvironmentVariables> about available environment variables.
=head1 Options
=head2 --help
Outputs how to use the C<spvmdeps> command to standard output.
=head2 -h
-h
Same as L</"--help">.
=head2 --version
Outputs the version of the C<spvmdeps> command to standard output. This version is the same as the version of L<SPVM>.
=head2 -v
-v
Same as L</"--version">.
=head2 --include-dir
--include-dir DIRECTORY
Prepends I<DIRECTORY> to L<class search directories|SPVM::Document::Language::Class/"Class Search Directories">
This option can be specified multiple times.
--include-dir dir1 --include-dir dir2
In this case, class search directories becomes the following.
[dir1, dir2, default_dirs]
=head2 -I
-I DIRECTORY
Same as L</"--include-dir">.
=head2 --json
--json
Prints JSON that contains all dependent class information.
Output Examples:
[
{"class_name":"Address"},
{"class_name":"Bool"},
{"class_name":"Byte"},
{"class_name":"CommandInfo"},
{"class_name":"Double"},
{"class_name":"Error"},
{"class_name":"Error::Compile"},
{"class_name":"Error::NotSupported"},
{"class_name":"Error::System"},
{"class_name":"Float"},
{"class_name":"Int"},
{"class_name":"Long"},
{"class_name":"SPVM"},
{"class_name":"Short"},
{"class_name":"TestCase::NativeAPI2"},
{"class_name":"TestCase::Precompile"}
]
# --with-version
[
{"class_name":"Address","version_from":"SPVM"},
{"class_name":"Bool","version_from":"SPVM"},
{"class_name":"Byte","version_from":"SPVM"},
{"class_name":"CommandInfo","version_from":"SPVM"},
{"class_name":"Double","version_from":"SPVM"},
{"class_name":"Error","version_from":"SPVM"},
{"class_name":"Error::Compile","version_from":"SPVM"},
{"class_name":"Error::NotSupported","version_from":"SPVM"},
{"class_name":"Error::System","version_from":"SPVM"},
{"class_name":"Float","version_from":"SPVM"},
{"class_name":"Int","version_from":"SPVM"},
{"class_name":"Long","version_from":"SPVM"},
{"class_name":"SPVM","version":"0.990036"},
{"class_name":"Short","version_from":"SPVM"},
{"class_name":"TestCase::NativeAPI2","version":"1.002"},
{"class_name":"TestCase::Precompile","version":"2.005"}
]
=head2 --cpanm
--cpanm
Prints cpanm commands that contains dependent CPAN modules. Classes its version is specified are treated as dependent CPAN modules.
Output Examples:
cpanm SPVM
cpanm SPVM::Sys
cpanm SPVM::Regex
# --with-version
cpanm SPVM@1.001
cpanm SPVM::Sys@1.201
cpanm SPVM::Regex@0.980
=head2 --cpanfile
--cpanfile
Prints cpanfile that contains dependent CPAN modules. Classes its version is specified are treated as dependent CPAN modules.
Output Examples:
requires 'SPVM';
requires 'SPVM::Sys';
requires 'SPVM::Regex';
# --with-version
requires 'SPVM', '== 1.001';
requires 'SPVM::Sys', '== 1.201';
requires 'SPVM::Regex', '== 0.980';
=head2 --with-version
--with-version
Output(default, L</"--cpanm">, L</"--cpanfile">, L</"--json">) contains version information.
=head2 --exclude
--exclude=<class_name>
Excludes a class name. This option can be used repeatedly.
Examples:
--exclude TestCase::Foo
Wildcard C<*> can be used.
--exclude TestCase::*
=head2 --resource-info
--resource-info
Shows all config files loading resources.
=head1 lib Directive
If the source code specified by I<SCRIPT_NAME> contains lib directives, The directories specified by lib directive is prepeneded to L<class search directories|SPVM::Document::Language::Class/"Class Search Directories">.
#lib "$FindBin::Bin/lib"
class {
}
This directories specified by lib directive is placed after the directories specified by L</"--include-dir"> option.
=head1 Copyright & License
Copyright 2023 Yuki Kimoto. All Rights Reserved.
MIT License.