Этот раздел описывает соглашения по написанию Make-файлов для программ GNU.
5.1 Общие соглашения для Makefile
Каждый Makefile должен включать строку
SHELL = /bin/sh
для того, чтобы избежать проблем на системах, в которых переменная SHELL может быть унаследована из окружения. (Подобные сложности отсутствуют при использовании утилиты GNU make).
Не следует предполагать, что '.' входит в путь для поиска исполнимых программ. Когда Вам нужно запускать программы, которые являются частью Вашего пакета, во время работы make, необходимо использовать префикс './', если программа строится в ходе работы make, или '$(srcdir)/' если файл является неизменяемой частью исходных текстов. Когда ни один из этих префиксов не указан, выполняется поиск в текущем пути.
Отличие между './' и '$(srcdir)' существенно, когда используется опция --srcdir программы configure. Правило вида:
foo.1: foo.man sedscript sed -e sedscript foo.man > foo.1
foo.o: bar.c $(CC) -I. -I$(srcdir) $(CFLAGS) -c bar.c -o foo.c
foo.c: bar.c $(CC) $(CFLAGS) $< -o $@
foo.1: foo.man sedscript sed -s $(srcdir)/sedscript $(srcdir)/foo.man > foo.1
5.2 Использование утилит в Makefile.
Команды, которые пишутся в Makefile (как, впрочем, и в любых других shell-скриптах вроде configure), должны работать в sh, а не в csh. Не следует использовать каких-либо специальных особенностей ksh или bash.
Скрипт configure и правила Makefile для построения и установки программы не должны использовать никаких утилит кроме следующих:
cat cmp cp echo egrep expr grep ln mkdir mv pwd rm rmdir sed test touch
ar bison cc flex install ld lex make makeinfo ranlib texi2dvi yacc
Возможно использование других утилит во фрагментах Makefile или скриптах, которые предназначены только для использования в данной конкретной системе, и для которых Вы уверены в их существовании.
5.3 Стандартные цели в Make
Все программы в GNU должны иметь следующие цели в своих Makefile'ах.
'all'
Компиляция всей программой. Эта цель должна быть целью по умолчанию. Эта цель не должна перестраивать никакие файлы документации; info-файлы должны включаться в поставку, DVI файлы должны формироваться только по явному запросу.
'install'
Компиляция программы и копирование исполнымых файлов, библиотек и т.д. туда, где они должны располагаться для их обычного использования. Если возможно, по этой цели должна выполняться простая проверка того, что программа была правильно установлена.
Команды должны создать все каталоги, в которых файлы будут установлены, если эти каталоги уже не существуют. Сюда входят каталоги, указанные как значения переменных prefix и exec_prefix, так же, как и все их требуемые подкаталоги. Другой способ выполнить это подразумевает использование цели installdirs, описанной ниже.
Используйте символ '-' перед любой командой для установки файлов с man-страницами для того, чтобы игнорировались все ошибки. Это нужно для того, чтобы можно было устанавливать программу на систему, в которой не установлена Unix-система man-документов.
Для установки info-файлов необходимо скопировать их в $(infodir) с $(INSTALL_DATA) (см. Переменные для исполнения команд), и затем выполнить программу install-info (если она имеется). install-info это скрипт, который выполняет редактирование файла 'dir' системы Info для того, чтобы добавить или обновить элемент меню для данного Info-файла; этот скрипт является частью пакета Texinfo. Далее приводится пример правила для установки Info-файла:
$(infodir)/foo.info: foo.info # There may be a newer info file in . than in srcdir -if test -f foo.info; then d=.; \ else d=$(srcdir); i; $(INSTALL_DATA) $$d/foo.info $@; \ # Run install-info only if it exists. # Use 'if' instead of just prepending '-' to the # line so we notice real errors from install-info. # We use '$(SHELL) -c' because some shells do # fail gracefuly when there is an unknown command. if $(SHELL) -c 'install-info --version' \ >/dev/null 2>&1; then \ install-info --infodir=$(infodir) $$d/foo.info; \ else true; fi
'uninstall'
Выполняется удаление всех установленных файлов, созданных при исполнении цели 'install' (но не тех файлов, которые создаются при исполнении цели 'all').
'clean'
Выполняется удаление тех файлов из текущего каталога, которые были созданы при построении программы. Не удаляются файлы, в которых сохранена конфигурация. Так же сохраняются файлы, которые могут быть получены при построении, но которые тем не менее входят в поставку. Следует удалять .dvi файлы, если они не являются частью поставки.
'distclean'
Удаляются все файлы из текущего каталога, которые были созданы при конфигурировании или построении программы. Если Вы распакуете исходные тексты программ, после чего построите программу не создавая самостоятельно каких-либо файлов, то 'make distclean' должно оставить только те файлы, которые входили в поставку.
'mostyclean'
Работает так же, как и clean, но оставляет неудаленными некоторые файлы, которые обычно нежелательно перекомпилировать. Например, цель 'mostyclean' для GCC не удаляет файл 'libgcc.a', поскольку его перекомпиляция редко когда бывает нужна, и к тому же занимает много времени.
'realclean'
Выполняется удаление из текущего каталога всего, что может быть построено с помощью Makefile. Обычно это включает в себя все то, что удаляется по distclean, исходные файлы на C, полученные с помощью построителя синтаксических анализаторов Bison, таблицу тегов, info-файлы и т.д.
Имеется одно исключение: 'make realclean' не должен удалять 'configure', даже если 'configure' может быть построен используя правило в Makefile. Более того, 'make realclean' не должен удалять ничего из того, чье существование требуется для выполнения 'configure' и начального исполнения программы.
'TAGS'
Обновляет таблицу тегов для программы.
'info'
Выполняется построение всех требуемых info-файлов. Лучший всего написать правила по следующему образцу:
info: foo.info foo.info: foo.texi chap1.texi chap2.texi $(MAKEINFO) $(srcdir)/foo.texi
'dvi'
Выполняется построение DVI-файлов для всей TeXinfo-документации. Пример правил:
dvi: foo.dvi foo.dvi: foo.texi chap1.texi chap2.texi $(TEXI2DVI) $(srcdir)/foo.texi
'dist'
Выполняется создание tar-файла, содержащего дистрибутивную поставку этой программы. tar-файл должен быть создан таким образом, чтобы имена файлов в нем начинались с подкаталога, имя которого являлось бы именем поставляемого пакета. Имя может включать в себя номер версии.
Например, поставка дистрибутивного архива для GCC версии 1.40 должна распаковываться в каталог с именем 'gcc-1.40'.
Простейший способ выполнить это состоит в создании названного таким образом каталога, и использовании ln или cp для установки соответствующих файлов в него. После чего необходимо выполнить tar для этого подкаталога.
Цель dist должна явно зависеть от всех файлов, которые не являются исходными, но должны входить в поставку, для того, чтобы убедиться в их актуальности. Смотри раздел "Издание версий".
5.5 Переменные для каталогов
Каталоги для установки должны всегда именоваться посредством переменных, поскольку это упрощает установку программы в нестандартное место. Стандартные имена для таких переменных следующие:
'prefix'
Префикс, используемый для построения умолчательных значений для переменных, перечисленных ниже. Значение по умолчанию для переменной prefix должно быть '/usr/local' (по крайней мере сейчас).
'exec_prefix'
Префикс, используемый при построении значений по умолчанию для некоторых переменных, перечисленных ниже. Значение по умолчанию для переменной exec_prefix должно быть $(prefix).
Как правило, $(prefix) используется для каталогов, которые содержат машиннозависимые файлы (такие, как исполнимые файлы и библиотеки процедур), в то время как $(prefix) используется для остальных каталогов.
'bindir'
Каталог для установки исполняемых файлов программ, которые могут быть запущены пользователем. Обычно, это '/usr/local/bin', но должно быть записано как '$(exec_prefix)/bin'
'libdir'
Каталог для установки исполняемых файлов, которые будут запускаться другими программами, а не пользователем. Объектные файлы и библиотеки объектного кода должны так же попадать в этот каталог. Идея состоит в том, что этот каталог используется для файлов, которые зависят от конкретной архитектуры машины, но не должны находится в пути для команд. Значение для libdir обычно '/usr/local/lib', но должно быть записано как '$(exec_prefix)/lib'.
'datadir'
Каталог для установки файлов с неизменяемыми данными, которые используются программами во время их работы. Этот каталог используется для файлов, которые не зависят от используемого типа машины. Значение этой переменной обычно '/usr/local/lib', но должно быть записано как '$(prefix)/lib'.
'statedir'
Каталог для установки файлов с данными, которые программы могут изменять в процессе своей работы. Эти файлы должны быть независимыми от типа используемой машины, и должны допускать разделение их между машинами при сетевой установке. Значение этой переменной обычно '/usr/local/lib', но должно быть записано как '$(prefix)/lib'
'includedir'
Каталог для установки заголовочных файлов (header-файлов), которые могут быть включены другими пользовательскими программами с помощью директивы препроцессора '#include'. Значение этой переменной обычно '/usr/local/include', но должно быть записано как '$prefix/include'.
Большинство компиляторов отличных от GCC не выполняют поиск заголовочных файлов в '/usr/local/include', поэтому установка заголовочных файлов в этот каталог целесообразна только для GCC. Иногда это не представляет из себя проблему, так как некоторые библиотеки предназначены для использования исключительно с GCC. Но имеются так же и библиотеки, предназначенные для работы и с другими компиляторами. Они должны устанавливать свои включаемые файлы в два места, одно из которых определено переменной includedir, а другое oldincludedir.
'oldincludedir'
Каталог для установки заголовочных файлов для использования с компиляторами, отличными от GCC. Значение этой переменной обычно 'usr/include'. /
Команды Makefile должны проверить, не пусто ли значение переменной oldincludedir. Если оно пусто, они не должны пытаться использовать ее и выполнять повторную установку включаемых файлов.
Пакет не должен замещать существующие заголовочные файлы в этом каталоге, в случае, если заголовочный файл пришел не из того же пакета. Так, если Ваш пакет Foo предоставляет заголовочный файл 'foo.h', то он должне установить заголовочный файл в каталог, заданный oldincludedir, если (1) foo.h не существует, или (2) foo.h существует и пришел из пакета Foo.
Для того, чтобы проверить, что foo.h пришел из пакета Foo, поместите специальную строку в этот файл - часть комментария - и проверьте наличие этой строки с помощью команды grep.
'mandir'
Каталог для установки man-страниц (если они есть) для этого пакета. Переменная должна включать суффикс для соответсвующей секции руководства - обычно '1' для утилит. Обычно значение этой переменной '/usr/local/man/man1', но должно быть записано как '$(prefix)/man/man1'
'man1dir'
Каталог для установки в раздел 1 man-страниц.
'man2dir'
Каталог для установки в раздел 2 man-страниц.
Используйте переменные такого рода вместо 'mandir', если пакет должен устанавливать man-страницы более чем в один раздел.
'manext'
Расширение для имени файла для устанавливаемых man-страниц. Переменная должна содержать точку, за которой следует соответствующая цифра, обычно '.1'.
'man1ext'
Расширение имени файла для установки в раздел 1 man-страниц.
'man2ext'
Расширение имени файла для установки в раздел 2 man-страниц.
Используйте переменные такого рода вместо 'manext', если пакет должен устанавливать man-страницы более чем в один раздел.
'infodir'
Переменная должна содержать имя каталога для установки info-файлов для данного пакета. По умолчанию, ее значение должно быть '/usr/local/info', но должно быть записано как '$(prefix)/info'.
'srcdir'
В этой переменной должно находится имя каталога, содержащего компилируемые исходные тексты. Значение этой переменной обычно вставляется скриптом configure.
Пример:
# Common prefix for installation directories. # NOTE: This directory must exist when you start the install. prefix = /usr/local exec_prefix = $(prefix) # Where to put the executable for the command 'gcc'. bindir = $(exec_prefix)/bin # Where to put the directories used by the compiler. libdir = $(exec_prefix)/lib # Where to put the Info files. infodir = $(prefix)/info