суббота, 10 марта 2012 г.

Кросс-платформенные системы сборки

В связи с поворотом в сторону многоплатформенной разработки
необходимость подобрать что-то подходящее возникла и перед нами.

Это первое, на чём программисты пытаются "поиграть" при отсутствии
понимания остальных аспектов задачи :-). Правда, в нашем случае
получилось так, что выбор системы сборки стал последним...



Основные требования к системе сборки


Поскольку имеется довольно большой опыт разработки немаленьких
программ, то требования к системе определились очень быстро:
- Кроссплатформенность
- Наличие подробной пользовательской документации
- Скорость работы на больших проектах
- Зрелость проекта
- Наличие активного community
- Распространенность
- Легкость подключения внешнего пакетного менеджера
или его аналога (*)
- Разумно ограниченные требования к квалификации maintainer'a

(*) Очень часто требуется хранить в составе исходной конфигурации
большие объёмы двоичных данных, например, графика, полученная от
дизайнеров, тестовые наборы электронных карт и так далее. Меняются они
редко, но меняются - по этой причине их нужно с одной стороны
"версионизировать", с другой - запихивать эти объёмы в репозитарий
исходных текстов может показаться разумным только на первый взгляд в
самом начале работ. Когда дамп SVN (к примеру) приобретает "взрослые
размеры" в деяток гигабайт со всеми вытекающими последствиями,
подобный оптимизм сетевые администраторы комментируют достаточно
язвительно...

Кандидаты



Изначально рассматривался вариант доработки внутрифирменной системы
сборки, благо она вся из себя Unix-подобная
(cygwin + gmake + perl + ...) и достаточно развитая. Система, как
никак, ровесник SCons (2000), поддерживает модули, внешние пакеты,
WiX, формирование нужных артефактов для регистрации сборок в базе
данных и т.д...

Тем не менее, при зрелом рассмотрении очевидно, что поддержка
нескольких платформ не сводится к работе в Unix-подобном окружении,
несколько ОС и toolchain'ов требуют совершенно других затрат на
разработку и поддержку системы - самое время вспомнить о причинах
появления Autotools ;-)

Даже относительно недолгий поиск альтернатив дает нам массу
конкурирующих вариантов. Вот те, кто прошёл самую грубую первичную
фильтрацию:
- gmake+Autotools
- SCons
- CMake
- WAF
- TUP
- GYP

Дальше рассмотрим каждого кандидата поподробнее.

gmake+Autotools


Что тут скажешь - "бессмертная классика".
Вот только под Windows придётся обязательно пользоваться cygwin или
чем-то подобным. Это-то можно пережить, но вот скорость работы даже на
небольших проектах - это что-то...

Довершающим штрихом является его сложность.

Явно не лучший кандидат в 201X-году.

SCons


Очень достойный вариант. Сборочные сценарии являются файлами Python,
сам он тоже целиком написан на Python, что вместе с расширяемой
архитектурой дает "свободу для творчества".

Очень зрелый проект, активное community, наличие ресурсов, посвященных
исключительно SCons.

С другой стороны, скорость работы на больших проектах, мягко говоря, не впечатляет.

Имеется "идейный наследник" в виде WAF.

CMake


Не менее достойный вариант. Непосредственно сборкой не занимается, a
лишь генерирует файлы управления сборкой из файлов
CMakeLists.txt. Поддерживает, как и SCons все нужные платформы и
распространенные компиляторы.

Сборка с использованием CMake работает на фоне SCons очень быстро.

WAF


Идейный наследник SCons, пытающийся компенсировать его
неторопливость и некоторые спорные аспекты архитектуры.

Тем не менее, проект KDE от BKsys/Waf отказался в пользу CMake.

Вызвано это, возможно, было тем, что BkSys не исправлял все "грехи"
SCons, отношения с его автором были подпорчены, а сам WAF явно на
момент принятия решения "не дотягивал" до должного уровня зрелости
(сейчас уже выпущена версия 1.6).

Возможно, причина была совершенно иная, но "осадок остался".

TUP


Самый быстрый из рассмотренных кандидатов.

Взамен требует полной ломки представлений о работе системы сборки от
mainainer'а.

Не слишком распространен, зрелость проекта пока под вопросом.

GYP (Generate Your Projects)



Видимо, очень мощная и хорошая система, раз ей собирается Chrome.
Тоже базируется на Python, как и многое в инструментарии
Google. Должен легко расширяться.

Тем не менее, минимум информации и нераспространенность не позволяют
считать его приемлемым вариантом.

Победители


После внимательного изучения вариантов стало ясно, что с учетом
имеющихся требований, реально вариантов всего два: SCons и CMake.

SCons выглядел более притягательным из "абстрактно-архитектурных"
соображений, к тому же у смежных команд имелся на нём опыт работы.

CMake подкупал своей широкой распространенностью.

Мне лично больше импонировал вариант SCons, но, поскольку, не хотелось
делать ошибок, было решено реализовать пилотный проект на SCons, а
потом повторить его на CMake и сравнить результаты.

В этом проекте было не больше 50 модулей, но начальная задержка при
работе SCons начала довольно быстро вызывать раздражение.

Сменили вычисление обновления файла на метку времени (по умолчанию
стоит хэш) - стало легче, но чуть-чуть...

Когда по плану дошло до альтернативной реализации на CMake,
выяснилось, что делается она несколько быстрее, работает все НАМНОГО
быстрее, "из коробки" есть поддержка Visual Studio проектов (в SCons
она лишь декларирована - на деле там еще пилить и пилить).

Поначалу в CMake ужаснул язык описания проектов - синтаксис его
показался ужасным, обилие скобок чем-то напомнило Lisp, неявные
умолчания и работа со списками вызвали ужас...

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

По итогу оказалось, что, будучи потенциально более "ущербной"
системой, CMake дает ощутимые практические преимущества.

Основные проблемы на начально этапе заключались как раз в понимании,
что CMake непосредственно сборкой не занимается, a лишь генерирует
файлы управления сборкой из файлов CMakeLists.txt - это означает, что
вся мощь по автоматической генерации файлов и модификации существующих
может быть применена только ПЕРЕД началом сборки или после ее конца,
на фазе install.

Если нам нужно сделать что-то средствами CMake во время сборки - нужно
запускать его вторую копию через custom rule. Кстати, некоторые
типовые задачи (вот она - ориентация на практику!) можно выполнять
прямо из командной строки CMake, например копирование файлов.

Вывод


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

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

Более того, чтобы систематизировать процесс построения, разработан
небольшой Python-драйвер, который запускается из корня дерева
исходных текстов и вызывает CMake для дальнейшей работы, если это
необходимо.

Комментариев нет: