Вперед Назад Содержание

9. Как запускать make

make-файл, определяющий, как перекомпилировать программу, может быть использован более, чем одним способом. Самое простое использование заключается в перекомпиляции каждого файла, зависимости которого были обновлены. Обычно make-файлы пишутся так, чтобы при запуске программы make без аргументов она делала именно это.

Но вы могли бы захотеть обновить только некоторые из файлов, вы могли бы захотеть использовать другой компилятор или другие опции компилятора, вы могли бы захотеть просто выяснить, у какие файлы нуждаются в обновлении, не изменяя их.

Передавая программе make аргументы при ее запуске, вы можете сделать все это, а также много другого.

Возвращаемым результатом программы make всегда является одно из трех значений:

0

Возвращаемым результатом является нуль, если программа make выполнилась успешно

2

Возвращаемым результатом является двойка, если программа make обнаруживает какую-либо ошибку. Она выдаст на экран сообщение, описывающее, какая именно ошибка произошла.

1

Возвращаемым результатом является единица, если вы используете опцию '-q' и программа make определяет, что какая-то цель не является, на момент запуска программы make, обновленной. Смотрите раздел 9.3 [Вместо исполнения команд].

9.1 Аргументы для определения make-файла

Для определения имени make-файла служит опция '-f' или '--file' (работает также опция '--makefile'). Например, фрагмент командной строки '-f altmake' указывает на использование в качестве make-файла файла с именем 'altmake'.

Если вы используете опцию '-f' несколько раз, указывая за каждым ее вхождением аргумент, все определенные таким образом файлы совместно используются в качестве make-файлов.

Если вы не используете опцию '-f' или '--file', то в качестве имен по умолчанию пробуются имена 'GNUmakefile', 'makefile' и 'Makefile', именно в таком порядке, и в роли make-файла используется первый из этих трех, который существует или может быть порожден (смотрите главу 3 [Написание make-файлов]).

9.2 Аргументы для определения главных целей

Главные цели представляют собой цели, которые в конечном счете стремится обновить программа make. Другие цели обновляются только в том случае, если они появляются в качестве зависимостей гланых целей или в качестве зависимостей зависимостей главных целей, и т.д..

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

Вы можете определить другую главную цель или главные цели при помощи аргументов программы make. Используйте имя главной цели как аргумент. Если вы определяете несколько главных целей, то программа make обрабатывает каждую из них по очереди, в том порядке, в котором вы их упоминаете.

Любая цель make-файла может быть определена в качестве главной цели (если она не начинается с символа '-' и не содержит символ '=', так как в этих случаях это будет воспринято, соответственно, как опция или определение переменной). В качестве главной цели может быть определена даже цель, не содержащаяся в make-файле, если программа make может найти неявное правило, которое указывает, как ее породить.

Одно из использований определения главной цели возможно в том случае, если вы хотите откомпилировать только часть программы или только одну из нескольких программ. Определите в качестве главной цели каждый файл, который вы хотите заново породить. Например, рассмотрим каталог, содержащий несколько программ, с make-файлом, который начинается примерно так:

.PHONY: all all: size nm ld ar as
Если вы работаете над программой size, то вы могли бы захотеть написать в качестве команды 'make size', и при этом были бы перекомпилированы только файлы этой программы.

Еще одно использование определения главной цели состоит в порождении файлов, который при работе с главной целью по умолчанию не породились. Например, это может быть файл с отладочной информацией или версия программы, компилирующаяся специально для тестирования, которые могут иметь правило в make-файле, но не являться зависимостью главной цели про умолчанию.

Определение главной цели также может использоваться при запуске команд, связанных с целями-именами действий (смотрите раздел 4.4 [Цели-имена действий]) или пустыми целями (смотрите раздел 4.6 [Пустые целевые файлы для фиксации событий]). Многие make-файлы содержат цель-имя действия и именем 'clean', которая удаляет все, за исключением исходных файлов. Естественно, это делается только в том случае, если вы явно требуете этого при помощи 'make clean'. Ниже приведен список типичных имен целей-имен действий и пустых целей. Смотрите раздел 14.3 [Стандартные цели], для детального списка всех стандартных имен целей, которые используются программными пакетами GNU.

'all'

Порождает все цели верхнего уровня, которые упомянуты в make-файле

'clean'

Удаляет все файлы, которые обычно создаются в результате выполнения программы make.

'mostlyclean'

