впат не подбирает вновь построенные объекты - PullRequest
0 голосов
/ 13 марта 2020

У меня есть этот Makefile (и GNU Make):

vpath %.o .objs

OBJDIR=.objs

all: symbol_tests.so

symbol_tests.so: symbol_tests.o symbol.o   # simulate linking
    @echo Linking target: $@, prerequisites: $^

%.o: %.c | $(OBJDIR)/
    gcc -o $(OBJDIR)/$@ -c $<

$(OBJDIR)/:
    -mkdir $@

, но сборка (без каких-либо подкаталогов или объектов) дает мне это:

mkdir .objs/
gcc -o .objs/symbol_tests.o -c symbol_tests.c
gcc -o .objs/symbol.o -c symbol.c
Linking target: symbol_tests.so, prerequisites: symbol_tests.o symbol.o

Очевидно, что с ни symbol.o, ни symbol_test.o не существует, их нужно строить. И они правильно помещаются в подкаталог ./objs.

Но при «связывании» vpath не подхватывает вновь созданные .o -файлы в подкаталоге .objs.

Разве это не странно? Запуск make снова дает:

Linking target: symbol_tests.so, prerequisites: .objs/symbol_tests.o .objs/symbol.o

Мне кажется, что для запуска поиска .o в подкаталоге они должны существовать при вызове make. Такого рода поражение цели vpath не так ли?

Или что-то не так с моим Makefile или пониманием vpath?

ПРИМЕЧАНИЕ: наличие $ ( OBJDIR) в директиве vpath не работает. Почему?

1 Ответ

1 голос
/ 14 марта 2020

Не похоже, что это будет работать ни для GNU Make, ни для любой другой марки, которую я пробовал.

Я думаю, vpath и $(VPATH) [и для BSD Make .PATH:] только действительно эффективен для оригинальных источников (т. е. файлов, которые существуют до вызова Make, но не для каких-либо промежуточных целей.

В частности, обратите внимание на следующее предостережение из руководства GNU Autoconf:

Использование $ <в явных правилах не является переносимым. Предварительно необходимый файл должен быть явно указан в правиле. Если вы хотите найти предварительное условие с помощью поиска VPATH, вам нужно кодировать все это вручную. </p>

См. больше предостережений в разделе руководства Gnu Autoconf 12.14 VPATH и Make .

Конечно, вы можете обмануть его, выполнив последний шаг ссылки в рекурсивном вызове make, но это кажется расточительным особенно если вы делаете это для множества целей.

BSD Make управляет созданием каталогов объектов, автоматически изменяя текущий рабочий каталог на каталог объектов и затем явный поиск источников через переменную ${.CURDIR} - место, где был впервые вызван make.

GNU Make, к сожалению, только устанавливает свои $(CURDIR) после того, как обрабатывает -C параметров , Кажется, что предпочтительный способ работы GNU Make (особенно в сочетании с другими инструментами GNU Autotools) - это использование отдельного каталога сборки для процесса Make. Т.е. создайте отдельный пустой каталог для сборки и начните с запуска сценария configure там с относительным путем к каталогу сборки:

mkdir build
cd build
../configure

Это создаст все необходимые Makefiles в каталоге сборки и Затем вы можете просто запустить Make в каталоге сборки:

gmake

Это, конечно, самый безопасный способ гарантировать, что в исходных каталогах не будет создано никаких целей (промежуточных или иных).

Вы также можете избежать vpath и напрямую добавить каталог объекта к каждому имени цели объекта, как в этом ответе: { ссылка }

...