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

StackOverflow https://stackoverflow.com/questions/240704

Вопрос

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

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

Спасибо

Питер

Это было полезно?

Решение

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

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

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

Я решил использовать Модуль:: Извлекать вместо этого.Он выполняет статический анализ, что означает, что он всегда будет улавливать 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 уже имеют ссылку на сайт зависимостей (в правой части страницы модуля).

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

perl -d:Modlist script.pl

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

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

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

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

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

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

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

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

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

use Acme::Magic::Pony;

Серьезно.Он автоматически установит модули Perl, если они окажутся отсутствующими.Смотрите на Акме::Магия::Пони страница в CPAN.

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

Например.У меня есть 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".

Вот функция быстрого запуска (с использованием превосходного акк):

# 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
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top