Аналогично цели 'clean', но может воздержаться от удаления некоторых файлов, перекомпилировать которые обычно не хочется. Например, в GCC цель 'mostlyclean' не удаляет файл 'libgcc.a', поскольку ее перекомпиляция требуется редко и занимает много времени.

'distclean'

'realclean'

'clobber'

Любая из этих целей могла бы быть определена для удаления некоторых файлов, которые не удаляются при помощи цели 'clean'. Например, таким способом могли бы удаляться конфигурационные файлы или связи, которые обычно создаются в качестве подготовки к компиляции, даже если сам make-файл не может создать эти файлы.

'install'

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

'print'

Печатает список измененных исходных файлов.

'tar'

Создает из исходных файлов tar-файл.

'shar'

Создает из исходных файлов архив командной оболочки (shar-файл).

'dist'

Создает из исходных файлов распространяемый файл. Это может быть tar-файл или shar-файл, или же сжатая версия одного из них, или даже что-нибудь еще, не упомянутое здесь.

'TAGS'

Обновляет таблицу тэгов программы, получаемой при помощи данного make-файла.

'check'

'test'

Выполняет самотестирование программы, получаемой при помощи данного make-файла.

9.3 Вместо исполнения команд

make-файл указывает программе make, как определить, является ли цель обновленной и как обновлять каждую цель. Но обновление целей - это не всегда то, что вам хочется. Некоторые опции определяют другие действия программы make.

'-n'

'--just-print'

'--dry-run'

'--recon'

"Нет операций". Действия программы make состоят в выводе на экран тех команд, которые использовались бы для обновления целей, но без реального их выполнения.

'-t'

'--touch'

"Изменение времени обновления". Действия программы make состоят в том, что цели помечаются как обновленные, без реального их изменения. Другими словами, программа make иммитирует компиляцию целей, но на самом деле не изменяет их содержимого.

'-q'

'--question'

"Запрос". Действия программы make состоят в выявлении того, являются ли цели уже обновленными, без выдачи каких-либо сообщений, и при этом, независимо от результатов, не выполняется ни одной команды.

'-W FILE'

'--what-if=FILE'

'--assume-new=FILE'

'--new-file=FILE'

"А что, если". За каждой опцией '-W' следует имя файла. В качестве времени изменения данных файлов программой make запоминается текущее время, хотя реальные времена модификации остаются прежними. Вы можете использовать опцию '-W' вместе с опцией '-n' для того, чтобы увидеть что произошло бы, если вам потребовалось изменить определенные файлы.

При указанной опции '-n', программа make печатает команды, которые обычно она бы выполняла, но без их выполнения.

При указанной опции '-t', программа make игнорирует команды в правилах и использует (точнее, создает эффект использования) команду touch для каждой цели, которую нужно заново порождать. При этом также печатается команда touch, если не используется опция '-s' или цель .SILENT. Для ускорения работы, программа make, в действительности, не вызывает программу touch. Она напрямую выполняет ее работу.

При указанной опции '-q', программа make ничего не печатает и не выполняет никаких команд, но возвращаемый ею результат является нулем, если, и только если, рассматриваемые ею цели уже являются обновленными. Если результатом является единица, то это значит, что необходимо выполнить какое-либо обновление. Если программа make обнаруживает ошибку, то результатом является двойка, поэтому вы можете отличить ошибку от необновленной цели.

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

Опции '-n', '-t', и '-q' не воздействуют на командные строки, которые начинаются с символа '+' или содержат в качестве подстроки '$(MAKE)' или '${MAKE}'. Обратите внимание, что только строка, начинающаяся с символа '+' или содержащая подстроку '$(MAKE)' или '${MAKE}' выполняется, невзирая на эти опции. Другие строки в том же правиле не выполняются, если они также не начинаются с символа '+' и не содержат в качестве подстроки '$(MAKE)' или '${MAKE}'. (Смотрите раздел 5.6.1 [Как pаботает пеpеменная make].)

Опция '-W' обеспечивает две возможности:

Обратите внимание, что опции '-p' and '-v' позволяют вам получить другую информацию о программе make и о используемых make-файлах (смотрите раздел 9.7 [Обзор опций]).

9.4 Предотвращение перекомпиляции некоторых файлов

Иногда у вас может быть иметься измененный исходный файл, но при этом вы можете не захотеть перекомпилировать все файлы, которые зависят от него. Например, предположим, что вы добавляете макрос или объявление в заголовочный файл, от которого зависят многие другие файлы. Следуя установленному порядку, программа make предполагает, что любое изменение в заголовочном файле требует перекомпиляции всех зависимых файлов, но вы знаете, что они не обязательно должны быть перекомпилированы и вы бы предпочли не тратить время, ожидая выполнения их компиляции.

