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

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

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

Спасибо

Питер


person Vagnerr    schedule 27.10.2008    source источник


Ответы (8)


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

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

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

Вместо этого я решил использовать Module :: 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 их видеть.)

person cjm    schedule 27.10.2008

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

person Community    schedule 27.10.2008

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

perl -d:Modlist script.pl

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

person Vagnerr    schedule 27.10.2008

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

Мне хочется написать сценарий, который:

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

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

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

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

person KeyserSoze    schedule 27.10.2008

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

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

person Jonathan Leffler    schedule 27.10.2008

use Acme::Magic::Pony;

Шутки в сторону. Он автоматически установит модули Perl, если они будут отсутствовать. См. Acme :: Magic: : Страница Pony в CPAN.

person JDrago    schedule 28.10.2008
comment
Интересно, но если вы попытаетесь использовать это в реальной коммерческой среде, ваша операционная группа будет немного расстроена из-за вас и захочет узнать, знакомы ли вы с концепциями стабильности и безопасности :-) - person Vagnerr; 01.11.2008

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

Например, У меня есть Baz.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), а затем установите Bundle :: Baz, как обычный модуль CPAN. Затем будут установлены все модули, перечисленные в "= head1 CONTENTS".

person draegtun    schedule 27.10.2008

Вот быстрая функция 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 $2 }' | sed 's/();\?$\|;$//' | sort | uniq
    ack '^\s*use\s+base\s+.*;\s*$' $dir | awk '{ print $3 }' | sed 's/();\?$\|;$//' | sort | uniq
}
person Robert Krimen    schedule 28.10.2008