#!perl use strict; use warnings; use SPVM(); use SPVM::Builder::DependencyAnalyzer; use SPVM::Builder::Util; 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.