Если перед изменением заголовочного файла вы предвидите эту проблему, то вы можете использовать опцию '-t'. Эта опция указывает программе make не выполнять команды из правил, а вместо этого пометить цель как обновленную путем изменения времени ее последней модификации. Вам следует придерживаться такого порядка действий:

  1. Используйте команду make для перекомпиляции исходных файлов, которые на самом деле требуют перекомпиляции.
  2. Сделайте изменения в исходных файлах.
  3. Используйте команду 'make -t' для отметки всех объектных файлов как обновленных. Когда вы в следующий раз запустите программу make, изменения в заголовочных файлах не вызовут никакой перекомпиляции.
Если вы уже изменили заголовочный файл в тот момент, когда некоторые файлы требуют перекомпиляции, делать это слишком поздно. Вместо этого, вы можете использовать опцию '-o <имя файла>', которая отмечает указанный файл как "старый" (смотрите раздел 9.7 [Обзор опций]). Это означает, что сам этот файл не будет заново порожен и ничего больше не будет заново порождено по причине изменения этого файла. Следуйте такому порядку действий:
  1. Перекомпилируйте исходные файлы, которые нуждаются в компиляции по причинам, не зависящим от определенного заголовочного файла, при помощи команды 'make -o <имя заголовочного файла>'. Если речь идет о нескольких заголовочных файлах, используйте отдельную опцию '-o' для каждого заголовочного файла.
  2. Измените время обновления всех объектных файлов при помощи команды 'make -t'.

9.5 Перекрывающиеся переменные

Аргумент, который содержит символ '=', определяет значение переменной: аргумент 'v=x' устанавливает x в качестве значения переменной v. Если вы определяете значение таким образом, то в make-файле все обычные присваивания значения этой же переменной игнорируются - мы говорим, что они перекрываются аргументом командной строки.

Наиболее типичным использованием этой возможности является передача дополнительных опций компиляторам. Например, в грамотно написанном make-файле в каждую команду, которая запускает C-компилятор, включается переменная CFLAGS, поэтому файл 'foo.c' должен компилироваться примерно так:

cc -c $(CFLAGS) foo.c
Таким образом, в какое значение вы ни устанавливаете переменную CFLAGS, это воздействует на каждый сеанс компиляции. make-файл, возможно, определяет обычное значение для переменной CFLAGS, например так:

CFLAGS=-g
Каждый раз, когда вы запускаете программу make, вы, если хотите, можете перекрыть это значение. Например, если вы напишете в командной строке 'make CFLAGS='-g -O'', каждый раз C-компиляция будет выполняться при помощи командной строки 'cc -c -g -O'. (Это иллюстрирует то, как вы можете использовать в командной оболочке апострофы для включения в значение переменной, при ее перекрытии, пробелов и других специальных символов.)

Переменная CFLAGS - это только одна их многих стандартных переменных, которые существуют только для того, чтобы вы могли изменять их таким образом. Смотрите раздел 10.3 [Переменные, используемые неявными правилами], где приведен полный их список.

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

Когда вы перекрываете переменную при помощи аргумента командной строки, вы можете определить либо рекурсивно вычисляемую переменную, либо упрощенно вычисляемую переменную. В примерах, показанных выше, создается рекурсивно вычисляемая переменная; для создания упрощенно вычисляемой переменной, пишите ':=' вместо '='. Но если вы не хотите включать в определяемое вами значение ссылку на переменную или вызов функции, то становится безразличным, какого вида переменную вы создаете.

Если один способ, при помощи которого make-файл может изменить переменную, которую вы перекрыли. Он заключается в использовании директивы override, которая представляет собой строку, которая выглядит примерно так: 'override VARIABLE = VALUE' (смотрите раздел 6.7 [Директива override]).

9.6 Проверка компиляции программ

Обычно, когда происходит ошибка при выполнении команды командной оболочки, программа make немедленно прекращает работу, возвращая ненулевой результат. Никаких команд ни для какой цели после этого не выполняется. Ошибка подразумевает, что главная цель не может быть корректно заново порождена, и программа make, как только узнает об ошибке, сразу сообщает об этом.

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

