Помогает ли §8.8 руководства GNU Make (3.82)?
[...] Хотя в этом примере использование eval может показаться слишком сложным,
Вместо того, чтобы просто писать правила, рассмотрим две вещи: во-первых, определение шаблона (в
PROGRAM_template) может быть намного сложнее, чем здесь; а во-вторых, ты
может поместить сложную «общую» часть этого примера в другой make-файл, а затем включить
это во всех отдельных make-файлах. Теперь ваши индивидуальные make-файлы довольно просты.
PROGRAMS = server client
server_OBJS = server.o server_priv.o server_access.o
server_LIBS = priv protocol
client_OBJS = client.o client_api.o client_mem.o
client_LIBS = protocol
# Everything after this is generic
.PHONY: all
all: $(PROGRAMS)
define PROGRAM_template =
$(1): $$($(1)_OBJS) $$($(1)_LIBS:%=-l%)
ALL_OBJS += $$($(1)_OBJS)
endef
$(foreach prog,$(PROGRAMS),$(eval $(call PROGRAM_template,$(prog))))
$(PROGRAMS):
$(LINK.o) $^ $(LDLIBS) -o $@
clean:
rm -f $(ALL_OBJS) $(PROGRAMS)
Это работает (для меня)
Это вывод из сборочного файла GNU чуть ниже:
stdcout_include_home = /work4/jleffler/usr/include
stdcout_include_home_name = /work4/jleffler/usr/include/stdcout
stdcout_Include = /work4/jleffler/usr/include
CFLAGS: -I/work4/jleffler/include -I/work4/jleffler/usr/include
GNU Makefile
CFLAGS = -I${HOME}/include
define Flags_template
$(1)_include_home := $(HOME)/usr/include
$(1)_include_home_name := $(HOME)/usr/include/$(1)
ifneq ($$(wildcard $$($(1)_include_home)/$(2)),)
$(1)_Include := $$($(1)_include_home)
else
ifneq ($$(wildcard $$($(1)_include_home_name)/$(2)),)
$(1)_Include := $$($(1)_include_home_name)
else
$(1)_Include := Neither $$($(1)_include_home) nor $$($(1)_include_home_name) contains $2
endif
endif
CFLAGS += -I$$($(1)_Include)
endef
$(eval $(call Flags_template,stdcout,StdCout.hpp))
.PHONY: test
test:
@echo stdcout_include_home = $(stdcout_include_home)
@echo stdcout_include_home_name = $(stdcout_include_home_name)
@echo stdcout_Include = $(stdcout_Include)
@echo CFLAGS: $(CFLAGS)
Разница заключается в вызовах с подстановочными знаками:
ifneq ($$(wildcard $($(1)_include_home)/$(2)),) # Fails
ifneq ($$(wildcard $$($(1)_include_home)/$(2)),) # Works
У меня есть половина интуиции о том, когда нужны двойные доллары и когда нужны одни доллары; Я не уверен, что могу сформулировать решение, хотя.