Как определить зависимости CPAN перед развертыванием проекта Perl?

есть ли у кого-нибудь предложения по хорошему подходу к поиску всех зависимостей CPAN, которые могли возникнуть в проекте разработки на заказ. Как правило, ваша локальная среда разработки редко совпадает с вашей живой, и по мере создания все больше и больше проектов вы склонны создавать локальную библиотеку установленных модулей. Это приведет к тому, что вы не обязательно заметите, что ваш последний проект имеет требование к неосновному модулю. Как там вообще требования упакуйте весь проект для развертывания в другую группу (в нашем случае нашу оперативную группу), важно знать, какие модули должны быть включены в пакет.

есть ли у кого-нибудь какие-либо идеи по этой проблеме.

спасибо

Петр

8 ответов


у меня самой была эта проблема. Devel:: Modlist (как было предложено ответ) принимает динамический подход. Он сообщает о модулях, которые были фактически загружены во время определенного запуска вашего скрипта. Это ловит модули, которые загружаются любыми средствами, но не может поймать условные требования. То есть, если у вас есть такой код:

if ($some_condition) { require Some::Module }

и $some_condition оказывается ложной, Devel::Modlist не будет как требование.

я решил использовать Модуль:: ExtractUse вместо. Он делает статический анализ, а это значит, что он всегда будет ловить Some::Module в приведенном выше примере. С другой стороны, он ничего не может сделать с кодом, например:

my $module = "Other::Module";
eval "use $module;";

конечно, можно использовать оба подхода, а затем объединить два списка.

в любом случае, вот решение я придумал:

#! /usr/bin/perl
#---------------------------------------------------------------------
# Copyright 2008 Christopher J. Madsen <perl at cjmweb.net>
#
# This program is free software; you can redistribute it and/or modify
# it under the same terms as Perl itself.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See either the
# GNU General Public License or the Artistic License for more details.
#
# Recursively collect dependencies of Perl scripts
#---------------------------------------------------------------------

use strict;
use warnings;
use File::Spec ();
use Module::CoreList ();
use Module::ExtractUse ();

my %need;
my $core = $Module::CoreList::version{'5.008'};

# These modules have lots of dependencies.  I don't need to see them now.
my %noRecurse = map { $_ => 1 } qw(
  Log::Log4perl
  XML::Twig
);

foreach my $file (@ARGV) {
  findDeps($file);
}

foreach my $module (sort keys %need) {
  print "  $module\n";
}

#---------------------------------------------------------------------
sub findDeps
{
  my ($file) = @_;

  my $p = Module::ExtractUse->new;

  $p->extract_use($file);

  foreach my $module ($p->array) {
    next if exists $core->{$module};
    next if $module =~ /^5[._\d]+/; # Ignore "use MIN-PERL-VERSION"
    next if $module =~ /$/;        # Run-time specified module

    if (++$need{$module} == 1 and not $noRecurse{$module}) {
      my $path = findModule($module);
      if ($path) { findDeps($path) }
      else       { warn "WARNING: Can't find $module\n" }
    } # end if first use of $module
  } # end foreach $module used
} # end findDeps

#---------------------------------------------------------------------
sub findModule
{
  my ($module) = @_;

  $module =~ s!::|\'!/!g;
  $module .= '.pm';

  foreach my $dir (@INC) {
    my $path = File::Spec->catfile($dir, $module);
    return $path if -f $path;
  }

  return;
} # end findModule

вы бы запустили это так:

perl finddeps.pl scriptToCheck.pl otherScriptToCheck.pl

он печатает список всех неосновных модулей, необходимых для выполнения перечисленных сценариев. (Если они не делают причудливые трюки с загрузкой модуля, которые мешают Module:: ExtractUse видеть их.)


вы можете использовать онлайн-сервис по адресуdeps.cpantesters.org это предоставит вам много полезных данных зависимостей. Все модули на CPAN уже имеют ссылку на сайт зависимостей (в правой части страницы модуля).


в прошлом я использовал Devel:: Modlist что достаточно хорошо позволяет вам идти

