Perl — создание дистрибутива

Как приятно, когда кому то надо то, о чём ты пишешь. Вот решил исправить ситуацию и продолжить цикл своих статеек по perl. На этот раз про создание дистрибутива perl проекта.

Итак, с чего же начать создание Perl дистрибутива своего проекта?

Для начала, давайте рассмотрим общие принципы построение дистрибутива на Perl.

Самые основные файлы и директории следующие:

  • Makefile.PL
    Основной файл. Это Perl программа. Её задача — сформировать файл Makefile — тот самый makefile инструкции, которые будет использовать уже программа make
  • MANIFEST
    Файл — листинг всех файлов, которые должны входить в пакет дистрибутива.  В нем должны быть только те файлы, без которых нельзя собрать проект. В него не входят промежуточные файлы, которые создаются во время компиляции, тестов и т.п..
    Его не надо создавать руками. Главное, что вам надо сделать — грамотно описать файл MANIFEST.SKIP
  • MANIFEST.SKIP
    Файл исключений. Вам его надо будет создать и добавить маски шаблоны в стиле регулярных выражений. Не поленитесь его создать — это облегчит вам жизнь 🙂
  • lib/
    Директория, относительно которой вам надо поместить все *.pm файлы.
  • bin/
    Директория, где будут размещаться запускаемые файлы *.pl
  • script/
    Почти аналог директории bin/, но есть небольшие отличия

