WAF — это программное обеспечение, предназначенное для автоматизации сборки, написанное на Python и использующее сценарные файлы конфигурации на языке Python.
Введение
Автоматическая сборка призвана играть основную роль в непрерывном объединении программных кодов и считается главным фактором в реализации многих проектов. Это начальный шаг в целой серии автоматизированных шагов, помогающих как можно раньше определить вероятные проблемы, вызванные последними коррективами в коде. Говоря в этом плане о сборке, подразумевается не просто процесс компиляции и связывания исходного кода для формирования исполняемого файла. Процесс сборки состоит из ряда проверок, а также включает в свой состав подбор всех компонентов, требуемых для работы программы. Этап сборки является необходимым, даже если пользователь пишет код на интерпретируемом языке.
Файлы, сформированные на этапе сборки, то есть, артефакты сборки, далее проходят следующие этапы, а именно, тестирование и развертывание в тестовом окружении. После успешного завершения всех этапов сборка считается готовой к развертыванию в производственную среду. Автоматизация сборки позволяет гарантировать, что все этапы будут исполнены в нужном порядке для каждого фрагмента или пакета программных фрагментов, и пользователь оперативно получит обратную связь, сэкономив свое время.
Многие программисты в качестве основного языка используют Python. Но тем не менее иногда встречаются задачи, когда необходимо выполнить, к примеру, на C/C++. Известны различные системы, с помощью которых можно собирать такие проекты. Классическими системами могут считаться make и autotools, но есть и альтернативные варианты, такие как, например, SCons и Waf.
WAF: ПО для автоматизации сборки
Для того чтобы сделать этот обзор более предметным, рассмотрим эту систему на практике. Предположим имеется в наличии простой проект, в котором присутствуют стандартные задачи сборки, далеко не всегда являющиеся тривиальными. Предположим, надо сформировать простой web-сервер, целью которого является выдача статичной страницы, подготавливаемой в отдельном html файле, но которая в результате должна встраиваться в исполняемый файл.
То есть, на этапе сборки по html-коду необходимо собрать исходник с кодом на Си. В качестве серверной библиотеки можно использовать mongoose, исходники которого будут находиться внутри проекта. Необходимо собрать их в статическую библиотеку, которую в дальнейшем нужно вставить внутрь исполняемого файла.
Для того чтобы собрать проект через WAF, потребуется, конечно, сам WAF, который может быть предоставлен в форме одного файла и его необходимо разместить прямо в корне проекта. Это означает, что инсталлировать WAF в систему нет необходимости, а пользователь кода получает из системы контроля версий проект уже с «начинкой». Помимо этого требуется сам сборочный скрипт, который можно назвать wscript.
Дерево разрабатываемого проекта имеет следующий вид:
~/devel/stupίd-server$ tree . |-- external tree . |-- external
| `-- mongoose
| |-- mongoose.c
| `-- mongoose.h
|-- html
| `-- ίndex.html
|-- html2c
|-- SConscrίpt
|-- SConstruct
|-- src
| `-- maίn.cpp
|-- waf
`-- wscrίpt
Преобразование html может быть выполнено позже, но необходимо осуществить сборку сервера. Он должен выдать ответ, который жестко зашит в main.cpp. Требуется осуществить следующие действия:
- Система обязана собрать mongoose в статическую библиотеку.
- Выполнить компиляцию src/main.cpp.
- Полученный результат следует объединить в один исполняемый файл.
Причем все артефакты следует расположить в отдельной директории, чтобы в случае ошибочных действий ее можно просто удалить. Следует также отметить, что утверждение о том, что если пользователь знает Python, то все будет легко, так как скрипты сборки написаны именно на нем, не совсем верное. На практике это может не действовать, так как синтаксически язык аналогичен Python, но при реальных действиях требуется ясное понимание идеологии и схемы работы этой систем, которое предполагает все-таки подробное изучение документации и часто исходников самой системы.
Программа на WAF выглядит следующим образом:
top = '.'
out = 'buίld-waf'
def set_optίons(opt):
opt.tool_optίons('compίler_cc')
opt.tool_optίons('compίler_cxx')
def confίgure(conf):
conf.check_tool('compίler_cc')
conf.check_tool('compiler_cxx')
conf.env.append_unique('CCFLAGS', '-O2')
conf.env.append_unique('CXXFLAGS', '-O2')
def build(bld):
bld(
target = 'mongoose',
features = 'cc cstaticlib',
source = bld.path.ant_glob('external/mongoose/**/*.c'),
export_incdirs = 'external/mongoose',
)
bld(
features = 'cxx cprogram',
source = bld.path.ant_glob('src/**/*.cpp'),
target = 'stupid-server',
lib = ['dl', 'pthread'],
uselib_local = ['mongoose'],
)
В первых двух строчках определяется, что будет считаться корнем проекта, и куда будут помещаться артефакты. Можно видеть, что в Waf все это выполнено очень логично. Затем идет выполнение функции set_options. Ее Waf вызывает для дополнения существующих стандартных параметров командной строки, пользовательскими параметрами. В рассматриваемом варианте должен быть добавлен стандартный набор параметров для того, чтобы можно было оказывать влияние на работу Cи и C++ компиляторов.
Затем идет функция configure. Она вызывается, когда используется ./waf configure
и служит для выставления всех переменных окружения и обнаружения всех инструментов, которые в дальнейшем будут применяться при сборке командой ./waf build
. Подразделение на два этапа, а именно, конфигурация и сборка, является аналогичным тому, что применяется в системе autotools и предназначено для ускорения процесса.
При каждодневном использовании конфигурирование следует вызывать редко, а сборку практически постоянно. Таким образом, экономится значительная часть вр