Основы программирования в Linux
a - 2.ogcc -g -Wall -ansi -с -о 3.o 3.car rv mylib.a 3.oa - 3.оgcc -o myapp main.о mylib.a$ <b>touch c.h</b>$ <b>make -f Makefile5</b>gcc -g -Wall -ansi -с -о 3.o 3.car rv mylib.a 3.or - 3.оgcc -o myapp main.о mylib.a$Как это работает
Сначала вы удаляете все объектные файлы и библиотеку и разрешаете команде
создать файл myapp, что она и делает, откомпилировав и создав библиотеку перед тем, как компоновать файл main.о с библиотекой для создания исполняемого файла myapp. Далее вы тестируете зависимость для файла 3.o, которая информирует командуmakeо том, что, если меняется файл c.h, файл 3.c следует заново откомпилировать. Она делает это корректно, откомпилировав файл и обновив библиотеку перед перекомпоновкой, создающей новую версию исполняемого файла myapp.makeБолее сложная тема: make-файлы и подкаталоги
При работе над большими проектами порой бывает удобно отделить от основных файлов файлы, формирующие библиотеку, и поместить их в подкаталог. С помощью команды
можно сделать это двумя способами.makeВо-первых, можно создать в подкаталоге второй make-файл для компиляции файлов, сохранения их в библиотеке и последующего копирования библиотеки на уровень вверх, в основной каталог. При этом в основном make-файле, хранящемся в каталоге более высокого уровня, есть правило формирования библиотеки, в котором описан запуск второго make-файла следующим образом:
mylib.a:(cd mylibdirectory;$(MAKE))Это правило гласит, что вы всегда должны пытаться создать mylib.a с помощью команды
. Когдаmakeинициирует правило создания библиотеки, она изменяет каталог на mylibdirectory и затем запускает новую командуmakeдля управления библиотекой. Поскольку для этого запускается новая командная оболочка, программа, применяющая make-файл, не выполняет командуmake. А командная оболочка, запущенная для выполнения правила построения библиотеки, находится в другом каталоге. Скобки обеспечивают выполнение всего процесса в одной командной оболочке.cdВторой способ заключается в применении нескольких макросов в одном make-файле. Дополнительные макросы генерируются добавлением символа
для каталога или символаDдля имени файла к тем макросам, которые мы уже обсуждали. Вы можете переписать встроенное правило с суффиксами .с.оF.c.o:$(СС) $(CFLAGS) -с $(@D)/$(<F) -о $(@D)/$(@F)для компиляции файлов в подкаталоге и сохранения в нем объектных файлов. Затем вы обновляете библиотеку в текущем каталоге с помощью зависимости и правила, наподобие приведенных далее:
mylib.a: mydir/2.o mydir/3.оar -rv mylib.a $?Вы должны решить, какой из способов предпочтительнее в вашем проекте. Многие проекты просто избегают применения подкаталогов, но это может привести к непомерному разрастанию исходного каталога. Как видно из только что приведенного краткого обзора, команду
можно использовать с подкаталогами и сложность возрастает при этом лишь незначительно.makeВерсия GNU команд make и gcc
Для GNU-команды
и GNU-компилятораmakeсуществуют две интересные дополнительные опции.gcc□ Первая — опция
("jobs") команды-j<i>N</i>. Она позволяетmakeвыполнятьmakeкоманд одновременно. Там, где несколько разных частей проекта могут компилироваться независимо, команда<i>N</i>запускает несколько правил в одно и то же время. В зависимости от конфигурации вашей системы эта возможность может существенно сократить время, затраченное на перекомпиляцию. Если у вас много исходных файлов, может быть стоит воспользоваться этой опцией. Как правило, небольшие числа, напримерmake, — хорошая отправная точка. Если вы делите компьютер с другими пользователями, применяйте эту опцию с осторожностью. Другие пользователи могут не одобрить запуск большого количества процессов при каждой вашей компиляции!-j3□ Второе полезное дополнение — опция
для-MM. Она формирует список зависимостей в форме, подходящей для командыgcc. В проекте со значительным числом исходных файлов, каждый из которых содержит разные комбинации заголовочных файлов, бывает трудно (но крайне важно) корректно определить зависимости. Если сделать каждый исходный файл зависимым от всех заголовочных файлов, иногда вы будете компилировать файлы напрасно. С другой стороны, если вы пропустите какие-то зависимости, возникнет еще более серьезная проблема, поскольку в этом случае вы не откомпилируете заново те файлы, которые нуждаются в перекомпиляции.makeВыполните упражнение 9.5.
Упражнение 9.5. Использованиеgcc -MMВ этом упражнении вы примените опцию
в программе-MMдля генерации списка зависимостей вашего примера:gcc$ <b>gcc -MM main.с 2.с 3.с</b>main.о: main.c a.h2.о: 2.с a.h b.h3.o: 3.с b.h c.h$Как это работает
Компилятор
просто просматривает исходные файлы, ищет заголовочные файлы и выводит требующиеся строки зависимостей в формате, готовом к вставке в make- файл. Вы должны лишь сохранить вывод во временном файле и затем вставить его в make-файл, чтобы иметь безошибочный набор зависимостей. Если вы пользуетесь копией, полученной отgcc, для появления ошибок в ваших зависимостях просто нет оснований!gccЕсли вы хорошо знакомы с make-файлами, можно попробовать применить средство
, которое выполняет функцию, аналогичную опцииmakedepend, но вставляет полученный список зависимостей в конец реального заданного вами make-файла.-MMПеред завершением темы make-файлов, быть может, стоит подчеркнуть, что не следует ограничивать применение make-файлов только компиляцией кода и созданием библиотек. Их можно использовать для автоматизации любой задачи, в которой есть последовательность команд, формирующих из входного файла некоторого типа выходной файл. Типичным "некомпиляционным" применением может быть вызов программ
, илиawkдля обработки некоторых файлов или генерация интерактивного справочного руководства. Вы можете автоматизировать практически любую обработку файлов, если на основании информации о дате и времени модификации файла можете определить, какие из файлов были изменены.sed