#c #makefile
#c #makefile
Вопрос:
У меня есть Makefile для компиляции некоторых исходных файлов C, и я помещаю выходные данные в другой каталог сборки, он немного похож на приведенный ниже makefile:
OBJDIR=/home/test/alpha
SRCDIR=/home/test/beta
# make variable will be exanded when used (and not at declaration)
OBJECTS:= $(addprefix $(OBJDIR), $(notdir $(patsubst %.c,%.o,$(wildcard $(SRCDIR)/*.c))))
SOURCES:=$(wildcard $(SRCDIR)/*.c))
.PHONY: copySourcesOver linkSources sharedLibrary
copySourcesOver: $(SOURCES)
cp $(SOURCES) $(OBJDIR)/
# pattern
$(OBJECTS)/%.o : $(OBJECTS)/%.c
gcc -fPIC $< -o $@
linkSources: $(OBJECTS)
gcc -shared -o libshared.so $@
sharedLibrary: copySourcesOver
linkSources
Итак, что происходит, когда я запускаю целевой:
make sharedLibrary
Я не получаю правила для создания $(OBJECTS)
. Интересная часть заключается в том, что когда я создаю эту цель во второй раз, я не получаю эту ошибку makefile, и я получаю разделяемую библиотеку.
Я провел небольшое исследование и выяснил, что Makefile не расширяет неявные правила для ПОДДЕЛЬНЫХ целей, вот почему я сменил linkSources
НЕЯВНУЮ цель на обычный файл. Но, к сожалению, это не решает проблему.
Я не понимаю, почему шаблон выполняется только при втором запуске make sharedLibrary
Комментарии:
1. Помимо того, на что указывает приведенный ниже ответ, ваш makefile также сломается, если вы используете более одного задания (
-j
); нет гарантии, что предварительные условия выполняются по порядку, если одно предварительное условие зависит от другого, то выразите это в makefile .2. Хороший момент. Я добавлю все зависимости
3. Некоторые из ваших правил не указывают свои цели как targets или свои зависимости как dependencies, поэтому
make
нельзя ожидать, что проверка того, должно ли выполняться правило, будет работать корректно.
Ответ №1:
Make выполняется в 2 этапа. На первом этапе проверяется, какие целевые объекты устарели и нуждаются в обновлении. На втором этапе он выполняет команды, которые обновляют целевые объекты. Это означает, что он проверяет актуальность объектных файлов, прежде чем фактически скопировать исходные файлы.
Таким образом, он проверяет и определяет, что объектные файлы обновлены, затем копирует (обновленные) исходные файлы в $(OBJDIR)
.
В документах есть хорошее чтение на эту тему.
Комментарии:
1. Итак, что я могу заключить после прочтения документации, так это то, что: OBJDIR =/home/test/alpha и SRCDIR =/ home / test / beta их правая сторона будет иметь отложенное расширение . $(OBJECTS) не расширяется при первом запуске makefile, только при втором
2. Ключевая информация находится внизу,
Rule definition
. ПравилоsharedLibrary : copySourcesOver linkSources
проверяется немедленно. Проверка наlinkSources
не приведет ни к какому действию, поскольку файлы обновлены (помните, что обновленные файлы еще не были скопированы), в то время как проверка наcopySourcesOver
приведет к копированию любых обновленных исходных файлов.
Ответ №2:
Цитата:
# pattern
$(OBJECTS)/%.o : $(OBJECTS)/%.c
gcc -fPIC $< -o $@
Это правило бессмысленно, поскольку OBJECTS
это переменная, содержащая несколько слов, а не один компонент path; более того, .c
источники находятся не в том же каталоге, что и объекты (в этом весь смысл).
Я подозреваю, что вы хотите:
$(OBJDIR)/%.o : $(SRCDIR)/%.c
Шаблон слева соответствует любому из шаблонов объектных файлов, которые вы рассчитали в OBJECTS
, переписав их $(SRCDIR)
часть в $(OBJDIR)
.
Кстати, видите, как это шаблонное правило легко выполняет обратную перезапись? Совпадение слева преобразуется в .c
предварительное условие справа. Видите, как правило не использует notdir
or addprefix
? Вы могли бы сделать то же самое (в обратном порядке) при вычислении OBJECTS
. Отбросьте notdir
и addprefix
и преобразуйте каждый путь одним patsubst
.
Кроме того, я бы исключил повторяющееся wildcard
. SOURCES
Сначала получите, а затем вычислите OBJECTS
из исходных текстов.
Наконец, как это будет работать при новой проверке, когда каталог объектов не существует? Вам нужно немного mkdir -p
туда. gcc ... -o foo/bar.o
не создаст foo
каталог.
Комментарии:
1. Первый целевой copySourcesOver копирует исходные файлы в каталог объектов. Да, я согласен, я изменил его на правило статического шаблона, $ (OBJECTS):%.o:%.c
2. Может ли ваш Makefile когда-либо запускаться в ситуации, когда каталог objects вообще не существует?
3. Один вопрос, пожалуйста, что такое обратная перезапись?
4. «Обратная перезапись» противоположна тому, что делает правило: правило сопоставляет шаблон .o слева с целевым, а затем переписывает его с предварительным условием .c справа. Это обратное по отношению к тому, что вы сделали для вычисления . o ОБЪЕКТЫ из исходных текстов. В основном выполняется шаблонное правило
patsubst(leftpat, rightpat, target)
.5. Нет, в этом случае каталог объектов уже существует, это переменная makefile OBJDIR . Я понимаю вашу точку зрения, я бы сделал то же самое в другом diff