创建gnu makefile“功能”的问题

时间:2011-02-03 20:42:51

标签: makefile

我有一大块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,一个完全消耗,一个空......

我不明白需要评估什么,用两个$等逃脱

我怎样才能做到这一点?

非常感谢。

1 个答案:

答案 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

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

我对双倍美元和需要单一美元的时候有一半的直觉;不过,我不确定我是否可以明确表达这个决定。