Итак, делаем такие шаги для создания дистрибута:

  1. Создаем директорию lib/ и помещаем в её корень свои модули *.pm. Например, для модуля, которому мы дали название Web::Site::Constants, например, должен быть файл в lib/Web/Site/Constants.pm
  2. Исполняемые скрипты или программы типа *.pl надо поместить либо в bin/, либо в script/ директорию. Также создаём их и помещаем туда файлы. Ничего страшного, если на этом этапе мы что-то забудем или не добавим. Всё можно это отложить на потом.
  3. Пишем Makefile.PL и в нем пишем код, который создаст файл Makefile. Для облегчения, perl имеет несколько вариантов модулей (базовый ExtUtils::MakeMaker) для помощи легкого формирования этого файла. Не мешает сразу почитать про него хотя бы бегло: perldoc ExtUtils::MakeMaker
    Простой пример файла:

    use ExtUtils::MakeMaker;
    WriteMakefile(
    AUTHOR       => 'Your name, your@email.here',
    NAME         => 'NameOfProject',
    VERSION_FROM => 'lib/WhereVariable_VERSION',
    NO_META      => 1,
    EXE_FILES    => [bin/my_script.pl]
    );
    

    Подробнее об этом я расскажу в следующей статье, которую пока не написал. Но вот вам домашнее задание — почитать perldoc ExtUtils::MakeMaker. Даже если мало что поёмете — всё равно почитайте. Что-то да отложится и потом в будущем всплывёт в вашей памяти 🙂

  4. Делаем пробный запуск:
    perl Makefile.PL
    В этот момент запускается код ExtUtils::MakeMaker (через WriteMakefile), который нам надо вызвать из Makefile.PL, он просканирует текущую папку на предмет файлов в lib/, bin/, script/ и создаст временные папку и файлы, где будут формироваться временные пред-инсталяционные файлы: blib/
  5. После у вас появится Makefile. Затем работа с дистрибутивом переходит в плоскость утилиты make. Поэтому, если вы хотите достаточно чётко понимать процесс инсталяции и работы, вам надо хоть как то понимать, что делает make (например в этой английской документации make). Простое правило — make в дальнейшем должна исполняться из текущего каталога корня нашего дистрибутива. То есть от туда, где находится файл Makefile.PL. Все shell команды, которые есть в Makefile, исполняются там, от куда запущена команда make, то есть в нашем случае — корень дистрибутива. Даже если в shell командах внутри makefile есть ‘cd’ команда (сменить папку), то следующая строка в makefile исполняется в новом shell из той же папки, откуда была запущена make.
    От себя скажу, что когда я понял, как работает make и как писать эффектиные make файлы, моя жизнь в мире Unix сильно упростилась. Ведь make универсальная вещь — с её помощью можно программировать повседневные муторные задачи, которые будут выполняться автоматически с оптимальным выполнением набора команд на основе зависимостей. Например, можно обновлять кучу DNS серверов простой правкой файлов на одной машине и затем простым запуском make. Либо даже устанавливать на «нулевую» ОС Linux, например, всё, что требуется вам для работы одним запуском make (я так довёл почти до автоматизма инсталляцию серверов и всех модулей и программ, которые мне необходимы для некоей конфигурации сервера). Либо делать резервирование с нескольких серверов на один простым запуском make. Всё это можно делать make программой и специально написанным makefile.
  6. Итак, как создан Makefile, запускаем make distcheck. Эту команду мы будем запускать один и более раз, пока не сформируем нормальный MANIFEST.SKIP. Ведь сейчас мы имеем Makefile, который сгенерирован на основе Makefile.PL и модули дистрибуции perl заботливо создали там много служебных «тагетов» (target — мишень), облегчающих работу с дистрибутивом. Их список можно посмотреть по команде make help
  7. make distcheck покажет вам все файлы, которые отсутствуют в MANIFEST. Ваша задача — посмотреть этот список и сделать файл MANIFEST.SKIP. Например, сразу же отметаем файлы в папке blib/ — это временная папка, где будут временные файлы, которые затем будут инсталированны в систему. Они нам не нужны. Пример и разбор файла MANIFEST.SKIP
    Makefile$
    ^blib
    ^pm_to_blib
    ^.*\.bak
    ^.*\.old
    

    Как я уже говорил выше, этот файл описывает исключения для файлов и каталогов в стиле регулярных выражений perl. Поскольку make мы исполняем от корня нашего дистрибутива,
    то файлы, которые будут сравниваться с этими масками, будут вида:

    Makefile
    blib/Web/Site/Constants.pm
    lib/Web/Site/Constants.pm
    Makefile.old
    

    и т.п.. Поэтому, чтобы исключить Makefile из дистрибута (он ведь создаётся автоматически на каждой машине, где будет инсталяция), мы пишем именно Makefile$. Можно написать ^Makefile$
    Поэтому, в том числе, чтобы исключить *.bak файлы, мы пишем маску ^.*\.bak — исключает всё, что заканчивается на .bak и перед этим имеет любые символы, в том числе ‘/’
    Запускаем make distcheck столько раз, сколько нам это необходимо, пока мы не увидим в консоли именно те файлы, которые должны быть в MANIFEST

  8. Как только мы сформировали MANIFEST.SKIP, запускаем make manifest. После этого, у нас есть в директории MANIFEST файл со списком наших файлов. Мы можем редактировать MANIFEST, даже ставить после любого файла строку с комментарием #…
    И в любой момент мы можем запустить снова make distcheck и/или make manifest. Команда make manifest лишь дополнит MANIFEST новыми файлами, которые мы позже добавим в папку и не исключим в MANIFEST.SKIP. И эта же команда сохранит наши комментарии, которые будут даны напротив файлов. Если вы удалите файл из проекта и запустите make manifest, он также будет удален из MANIFEST.

Дальнейшая работа будет заключаться в работе с make утилитой, которая в свою очередь будет работать с генерированным Makefile. Сами же команды в Makefile для perl построены таким образом, чтобы вся работа заключалась в работе с папкой blib — папкой, где будут создаваться файлы на основе файлов в директориях lib/, bin/ и script/. При этом, файлы, которые вы разместите в bin/ или script/, будут «особенными» — Makefile имеет команды для копирования и преобразования их в blib/bin и blib/script директориях. Преобразование заключается в прописывании предстартовых строчек в самих *.pl файлах так, чтобы сделать максимальное портирование на разные типы Unix, а также в установке на эти файлы аттрибутов исполняемости (‘x’). Ведь бывают ситуации, когда на Unix стоит несколько perl версий интерпретатора в разных местах. Задача этих преобразований сделать так, чтобы perl скрипты и модули исполнялись (и устанавливались) именно от той версии perl, которая была запущена на файл Makefile.PL. В этом ещё один плюсь дистрибуции — «навести порядок», если мы имеем несколько версий perl на машине.

В дальнейшей своей статье я расскажу о дальнейших шагах. Наверное, напишу следующую статейку в течении недели.