В таких случаях вам следует использовать опцию '-k' или '--keep-going'. Она указывает программе make продолжать работу с другими зависимостями обновляемых целей, при необходимости заново порождая эти зависимости, перед прекращением работы возвратом ненулевого результата. Например, в случае ошибки при компиляции одного объектного файла, программа make, запущенная при помощи командной строки 'make -k', продолжит компиляцию других объектных файлов, хотя уже и известно, что их компоновка будет невозможна. Помимо продолжения работы после после неудачной команды командной оболочки, программа make, запущенная при помощи командной строки 'make -k', будет продолжать работу как можно дольше после того, как она выяснит, что не знает, как породить целевой файл или файл зависимости. Такая ситуация всегда будет вызывать сообщение об ошибке, но без опции '-k' это является фатальной ошибкой (смотрите раздел 9.7 [Обзор опций]).

Обычное поведение програмы make предполагает, что вы стремитесь получить обновленные главные цели - как только программа make выясняет, что это невозможно, она также может сразу сообщить о неудаче в своей работе. Опция '-k' указывает на то, что на самом деле программа make используется для проверки как можно большего количества изменений, сделанных в программе, возможно, для поиска нескольких независимых проблем для того, чтобы вы могли исправить их перед следующей попыткой компиляции. Именно поэтому M-x compile, команда редактора Emacs, по умолчанию передает программе make опцию '-k'.

9.7 Обзор опций

Вот список всех опций, которые понимает программа make:

'-b'

'-m'

Эти опции включены для совместимости с другими версиями программы make и они игнорируются.

'-C <каталог>'

'--directory=<каталог>'

Перед чтением make-файлов переходит в каталог, определяемый аргументом <каталог>. Если определены несколько опций '-C', то каждая из них интерпретируется относительно предыдущей: фрагмент командной строки '-C / -C etc' эквивалентен такому фрагменту: '-C /etc'. Это обычно используется при рекурсивных вызовах программы make. (смотрите раздел 5.6 [Рекурсивное использование программы make]).

'-d'

'--debug'

Помимо обычной работы, выводит отладочную информацию. Отладочная

информация говорит о том, какие файлы рассматриваются на предмет

порождения их заново, времена изменения каких файлов

сравниваются и с какими результатами, какие файлы на самом деле

нуждаются в порождении их заново, какие неявные правила

принимаются в расчет и какие из них применяются - все, что имеет

отношение к тому, как программа make решает, что делать.

'-e'

'--environment-overrides'

Дает переменным, взятым из командной среды, приоритет перед переменными из make-файлов. Смотрите раздел 6.9 [Переменные из командной среды].

'-f <имя файла>'

'--file=<имя файла>'

'--makefile=<имя файла>'

Читает в качестве make-файла файл с именем, определяемым аргументом <имя файла>. Смотрите главу 3 [Написание make-файлов].

'-h'

'--help'

Напоминает вам об опциях, которые понимает программа make, после чего заканчивает работу.

'-i'

'--ignore-errors'

Игнорирует все ошибки в командах, выполняемых для порождения файлов заново. Смотрите раздел 5.4 [Ошибки в командах].

'-I <каталог>'

'--include-dir=<каталог>'

Назначает каталог, определяемый аргументом <каталог> для поиска включаемых make-файлов. Смотрите раздел 3.3 [Включение других make-файлов]. Если если используется несколько опций '-I' для определения нескольких каталогов, поиск по каталогам происходит в том порядке, в котором они перечислены.

'-j [<задания>]'

'--jobs=[<задания>]'

Определяет количество заданий (команд), которые будут выполняться одновременно. При отсутствии аргумента, программа make запускает одновременно столько заданий, сколько возможно. Если определена более, чем одна опция '-j', то действует та, которая указана последней в командной строке. Смотрите раздел 5.3 [Параллельное выполнение], для дополнительной информации о том, как выполняются команды.

'-k'

'--keep-going'

Продолжает работу после ошибки как можно дольше. В то время как порождение цели закончилось неудачно, и цели, зависящие от нее, не могут быть заново порождены, другие зависимости этих целей все равно могут быть обработаны. Смотрите раздел 9.6 [Проверка компиляции программ].

'-l [<загрузка>]'

'--load-average[=<загрузка>]'

'--max-load[=<загрузка>]'

Определяет, что ни одно новое задание (команда) не должно стартовать, если есть другие запущенные задания и средняя загрузка не меньше, чем значение, определяемое аргументом <загрузка> (число с плавающей точкой). Отсутствие аргумента отменяет действие предыдущего предела загрузки.

'-n'

'--just-print'

'--dry-run'

'--recon'

