использования последовательности john paul johnpaul
на выражения, использующие SOURCES
.
SOURCES = john.cpp paul.cpp johnpaul.cpp
...
# Собираем libjohnpaul.a из john.о, paul.o и johnpaul.о
$(OUTPUTFILE): $(subst .cpp, .o,$(SOURCES))
ar ru $@ $^
ranlib $@
...
# Генерируем зависимости .cpp-файлов от .hpp-файлов
include $(subst .cpp,.d,$(SOURCES))
%d: %.cpp
$(CC) -M $(CPPFLAGS) $< > $@.$$$$;
sed 's,($*).o[ :]*.1.o $@ : .g' < $@ $$$$ > $@;
rm -f $@.$$$$
Здесь я использую функцию $(subst
, которая заменяет в строке
все вхождения
на
.
GNU make поддерживает большое количество функций обработки строк и имен файлов, а также много других. Также она поддерживает определение пользовательских функций. Как обычно, за подробным описанием обратитесь к
Рецепты 1.2 и 1.7.
1.17. Сборка динамической библиотеки с помощью GNU Make
Вы хотите использовать GNU
Вначале в директории, где должна быть создана динамическая библиотека, создайте make-файл и объявите фиктивную цель
all, единственным пререквизитом которой будет эта динамическая библиотека. Затем объявите цель динамической библиотеки. Ее пререквизитами должны быть объектные файлы, из которых она собирается, а ее командный сценарий должен представлять собой командную строку для сборки библиотеки из набора объектных файлов, аналогично показанному в рецепте 1.4. При использовании GCC или компилятора с похожим синтаксисом командной строки настройте, если требуется, неявные правила шаблонов, изменив одну или более переменных CXX
, CXXFLAGS
и т.п., используемых в базе данных неявных правил install
и clean
, как показано в рецепте 1.15, и механизм для автоматической генерации зависимостей исходных файлов, как показано в рецепте 1.16.
Например, чтобы из исходных файлов, перечисленных в примере 1.2, собрать динамическую библиотеку с помощью GCC в Unix, в директории
# Укажите расширения файлов, удаляемых при очистке
CLEANEXTS = o so
# Укажите исходные файлы, целевой файл и директорию установки
SOURCES = george.cpp ringo.cpp georgeringo.cpp
OUTPUTFILE = libgeorgeringo.so
INSTALLDIR = ../binaries
.PHONY: all
all: $(OUTPUTFILE)
# Соберите libgeorgeringo.so из george.o, ringo.о
# и georgeringo.o; subst - это функция поиска и замены.
# показанная в рецепте 1.16
$(OUTPUTFILE): $(subst .cpp,.o,$(SOURCES))
$(CXX) -shared -fPIC $(LDFLAGS) -о
.PHONY: install
install:
mkdir -p $(INSTALLDIR)
cp -p $(OUTPUTFILE) $(INSTALLDIR)
.PHONY: clean
clean:
for file in $(CLEANEXTS); do rm -f *.$$file; done
# Сгенерируйте зависимости файлов .cpp от файлов .hpp
include $(subst .cpp,.d,$(SOURCES))
%.d: %.cpp
$(CC) -M $(CPPFLAGS) $< > $@.$$$$;
sed 's. ($*).o[ :]*.1.o $@ : ,g' < $@.$$$$ > $@;
rm -f $@.$$$$
make-файл из примера 1.22 — это прямое применение идей из рецептов 1.4, 1.15 и 1.16. Главным отличием между примерами 1.22 и 1.20 является правило для сборки
$(OUTPUTFILE): $(subst .cpp,.o,$(SOURCES))
$(CXX) -shared -fPIC $(LDFLAGS) -о $@ $^
Здесь $(OUTPUTFILE)
раскрывается как libgeorgeringo.so
, а выражение $(subst.cpp, .o, $(SOURCES))
раскрывается как george.о
, ringo.о
и georgeringo.o
, как показано в рецепте 1.16. Командный сценарий $(CXX) -shared -fPIC $(LDFLAGS) -о
— это адаптация командной строки GCC, показанной в табл. 1.11.