Ответ состоит в том, что промежуточные переменные, такие как
$(CXX)
,
$(CXXFLAGS)
,
$(CPPFLAGS)
и
$(LDFLAGS)
, служат как точки настройки (customization points). Например, указав значение
LDFLAGS
в командной строке, в make-файле или установив значение переменной среды, можно указать дополнительные флаги, передаваемые компоновщику. Переменные
CPPFLAGS
и
CXXFLAGS
играют схожую роль для опций препроцессора и компилятора C++ соответственно. А установив значение переменной
CXX
, можно указать компилятор,
отличный от GCC. Например, чтобы собрать hello с помощью Intel для Linux и используя make-файл из примера 1.18, вы должны в командной строке ввести
make CXX=icpc
, предполагая, что переменные среды, необходимые для компилятора Intel, уже установлены.
VPATH и директива vpath
В примере 1.18 make может применить правильное шаблонное правило, потому что файл .cpp находится в той же директории, в которой создается выходной файл. Если исходные файлы находятся в другой директории, то для указания make, где искать цели или пререквизиты, используется переменная
VPATH
.
VPATH = <путь-к-файлам-cpp>
Чтобы сказать make, что выполнять поиск определенных типов файлов требуется в определенном месте, используйте директиву
vpath
.
# искать файлы .exp в ../lib
vpath %. exp../lib
Смотри также
Рецепты 1.2 и 1.7.
1.16. Сборка статической библиотеки с помощью GNU Make
Проблема
Вы хотите использовать GNU make для сборки статической библиотеки из набора исходных файлов C++, таких как перечисленные в примере 1.1.
Решение
Вначале в директории, где должна быть создана статическая библиотека, создайте make-файл и объявите фиктивную цель
all
, единственным пререквизитом которой будет статическая библиотека. Затем объявите цель статической библиотеки. Ее пререквизитами должны быть объектные файлы, входящие в состав библиотеки, а ее командный сценарий должен представлять собой командную строку для сборки библиотеки из набора объектных файлов, аналогично показанному в рецепте 1.3. При использовании GCC или компилятора с похожим синтаксисом командной строки настройте, если требуется, неявные правила шаблонов, изменив одну или более переменных
CXX
,
CXXFLAGS
и т.п., используемых в базе данных неявных правил make, как показано в рецепте 1.15. В противном случае, используя синтаксис шаблонных правил, описанный в рецепте 1.16, напишите шаблонное правило, говорящее make, как с помощью командной строки из табл. 1.8 компилировать .cpp– файлы в объектные. Далее явно или неявно объявите цели, указывающие, как каждый из исходных файлов библиотеки зависит от включаемых в него заголовков. Эти зависимости можно описать вручную или сгенерировать их автоматически. Наконец, добавьте цели
install
и
clean
, как показано в рецепте 1.15.
Например, чтобы с помощью GCC в Unix собрать из исходных файлов, перечисленных в примере 1.2, статическую библиотеку, создайте в директории johnpaul make-файл, показанный в примере 1.20.
Пример 1 20. make-файл для создания libjohnpaul.a с помощью GCC в Unix
# Укажите расширения файлов, удаляемых при очистке
CLEANEXTS - о а
# Укажите целевой файл и директорию установки
OUTPUTFILE = libjohnpaul.a
INSTALLDIR = ../binaries
# Цель по умолчанию
.PHONY: all
all: $(OUTPUTFILE)
#
Соберите libjohnpaul.a из john.o. paul.o и johnpaul.с
$(OUTPUTFILE): john.o paul.o johnpaul.о
ar ru $@ $^
ranlib $@
# Для сборки john.o, paul.o и johnpaul.о из файлов .cpp
# правила не требуются; этот процесс обрабатывается базой данных
# неявных правил make
.PHONY: install
install:
mkdir -p $(INSTALLDIR)
cp -p $(OUTPUTFILE) $(INSTALLDIR)
.PHONY: clean
clean:
for file in $(CLEANEXTS); do rm -f *.$$file; done
# Укажите зависимости файлов cpp от файлов .hpp
john.o: john.hpp
paul.o: paul.hpp
johnpaul.o: john.hpp paul.hpp johnpaul.hpp
Аналогично, чтобы собрать статическую библиотеку с помощью Visual С++, ваш make-файл должен выглядеть, как показано в примере 1.21.
Пример 1.21. make-файл для создания libjohnpaul.lib с помощью Visual C++
# Укажите расширения файлов, удаляемых при очистке
CLEANEXTS = obj lib
# Specify the target file and the install directory
OUTPUTFILE = libjohnpaul.lib
INSTALLDIR = ./binaries
# Шаблонное правило для сборки объектного файла из файла .cpp
# Соберите libjohnpaul.lib из john.obj, paul.obj и johnpaul.obj
$(OUTPUTFILE): john.obj paul.obj johnpaul.obj
"$(MSVCDIR)/bin/link" -lib -nologo -out:"$@" $^
.PHONY: install
install:
mkdir -p $(INSTALLDIR)
cp -p $(OUTPUTFILE) $(INSTALLDIR)
.PHONY: clean
clean:
for file in $(CLEANEXTS); do rm -f *.$$file; done
# Укажите зависимости файлов .cpp от файлов .hpp
john.obj: john.hpp
paul.obj: paul.hpp
johnpaul.obj: john.hpp paul.hpp johnpaul.hpp
В примере 1.21 я с помощью переменной среды MSVCDIR, устанавливаемой в vcvars32.bat, показал команду Visual C++ link.exe как
"$(MSVCDIR)/bin/link"
. Это позволяет избежать путаницы между компоновщиком Visual C++ и командой Unix link, поддерживаемой Cygwin и MSYS. Для полноты картины я также использовал MSVCDIR для команды компиляции Visual С++.