Выпуск 20. Октябрь 2014

Событийно-ориентированное программирование. Введение | Содержание | Работа с API GitHub в Perl

Локальная установка и использование Perl-модулей

Рассмотрены способы установки Perl-модулей в локальную директории с помощью cpanm, использование local::lib для работы с ними, и carton для автоматизации процесса.

Часто требуется изолировать установленные модули для каждого проекта отдельно. Это может быть связано с разными версиями, необходимостью локализации или, например, с нежеланием устанавливать модули в систему, если вы просто тестируете какое-то новое Perl-приложение. Для примера возьмем простейшую серверную программу на Plack, которая при наличии параметра name приветствует посетителя:

#!/usr/bin/env perl

use strict;
use warnings;

use Plack::Request;

sub {
    my $env = shift;

    my $req = Plack::Request->new($env);
    my $name = $req->param('name') || 'anonymous';

    return [200, [], [qq{Hello, $name!}]];
}

Наш проект на текущий момент имеет следующую структуру:

app.psgi

cpanm

Далее с помощью cpanfile (подробнее о формате cpanfile читайте в статьей Что такое cpanfile?) укажем зависимости:

requires 'Plack';

Теперь наш проект выглядит так:

app.psgi
cpanfile

Установим зависимости в локальную директорию. Пусть, например, это будет third-party. Для того, чтобы все модули устанавливались несмотря на их присутствие в локальной системе, воспользуемся ключом -L у cpanm:

$ cpanm -L third-party --installdeps .

Установка займет некоторое время и на выходе мы получим следующую структуру:

app.psgi
cpanfile
third-party/
    bin/
        ...
        plackup
    lib/
        perl5/
            x86_64-linux-gnu-thread-multi
            ...
    man/
        ...

Как видно, модули установились в third-party/lib/perl5, исполняемые файлы в third-party/bin и man-страницы в third-party/man. В директории perl5 присутствует также x86_64-linux-gnu-thread-multi, куда обычно устанавливаются модули, требующие компиляции. К сожалению, до сих пор Plack требует компилятор для установки, однако ведутся работы по разделению дистрибутива на несколько пакетов, где необходимые модули для запуска приложения не будут требовать компиляции.

Работа cpanm на этом закончена. Мы установили необходимые модули в локальную директорию. Теперь необходимо запустить наше приложение.

local::lib

Если мы попробуем запустить следующим образом:

$ perl third-party/bin/plackup app.psgi

То получим вполне ожидаемую ошибку:

Can't locate Plack/Runner.pm in @INC

Мы, конечно, можем указать perl с помощью ключа -I где искать модули, однако это довольно утомительно. Более того, часто можно забыть подключить директорию с компилированными модулями, и это не так просто автоматизировать, потому как название директории меняется в зависимости от операционной системы. Именно для подключения локальных модулей нам поможет local::lib.

$ perl -Mlocal::lib=third-party third-party/bin/plackup app.psgi
HTTP::Server::PSGI: Accepting connections at http://0:5000/

Ключ -M интерпретатора подключает модули до запуска скрипта. А с помощью = можно передать модулю параметры. local::lib получает их в методе import и подключает необходимую директорию.

Использование cpanm и local::lib таким образом позволяет быстро установить модули рядом с проектом и запустить его. Однако, для больших приложений, которые часто приходится устанавливать и запускать на разных системах, это не слишком удобно.

Carton

Carton объединяет в себе возможности cpanm и local::lib (на самом деле, внутри он использует эти два модуля), а также избавляет от необходимости ручного указания путей, позволяет контролировать зависимости и упрощает процесс поставки приложения.

Для работы carton достаточно cpanfile, который у нас уже есть. Вернемся к структуре проекта до установки зависимостей и инициализируем carton:

$ carton install
Installing modules using cpanfile
Successfully installed ...
23 distributions installed
Complete! Modules were installed into local

Модули установились в директорию local, но это не так важно, потому как carton сам позаботится о добавлении нужных путей для запуска perl. Кроме того, carton создал файл cpanfile.snapshot, где указаны установленные зависимости с их версиями. Это файл стоит добавить в систему контроля версий. При запуске carton install --deployment и при наличии cpanfile.snapshot будут установлены указанные там версии. Таким образом, на машине другого разработчика или сервере будет такое же окружение.

Запускаем приложение:

$ carton exec -- plackup app.psgi
HTTP::Server::PSGI: Accepting connections at http://0:5000/

carton exec запускает приложение в виртуальном окружении, где все модули подгружаются из директории local. Так, например, можно проверять все ли модули указаны как зависимости.

carton также позволяет собирать дистрибутив с зависимостями:

$ carton bundle
Bundling modules using cpanfile
Copying K/KA/KAZEBURO/Apache-LogFormat-Compiler-0.32.tar.gz
Copying ...
/tmp/h3lGuLzMVc/carton.pre.pl syntax OK
Bundling vendor/bin/carton
Complete! Modules were bundled into vendor/cache

Теперь в директории vendor/cache находятся тарболы модулей. Просто скопировав их на другую машину и запустив там:

$ carton install --cached

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

Другие решения

Другим подходом для контроля зависимостей является создание своего приватного CPAN. Это позволяют сделать модули CPAN::Mini и подобные ему. Отдельно стоит приложение Pinto (читайте подробнее в статье Pinto — собственный CPAN из коробки), которое автоматизирует процесс установки, контроля и фиксирования модулей.

Вячеслав Тихановский


Событийно-ориентированное программирование. Введение | Содержание | Работа с API GitHub в Perl
Нас уже 1393. Больше подписчиков — лучше выпуски!

Комментарии к статье