.PHONY all
all: $(OUTPUTFILE)
# Собрать hello из hello.cpp
$(OUTPUTFILE) hello.cpp
g++ -o $@ $<
# Цели Install и clean как в примере 1 16
В командном сценарии g++ -o $@ $< переменная $@ раскрывается как hello, а переменная $< раскрывается как hello.cpp. Следовательно, make-файл из примера 1.17 эквивалентен файлу из примера 1.16, но содержит меньше дублирующегося кода.
make-файл в примере 1.17 может быть еще проще. На самом деле командный сценарий, связанный с целью hello, избыточен, что демонстрируется выполнением make-файла из примера 1.18.
# Указываем целевой файл и директорию установки
OUTPUTFILE=hello
INSTALLDIR=binaries
# Цель по умолчанию
.PHONY: all
all: $(OUTPUTFILE)
# Говорим make пересобрать hello тогда, когда изменяется hello.cpp
$(OUTPUTFILE): hello.cpp
# Цели Install и clean как в примере 1.16
Откуда make знает, как собирать исполняемый файл
%: %.cpp
# исполняемые команды (встроенные):
$(LINK.cpp) $(LOADLIBS) $(LDLIBS) -о $@
Правила, первые строки которых имеют вид %, известны как % действует как
Чтобы напечатать базу данных неявных правил GNU
Например, при первом выполнении make-файла из примера 1.18 пререквизит hello цели по умолчанию all является устаревшим. Хотя hello фигурирует как цель правила $(OUTPUTFILE): hello.cpp, это правило не содержит командного сценария, и, таким образом, оно бесполезно для сборки файла hello. Следовательно, make выполняет поиск в своей внутренней базе данных и находит правило, показанное в примере 1.19. Подставляя в правило из примера 1.19 вместо подстановочного знака строку hello, hello в качестве цели.
hello: hello.cpp
$(LINK.cpp) $(LOADLIBS) $(LDLIBS) -o $@
Пока все хорошо, но есть еще кое-что. Повторный взгляд на внутреннюю базу данных LINK.cpp по умолчанию раскрывается как $(LINK.cc). В свою очередь LINK.cc по умолчанию раскрывается как
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)
Наконец, переменная CXX по умолчанию раскрывается как g++, а четыре другие переменные — $(CXXFLAGS), $(CPPFLAGS), $(LDFLAGS) и $(TARGET_ARCH) — раскрываются как пустые строки. После выполнения всех этих подстановок получается следующее правило, которое теперь выглядит более знакомо.
hello: hello.cpp
g++ $^ -o $@
Запутались? Это не страшно. Если вы изучите приведенное объяснение и потратите некоторое время на изучение внутренней базы данных
Теперь, когда вы увидели, как шаблонное правило из примера 1.19 приводит к тому, что
%: %.cpp
g++ $^ -о $@
Ответ состоит в том, что промежуточные переменные, такие как $(CXX), $(CXXFLAGS), $(CPPFLAGS) и $(LDFLAGS), служат как точки настройки (customization points). Например, указав значение LDFLAGS в командной строке, в make-файле или установив значение переменной среды, можно указать дополнительные флаги, передаваемые компоновщику. Переменные CPPFLAGS и CXXFLAGS играют схожую роль для опций препроцессора и компилятора C++ соответственно. А установив значение переменной CXX, можно указать компилятор, отличный от GCC. Например, чтобы собрать make CXX=icpc, предполагая, что переменные среды, необходимые для компилятора Intel, уже установлены.
