Основы программирования в Linux
myapp: main:о 2.о 3.omain.о: main.c a.h2.о: 2.с a.h b.h3.o: 3.c b.h c.hСписок свидетельствует о том, что myapp зависит от main.о, 2.o и 3.o, a main.o зависит от main.c и a.h и т. д.
Данный набор зависимостей формирует иерархию, показывающую, как исходные файлы связаны друг с другом. Вы легко можете увидеть, что если изменяется b.h, то придется пересмотреть 2.o и 3.o, а поскольку 2.o и 3.o будут изменены, вам придется перестроить и myapp.
Если вы хотите собрать несколько файлов, можно использовать фиктивную цель или задание
. Предположим, что ваше приложение состоит из двоичного файла myapp и интерактивного руководства myapp.1. Описать их можно следующей строкой:allall: myapp myapp.1И еще раз, если вы не включите задание
, программаallпросто создаст выходной файл, первым найденный в make-файле.makeПравилаВторой, компонент make-файла — правила или инструкции, описывающие способ создания выходного файла задания. В примере из предыдущего раздела какую команду следует применить после того, как команда
определила, что файл 2.o нуждается в перестройке? Возможно, достаточно простого применения командыmake(и как вы увидите в дальнейшем,gcc -с 2.сна самом деле знает много стандартных правил), но что если вы хотите указать каталог include или задать опцию вывода символьной информации для последующей отладки? Сделать это можно, явно определив правила в make-файле.makeПримечаниеВ данный момент мы должны информировать вас об очень странной и неудачной синтаксической записи, применяемой в make-файлах: разнице между пробелом и табуляцией. Все правила должны представлять собой строки, начинающиеся со знака табуляции; пробел не годится. Так как несколько пробелов и табуляция выглядят почти одинаково и поскольку почти во всех других случаях, касающихся программирования в системе Linux, нет большой разницы между пробелами и табуляциями, это может вызвать проблемы. Кроме того, пробел в конце строки в make-файле может вызвать сбой при выполнении команды
. Тем не менее, это исторический факт и в наше время слишком много make-файлов находится в обращении, чтобы можно было рассчитывать на изменение положения вещей, поэтому будьте внимательны! К счастью, если командаmakeне работает из-за пропущенной табуляции, это обычно довольно понятно.makeА теперь выполните упражнение 9.1.
Упражнение 9.1. Простой make-файлБольшинство правил или инструкций состоит из простой команды, которая могла бы быть набрана в командной строке. Для примера создайте свой первый make-файл Makefile1:
myapp: main.о 2.o 3.ogcc -о myapp main.о 2.o 3.omain.о: main.c a.hgcc -с main.c2.о: 2.с a.h b.hgcc -с 2.с3.o: 3.c b.h c.hgcc -с 3.cЗапустите команду
с опциейmake, потому что ваш make-файл не назван одним из стандартных имен makefile или Makefile. Если запустить приведенный код в каталоге, не содержащем исходных файлов, будет получено следующее сообщение:-f$ <b>make -f Makefile1</b>make: *** No rule to make target 'main.c', needed by 'main.o'. Stop.$Команда
предположила, что первое задание в make-файле,make, — это файл, который вы хотите создать. Затем она просмотрела остальные зависимости и прежде всего определила, что нужен файл, названный main.c. Поскольку вы все еще не создали этот файл и в make-файле не сказано, как он может быть создан, командаmyappвывела сообщение об ошибке. Итак, создайте исходные файлы и попробуйте снова. Поскольку результат нас не интересует, эти файлы могут быть очень простыми. Заголовочные файлы на самом деле пустые, поэтому вы можете создать их командойmake:touch$ <b>touch a.h</b>$ <b>touch b.h</b>$ <b>touch c.h</b>Файл main.c содержит функцию
, вызывающую функцииmainиfunction_two. В других двух файлах определены функцииfunction_threeиfunction_two. В исходных файлах есть строкиfunction_threeдля соответствующих заголовочных файлов, поэтому они оказываются зависимыми от содержимого включенных файлов заголовков. Это приложение не назовешь выдающимся, но, тем не менее, далее приведены листинги программ:#include/* main.c */#include <stdlib.h>#include "a.h"extern void function_two();extern void function_three();int main() {function_two();function_three();exit(EXIT_SUCCESS);}/* 2.c */#include "a.h"#include "b.h"void function_two() { }/* 3.с */#include "b.h"#include "c.h"void function_three() { }Теперь попробуйте выполнить команду make еще раз:
$ <b>make -f Makefile1</b>gcc -с main.с gcc -с 2.сgcc -с 3.сgcc -о myapp main.о 2.о 3.о$На этот раз сборка прошла успешно.
Как это работает
Команда
обработала секцию зависимостей make-файла и определила файлы, которые нужно создать, и порядок их создания. Хотя вы сначала описали, как создать файл myapp, командаmakeопределила правильный порядок создания файлов. Затем она запустила соответствующие команды для создания этих файлов, приведенные вами в секции правил. Командаmakeвыводит на экран выполняемые ею команды. Теперь вы можете протестировать ваш make-файл, чтобы увидеть, корректно ли он обрабатывает изменения в файле b.h:make