我有一大块makefile(~50行),需要为不同的情况(使用不同的库)复制粘贴5次。是否可以在makefile中创建一个函数,只调用该函数而不是复制粘贴?
这是我尝试过的一个例子。基本上,这会尝试为已安装的库找到正确的路径。
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)
endif
endif
CFLAGS += -I$$($(1)_Include)
endef
$(eval $(call Flags_template,stdcout,StdCout.hpp))
.PHONY: test
test:
# stdcout_include_home_name = $(stdcout_include_home_name)
# stdcout_Include = $(stdcout_Include)
# CFLAGS: $(CFLAGS)
输入“make”,我得到这个输出:
# stdcout_include_home_name = /home/nicolas/usr/include/stdcout
# stdcout_Include =
# CFLAGS: -I
它非常接近。但请注意最后一个“-I”,我总是得到dupplicates,一个完全消耗,一个空......
我不明白需要评估什么,用两个$等逃脱
我怎样才能做到这一点?
非常感谢。
答案 0 :(得分:1)
GNU Make(3.82)手册的§8.8是否有帮助?
[...]虽然在这个例子中使用eval似乎过于复杂, 而不只是写出规则,考虑两件事:第一,模板定义(在 PROGRAM_template)可能需要比这里复杂得多;第二,你 可能会将此示例的复杂“通用”部分放入另一个makefile中,然后包含 它在所有单个makefile中。现在你的个人文件非常简单。
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 makefile的输出:
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
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
我对双倍美元和需要单一美元的时候有一半的直觉;不过,我不确定我是否可以明确表达这个决定。