perl -d:Modlist script.pl

чтобы получить список необходимых модулей.


У меня есть система сборки на основе Make для всех моих приложений C/C++ (как на ПК, так и для различных встроенных проектов), и хотя мне нравится иметь возможность выполнять сборку верхнего уровня на новой машине и проверять все зависимости (я проверяю свои цепочки инструментов на контроль версий :D), Я был разочарован тем, что не делаю то же самое для интерпретируемых языков, которые в настоящее время не имеют файла makefile в моей системе сборки.

меня подмывает написать сценарий, который:

  • поиски мои управление ревизией репозитория для файлов с .pl or .расширение pm
  • работает perl -d:Modlist на них (спасибо Vagnerr!)
  • объединение его со списком необходимых модулей
  • и, наконец, сравнивая его со списком установленных модулей.

затем я бы выполнил этот скрипт как часть моей сборки верхнего уровня, чтобы любой, кто что-либо строит, знал, есть ли у них все необходимое для запуска каждого скрипта perl, который они получили от управления ревизиями. Если есть некоторые Perl-скрипты они никогда не запускают и не хотят устанавливать CPAN, что требуется для его запуска, им придется удалить нежелательный скрипт со своего жесткого диска, поэтому проверка зависимостей не может их найти. Я знаю, как изменить клиент perforce, чтобы исключить определенные подкаталоги, когда вы делаете "синхронизацию", мне придется выяснить это для subversion...

Я бы предложил сделать проверку зависимостей одним скриптом, который ищет файлы pl, в отличие от отдельного файла makefile для проверки зависимости для каждого сценария или на основе жестко закодированного списка имен сценариев. Если вы выберете метод, который требует, чтобы пользовательское действие проверяло сценарий на наличие зависимостей, люди забудут выполнить это действие, так как они смогут запустить сценарий, даже если они не выполняют проверку зависимостей.

Как я уже сказал, я еще не реализовал вышеизложенное, но этот вопрос побудил меня попытаться сделать это. Я вернусь со своим опытом после того, как закончу.


"очевидный" способ-болезненный, но умеренно эффективный - установить совершенно новую сборку базового Perl в каком-то месте (вы не собираетесь использовать это в производстве), а затем попытаться установить свой модуль, используя эту "девственную" версию Perl. Вы найдете все отсутствующие зависимости. В первый раз это может быть больно. После первого раза у вас уже будет большинство зависимостей, и это будет значительно менее болезненно.

рассмотреть запуск собственного локального репозитория модулей CPAN-так что вам не всегда придется загружать код. Также рассмотрите, как вы очищаете устаревшие модули.


use Acme::Magic::Pony;

серьезно. Он автоматически установит модули Perl, если они окажутся отсутствующими. Вижу Acme::Magic:: Pony страница в CPAN.


Это ответ "лошадь, которая болтами", но у меня есть привычка создавать файл пакета со всеми моими зависимостями. Таким образом, когда я иду в новую среду, я просто копирую ее и устанавливаю.

например. У меня есть баз.pm

package Bundle::Baz;
$VERSION = '0.1';
1;
__END__
=head1 NAME
Bundle::Baz
=head1 SYNOPSIS
perl -MCPAN -e 'install Bundle::Baz'
=head1 CONTENTS
# Baz's modules
XML::Twig
XML::Writer
Perl6::Say
Moose

поставить это в ~/.cpan / Bundle/ (или где угодно .cpan lives), а затем установите "Bundle::Baz" как обычный модуль CPAN. Затем устанавливаются все модули, перечисленные в разделе "=HEAD1 CONTENTS".


вот функция quickie bash (используя отличный ack):

# find-perl-module-use <directory> (lib/ by default)
function find-perl-module-use() {
    dir=${1:-lib}
    ack '^\s*use\s+.*;\s*$' $dir | awk '{ print  }' | sed 's/();\?$\|;$//' | sort | uniq
    ack '^\s*use\s+base\s+.*;\s*$' $dir | awk '{ print  }' | sed 's/();\?$\|;$//' | sort | uniq
}