Задание installзависит от myapp, поэтому команда makeзнает, что должна создать myapp перед выполнением других команд задания install. Правила выполнения installсостоят из нескольких команд сценария командной оболочки. Поскольку команда makeзапускает командную оболочку для выполнения правил и применяет новую командную оболочку для каждого правила, следует добавлять обратные слэши, чтобы все команды сценария были в одной логической строке и передавались для выполнения все вместе одному сеансу командной оболочки. Эта команда начинается со знака отменяющего вывод команды в стандартный файл вывода перед выполнением правила.
Задание installвыполняет несколько команд одну за другой для установки приложения в указанное расположение. Оно не проверяет успешность выполнения предыдущей команды перед выполнением следующей. Если очень важно, чтобы последующие команды выполнялись только в случае успешного завершения предыдущей, можно написать команды, объединенные с помощью операции &&,как показано далее:
@if [ -d $(INSTDIR) ]; \
then \
cp myapp $(INSTDIR) &&\
chmod a+x $(INSTDIR)/myapp && \
chmod og-w $(INSTDIR/myapp && \
echo "Installed in $(INSTDIR)" ; \
else \
echo "Sorry, $(INSTDIR) does not exist"; false ; \
fi
Как вы, вероятно, помните из главы 2, у командной оболочки есть команда and, благодаря которой выполнение последующей команды возможно лишь при успешном завершении предыдущей. В данном примере вас не слишком заботит успешное завершение предыдущих команд, поэтому можно придерживаться более простой формы.
Если вы — обычный пользователь, то у вас может не быть прав на установку новых команд в каталог /usr/local/bin. Можно изменить в make-файле каталог установки, изменить права доступа к этому каталогу или заменить пользователя (с помощью команды su) на root перед запуском make install.
$ rm *.о myapp
$ make -f Makefile3
gcc -I. -g -Wall -ansi -c main.c
gcc -I. -g -Wall -ansi -c 2.c
gcc -I. -g -Wall -ansi -с 3.c
gcc -o myapp main.о 2.o 3.o
$ make -f Makefile3
make: Nothing to be done for 'all'.
$ rm myapp
$ make -f Makefile3 install
gcc -o myapp main.o 2.o 3.o
Installed in /usr/local/bin
$ make -f Makefile3 clean
rm main.о 2.о 3.о
$
Как это работает
Сначала вы удаляете файл myapp и все объектные файлы. Команда makeсамостоятельно выбирает задание all, которое приводит к сборке myapp. Затем вы снова запускаете команду make, но т.к. у файла myapp свежая версия, makeне делает ничего. Далее вы удаляете файл myapp и выполняете make install. Эта команда создает заново двоичный файл и копирует его в каталог установки. В заключение выполняется команда make clean, удаляющая объектные файлы.
До сих пор вы описывали в make-файле подробно, как выполнять каждый шаг. В действительности у команды makeесть много встроенных правил, которые существенно упрощают make-файлы, особенно если у вас много исходных файлов. Для того чтобы проверить это, создайте традиционную программу, приветствующую мир:
#include
#include
int main() {
printf("Hello World\n");
exit(EXIT_SUCCESS);
}
He задавая make-файла, попробуйте откомпилировать ее с помощью команды make:
$ make foo
сс foo.с -о foo
$
Как видите, makeзнает, как запустить компилятор, хотя в данном случае она выбирает ссвместо gcc(в ОС Linux это нормально, потому что cc— обычно ссылка на gcc). Иногда эти встроенные правила называют подразумеваемыми правилами. Стандартные правила используют макросы, поэтому задавая некоторые новые значения для макросов, вы можете изменить стандартное поведение.
$ rm foo
$ make CC=gcc CFLAGS="-Wall -g" foo
gcc -Wall -g foo.с -o foo
$
С помощью опции -pможно попросить команду makeвывести на экран встроенные правила. Их так много, что мы не можем привести в книге все встроенные правила, ограничимся коротким фрагментом вывода команды make -pверсии GNU, демонстрирующим часть этих правил:
OUTPUT_OPTION = -o $@
COMPILE.с = $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -с
%.о: %.с
# commands to execute (built-in) :
$(COMPILE.с) $(OUTPUT_OPTION) $<
Теперь, принимая во внимание описанные встроенные правила, вы можете упростить ваш make-файл, удалив правила для создания объектных файлов и оставив только зависимости, таким образом, соответствующая секция make-файла читается просто:
Читать дальше