#!perl use strict; use warnings; use utf8; use 5.008001; use Getopt::Long (); use File::Basename (); use Module::CPANfile (); use App::scan_prereqs_cpanfile qw( debugf find_perl_files scan_inner_packages scan scan_test_requires load_diff_src ); my $version; my $diff; my $include_empty; my $scan_test_requires; my $dir = "."; my $ignorefile; my $ignore_regexp; my @ignore = qw(eg examples share fatlib _build .git blib local .build); my $add_ignore; my $p = Getopt::Long::Parser->new( config => [qw(posix_default no_ignore_case auto_help)] ); $p->getoptions( 'version!' => \$version, 'diff=s' => \$diff, 'ignore=s' => \$add_ignore, 'ignore-file=s' => \$ignorefile, 'include-empty!' => \$include_empty, 'scan-test-requires' => \$scan_test_requires, 'dir=s' => \$dir, ); push @ignore, split /,/,$add_ignore if $add_ignore; if ($ignorefile) { ! -r $ignorefile && die "Unable to read ignore-file '$ignorefile' !" ; open my $fh, '<', $ignorefile; chomp(my @lines = <$fh>); $ignore_regexp = join '|', @lines; close $fh; } if ($version) { printf "%s %s\n", File::Basename::basename($0), $App::scan_prereqs_cpanfile::VERSION; exit 0; } { my ($runtime_files, $test_files, $configure_files, $develop_files) = find_perl_files($dir, ignore => \@ignore, ignore_regexp => $ignore_regexp); debugf($develop_files); my @inner_packages = scan_inner_packages(@$test_files, @$runtime_files, @$configure_files, @$develop_files); my $meta_prereqs = $diff ? load_diff_src($diff) : +{}; # runtime my $runtime_prereqs = scan($runtime_files, \@inner_packages, $meta_prereqs, [qw(runtime)], 'runtime', +{}); # test my $test_prereqs = scan($test_files, \@inner_packages, $meta_prereqs, [qw(test runtime)], 'test', $runtime_prereqs); # configure my $configure_prereqs = scan($configure_files, \@inner_packages, $meta_prereqs, [qw(configure runtime)], 'configure', $runtime_prereqs); # develop my $develop_prereqs = scan($develop_files, \@inner_packages, $meta_prereqs, [qw(develop test runtime)], 'develop', +{ %{$runtime_prereqs||{}}, %{$test_prereqs||{}}}); if ($scan_test_requires) { $develop_prereqs = scan_test_requires($dir, $develop_prereqs); } print Module::CPANfile->from_prereqs( { runtime => { requires => $runtime_prereqs, }, configure => { requires => $configure_prereqs, }, test => { requires => $test_prereqs, }, develop => { requires => $develop_prereqs, }, } )->to_string($include_empty); } __END__ =head1 NAME scan-prereqs-cpanfile - Scan prerequisite modules and generate CPANfile =head1 SYNOPSIS % scan-prereqs-cpanfile --diff=META.json # Generate diff from META.json --diff=cpanfile # Generate diff from cpanfile --ignore=extlib --dir=/foo/bar --scan-test-requires =head1 DESCRIPTION This script scans prerequisite modules from your code, and generate CPANfile. You can also list missing prerequisite modules. =head1 SCANNING RULES =over 4 =item Used modules in `Build.PL` or `Makefile.PL` as 'test' requires =item Used modules in `t/` as 'test' requires =item Used modules in `xt/`, `benchmark/` and `author/` as 'develop' requires =item Used modules in other directories as 'runtime' requires =back =head1 OPTIONS =over 4 =item --diff --diff=META.json # Generate diff from META.json --diff=cpanfile # Generate diff from cpanfile Compare the scanning result with META.json, META.yml or cpanfile. With this option, scan-prereqs-cpanfile displays missing prerequisite modules only. =item --ignore --ignore=tools,extlib Ignore some directories. =item --ignore-file --ignore-file=ignored.regex Ignore all files and directories matching a regex pattern listed in this file. =item --include-empty By default, phases without any prereqs are not dumped, By giving this option, cpanfile will have an empty block such as: on test => sub { }; Defaults to false. =item --scan-test-requires Scan test files and include the modules specified by L<Test::Requires> as 'develop' requires. =item --dir --dir=DIRECTORY Scan for modules in DIRECTORY (instead of '.') =back =head1 AUTHOR Tokuhiro Matsuno =head1 SEE ALSO L<Module::CPANfile>, L<Perl::PrereqScanner::Lite>