Использование autotools
Содержание
Подготовка заготовки configure.ac
Первым делом запускаем в каталоге с файлами проекта утилиту autoscan
:
$ autoscan
По завершении её работы в текущем каталоге должен появиться файл configure.auto
. Переименуем его в configure.ac
:
$ mv configure.auto configure.ac
Откроем файл configure.ac
в текстовом редакторе и внесём информацию о проекте, отредактировав строчку AC_INIT
:
AC_INIT([view3d], [1.2-sdl2], [vladimir@stupin.su])
Где:
view3d
- название проекта,1.2-sdl2
- версия программы,vladimir@stupin.su
- адрес электронной почты сопровождающего проект/программу.
Если в проекте есть отдельный заголовочный файл, в который вынесены все опции для настройки проекта, то имя этого файла нужно вписать в макрос AC_CONFIG_HEADER
:
AC_CONFIG_HEADER([config.h])
Если же такого файла нет, то этот макрос нужно удалить.
В макросе AC_CONFIG_SRCDIR
нужно указать имя главного файла, из которого система сборки autotools
рекурсивно извлечёт все используемые заголовочные файлы:
AC_CONFIG_SRCDIR([main.c])
Система сборки autotools
предназначена прежде всего для сборки программ проекта GNU. У проекта GNU имеется собственный набор стандартных файлов, которые должны быть в каталоге с проектом. Для сборки других программ, не соответствующих стандартам проекта GNU, нужно добавить в макрос AM_INIT_AUTOMAKE
опцию foreign
:
AM_INIT_AUTOMAKE([foreign])
Для того, чтобы в процессе компиляции программы выводились разнообразные сообщения об ошибках, которые помогают выявлять допустимые, но подозрительные, фрагменты кода, я добавляю в макрос AM_INIT_AUTOMAKE
дополнительные опции:
AM_INIT_AUTOMAKE([foreign -Wportability -Wall -Werror -Wsyntax])
Подготовка файла Makefile.am
Теперь создадим шаблон для генерации файла Makefile
. Для начала нужно вернуться к файлу configure.ac
и добавить в него макрос для формирования файла Makefile
из будущего файла Makefile.am
, который мы собираемся создать:
AC_CONFIG_FILES([Makefile])
Теперь можно приступать непосредственно к созданию файла Makefile.am
.
Сборка двоичных файлов
В простейшем случае можно ограничиться двумя строчками:
bin_PROGRAMS = view3d
view3d_SOURCES = vmdl.cpp idpo.cpp events.cpp main.cpp
В переменной bin_PROGRAMS
перечисляются имена выполняемых файлов, которые должны получиться в итоге сборки.
Для каждого исполняемого файла указывается по одной переменной вида <имя>_SOURCES
, в которой перечисляются все файлы исходных текстов, необходимых для сборки этой программы.
Аналогичным образом при помощи переменной sbin_PROGRAMS
можно собирать исполняемый файлы для помещения в каталог sbin
.
Опции компиляции
Для того, чтобы компилировать двоичный файл с другими опциями, то для каждого из двоичных файлов опции компиляции можно настроить с помощью переменной вида <имя>_CFLAGS
. Например, в примере ниже одна и та же программа собирается дважды, причём вторая компилируется с опцией компилятора -DLITE
, а при её сборке не используется файл master.c
:
sbin_PROGRAMS = parled12 parled12lite
parled12_SOURCES = client.c daemon.c main.c parport.c server.c config.c evloop.c master.c parports.c slave.c
parled12lite_SOURCES = client.c daemon.c main.c parport.c server.c config.c evloop.c parports.c slave.c
parled12lite_CFLAGS = -DLITE
Тесты
Если в программе имеются тесты, то их сборку можно настроить способом, аналогичным сборке исполняемых файлов:
check_PROGRAMS = test
test_SOURCES = bin.c test.c
TESTS = $(check_PROGRAMS)
В переменной check_PROGRAMS
перечисляются имена выполняемых файлов, которые должны получиться в итоге сборки тестовых программ.
Для каждого исполняемого файла указывается по одной переменной вида <имя>_SOURCES
, в которой перечисляются все файлы исходных текстов, необходимых для сборки этой программы.
При успешном прохождении теста программа должна завершаться с нулевым кодом возврата.
В переменной TESTS
перечисляются все программы, которые нужно вызвать для тестирования проекта.
В дальнейшем запустить все тесты можно будет с помощью команды следующего вида:
$ make check
По окончании тестирования итоги будут сведены в таблицу следующего вида:
make check-TESTS
make[1]: вход в каталог «/home/stupin/old/git/pup»
make[2]: вход в каталог «/home/stupin/old/git/pup»
PASS: test
============================================================================
Testsuite summary for pup 1.0
============================================================================
# TOTAL: 1
# PASS: 1
# SKIP: 0
# XFAIL: 0
# FAIL: 0
# XPASS: 0
# ERROR: 0
============================================================================
make[2]: выход из каталога «/home/stupin/old/git/pup»
make[1]: выход из каталога «/home/stupin/old/git/pup»
Документация
Если в проекте есть дополнительные файлы с документацией, которую нужно установить в систему (или поместить в двоичный пакет) вместе с собранными двоичными файлами, то их можно можно перечислить в переменной dist_doc_DATA
:
dist_doc_DATA = README.md ideas.txt
Учёт зависимостей
Для сборки большинства программ требуются дополнительные библиотеки. Перед сборкой программы нужно её скомпилировать, а это не получится сделать, если в системе нет заголовочных файлов этих библиотек. Для проверки наличия в системе необходимых заголовочных файлов предназначен макрос AC_CHECK_HEADERS
:
AC_CHECK_HEADERS([fcntl.h limits.h stdlib.h string.h sys/file.h sys/ioctl.h sys/socket.h syslog.h unistd.h])
Для получения полного списка используемых проектом системных и сторонних заголовочных файлов я пользуюсь командами следующего вида:
$ egrep -h '^#include\s+<' *.h *.c | sort -u
Для поиска библиотек используются макрос AC_CHECK_LIB
, первым аргументом которого является имя библиотеки, а вторым аргументом - необходимые функции:
AC_CHECK_LIB([z], [compress2, uncompress])
AC_CHECK_LIB([m], [sqrt])
AC_CHECK_LIB([SDL2], [SDL_CreateWindow, SDL_GetError, SDL_GL_CreateContext, SDL_GL_MakeCurrent, SDL_GL_SetAttribute, SDL_GL_SwapWindow, SDL_Init, SDL_PollEvent, SDL_Quit])
AC_CHECK_LIB([GL], [glClear, glClearDepth, glColor3f, glDepthFunc, glDisable, glEnable, glFinish, glFrustum, glHint, glLightf, glLightfv, glLoadIdentity, glLoadMatrixf, glMat rixMode, glPolygonMode, glRotatef, glShadeModel, glTexEnvf, glTexParameterf, glTranslatef])
Обратите внимание, что в отличие от других макросов, в этом макросе список функций перечисляется не через пробел, а через запятую!
Генерация файлов configure и Make
Теперь, когда мы подготовили файлы configure.ac
и Makefile.am
, можно приступить к автоматической генерации файлов configure
и Makefile
, с помощью которых можно будет настроить и собрать проект.
Сначала вызываем команду aclocal
, которая создаст файл aclocal.m4
необходимый для дальнейших действий:
$ aclocal
Теперь вызываем команду autoconf
, которая создаст нужный нам файл configure
:
$ autoconf
Далее вызываем команду automake
, которая создаст нужный нам файл Makefile
для утилиты GNU Make:
$ automake --add-missing
Опция --add-missing
создаёт в каталоге с проектом дополнительные файлы, необходимые для обработки Makefile
.
Сборка проекта
Теперь у нас имеются файлы configure
и Makefile
. Первый файл - это сценарий оболочки, который собирает информацию о системе, в которой выполняется сборка проекта: проверяет наличие необходимых для сборки компилятора, компоновщика, заголовочных файлов, библиотек, функций, определений типов данных, формирует опции для вызова обнаруженных в системе компилятора и сборщика и т.п. Второй файл содержит список возможных целей сборки, информацию о зависимостях между ними и команды преобразования файлов исходных текстов в двоичные объектные файлы.
Вызовем скрипт настройки:
$ ./configure
Для компиляции и сборки двоичных файлов вызовем GNU Make:
$ make
Для тестирования можно вызвать GNU Make с целью check
:
$ make check
Для сборки архива с исходными текстами и всеми файлами, необходимыми для сборки проекта, можно вызвать GNU Make с целью dist
:
$ make dist
Архив должен сформироваться в текущем каталоге.