Печатает команды, который должны выполняться, но не выполняет их. Смотрите раздел 9.3 [Вместо исполнения команд].

'-o <имя файла>'

'--old-file=<имя файла>'

'--assume-old=<имя файла>'

Не порождает заново файл с именем, определяемым аргументом <имя файла>, даже если он более старый, чем его зависимости, и не порождает заново ничего, что заново порождалось бы в случае изменений в этом файле. По существу, файл обрабатывается как очень старый и его правила игнорируются. Смотрите раздел 9.4 [Предотвращение перекомпиляции некоторых файлов].

'-p'

'--print-data-base'

Выводится на экран базу данных (правила и значения переменных), которая получается в результате чтения make-файлов, а затем выполняется как обычно или каким-либо другим образом, если это определено. При использовании этой опции также выводится на экран информация о версии, которая дается с помощью опции '-v' (смотрите ниже). Чтобы вывести на экран базу данных, не пытаясь породить заново никаких файлов, используйте команду 'make -p -f /dev/null'.

'-q'

'--question'

"Режим запроса". Не выполняет никаких команд и ничего не печатает - просто возвращает результат, который является нулем, если указанные цели уже обновлены, единицей, если требуется какое-либо новое порождение или двойкой, если обнаруживается ошибка. Смотрите раздел 9.3 [Вместо исполнения команд].

'-r'

'--no-builtin-rules'

Отменяет использование встроенных неявных правил (смотрите главу 10 [Использование неявных правил]). Вы можете при этом определить ваши собственные неявные правила путем написания шаблонных правил (смотрите раздел 10.5 [Определение и переопределение шаблонных правил]). Опция '-r' также очищает список суффиксов, по умолчанию используемый для суффиксных правил (смотрите раздел 10.7 [Устаревшие суффиксные правила]). Но вы можете при этом, с помощью правила для цели .SUFFIXES, определить ваши собственные суффиксы и затем определить ваши собственные суффиксные правила.

'-s'

'--silent'

'--quiet'

Работа без сообщений - не выводит на экран команды в момент их исполнения.

'-S'

'--no-keep-going'

'--stop'

Отменяет действие опции '-k'. Эта опция не нужна никогда, за исключением рекурсивного использования программы make, когда опция '-k' может быть унаследована от процесса make верхнего уровня через переменную MAKEFLAGS (смотрите раздел 5.6 [Рекурсивное использование программы make]), а также установки вами в вашей командной среде опции '-k' в переменную MAKEFLAGS.

'-t'

'--touch'

Изменение времени обновления файлов (пометка их как обновленных без реального их изменения) вместо запуска соответствующих им команд. Это используется в целях создания иммитации того, что команды выполнены, для того, чтобы обмануть будущие вызовы программы make. Смотрите раздел 9.3 [Вместо исполнения команд].

'-v'

'--version'

Выводит на экран версию программы make, а также ее copyright, список авторов и замечание об отсутствии гарантии - после этого работа завершается.

'-w'

'--print-directory'

Выводит на экран сообщение, содержащее имя рабочего каталога как перед, так и после выполнения make-файла. Это может быть полезным для отслеживания ошибок из сложным образом вложенных рекурсивных команд make. Смотритие раздел 5.6 [Рекурсивное использование программы make]. (На практике вам редко придется определять эту опцию, так как программа make делает это за вас - смотрите раздел 5.6.4 [Опция '--print-directory']).

'--no-print-directory'

Отменяет вывод на экран имени рабочего каталога, осуществляемый с помощью опции '-w'. Этот способ полезен тогда, когда опция '-w' устанавливается автоматически, но вы не хотите видеть лишних сообщений. Смотрите раздел 5.6.4 [Опция '--print-directory'].

'-W <имя файла>'

'--what-if=<имя файла>'

'--new-file=<имя файла>'

'--assume-new=<имя файла>'

Делает вид, что цель, определяемая аргументом <имя файла>, только что была изменена. При использовании вместе с опцией '-n', эта опция показывает вам, что бы произошло, если бы вам потребовалось изменить этот файл. Без опции '-n', эта опция почти аналогична запуску команды touch для данного файла перед запуском программы make, за исключением того, что время изменения изменяется только в представлении программы make. Смотрите раздел 9.3 [Вместо исполнения команд].

'--warn-undefined-variables'

Порождает предупреждающее сообщение всегда, когда программа make встречает ссылку на неопределенную переменную. Это может быть полезным, когда вы пытаетесь отладить make-файлы, сложными способами использующие переменные.


Вперед Назад Содержание