Как определить зависимости CPAN перед развертыванием проекта Perl? - PullRequest
12 голосов
/ 27 октября 2008

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

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

Спасибо

Peter

Ответы [ 8 ]

13 голосов
/ 27 октября 2008

У меня была эта проблема сама. 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 видеть их.)

11 голосов
/ 27 октября 2008

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

10 голосов
/ 27 октября 2008

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

perl -d:Modlist script.pl

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

5 голосов
/ 27 октября 2008

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

Я испытываю желание написать скрипт, который:

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

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

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

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

3 голосов
/ 29 октября 2008
use Acme::Magic::Pony;

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

3 голосов
/ 27 октября 2008

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

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

2 голосов
/ 27 октября 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 СОДЕРЖАНИЕ».

1 голос
/ 29 октября 2008

Вот функция быстрого запуска (используя превосходные 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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...