Генерация правил сборки файлов GNU - PullRequest
0 голосов
/ 10 февраля 2019

Так что в моем проекте у меня есть каталог src и каталог obj.Я рекурсивно нахожу файлы .c и .cpp в моем каталоге src, а затем соответствующий файл .o помещается прямо в каталог obj.Например, если у меня есть файл .cpp: src/dir1/dir2/file.cpp, соответствующий ему файл .o будет obj/file.o.Затем я создаю правило для получения файла .o из файла .cpp, используя функцию make foreach , используя этот код:

rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2)$(filter $(subst *,%,$2),$d))
src = $(call rwildcard,src/,*.cpp *.c)
obj = $(patsubst %,obj/%.o,$(basename $(notdir $(src))))

$(info src: [$(src)])
$(info obj: [$(obj)])

game.exe: $(obj)
    g++ $^ -o $@

define objFromSrc
$(1): $(2)
    $(info $(1) $(2))
    g++ -c $(2) -o $(1)
endef

$(foreach t,$(src),$(call objFromSrc,$(patsubst %,obj/%.o,$(basename $(notdir $(t)))),$(t)))

Вот вывод для некоторых файлов примеров:

src: [src/dir/main.cpp src/dir/dir2/other3.cpp src/dir/other2.cpp src/other.c]
obj: [obj/main.o obj/other3.o obj/other2.o obj/other.o]
obj/main.o src/dir/main.cpp
obj/other3.o src/dir/dir2/other3.cpp
obj/other2.o src/dir/other2.cpp
obj/other.o src/other.c
makefile:20: *** multiple target patterns.  Stop.

Вы видите, что переменная obj правильно содержит соответствующие имена файлов .o.И функция objFromSrc генерирует правило, в котором цель и зависимость верны, но все же я получаю ошибку множественных шаблонов цели.

Почему я получаю эту ошибку и как ее исправить?

Ответы [ 2 ]

0 голосов
/ 10 февраля 2019

Вам не хватает $(eval) для анализа сгенерированного кода make-файла:

$(eval $(foreach t,$(src),...))

Я бы также предложил добавить пустую строку в конце многострочного define.Выход из этого обычно вызывает проблемы при $(eval) использовании динамически сгенерированного кода make-файла.

define objFromSrc
$(1): $(2)
    $(info $(1) $(2))
    g++ -c $(2) -o $(1)

endef

$(info eval $(foreach t,$(src),...))

КОД БОНУСА: Ваш рецепт является константой, поэтому нет необходимостивоссоздать его для каждого правила.Вместо этого используйте правило статического шаблона для $(obj):

.DEFAULT_GOAL := game.exe

obj :=
define objFromSrc
$(1): $(2)
obj += $(1)

endef

$(eval $(foreach t,$(src),...))

$(info obj: [$(obj)])

$(obj): %.o:
    g++ -o $@ -c $<

game.exe: $(obj)
    g++ $^ -o $@
0 голосов
/ 10 февраля 2019

Почему я получаю эту ошибку и как ее исправить?

Все эти define и $(call ...) в make создают простые строки ,Вы должны оценить его, чтобы make сделал то, что вы приказали (т.е. чтобы создать правило $1 : $2):

$(foreach t,$(src),$(eval $(call objFromSrc,$(patsubst %,obj/%.o,$(basename $(notdir $(t)))),$(t))))
...