创建 gnu makefile“函数”时出现问题

发布于 2024-10-16 02:06:18 字数 1010 浏览 1 评论 0原文

我的 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”,我总是得到重复项,一个完全耗尽,一个空...

我不明白需要评估什么,用两个 $ 转义等等。

我怎样才能实现这一点?

非常感谢。

I have a big chunk of my makefile (~50 lines) that needs to be copy-pasted 5 times for different case (the different libraries used). Is it possible to create a function in a makefile and just call that function instead of copy-pasting?

This is an example of what I've tried. Basically this tries to find the right path for an installed library.

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)

Typing "make", I get this output:

# stdcout_include_home_name = /home/nicolas/usr/include/stdcout
# stdcout_Include = 
# CFLAGS: -I

It's so close. But note the last "-I", I always get dupplicates, one fully expended, one empty...

I don't understant what needs to be eval'ed, escaped with two $, etc.

How can I achieve this?

Thank you very much.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

执手闯天涯 2024-10-23 02:06:18

GNU Make (3.82) 手册的第 8.8 节有帮助吗?

[...] 虽然在此示例中使用 eval 似乎过于复杂,
不仅仅是写出规则,还要考虑两件事:首先,模板定义(在
PROGRAM_template)可能需要比这里复杂得多;其次,你
可能会将这个示例的复杂的“通用”部分放入另一个 makefile 中,然后包含
它在所有单独的 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

我对何时需要双美元和何时需要单美元有一半的直觉;不过,我不确定我能清楚地表达出这个决定。

Does §8.8 of the GNU Make (3.82) manual help?

[...] Although it might seem overly complex to use eval in this example,
rather than just writing out the rules, consider two things: first, the template definition (in
PROGRAM_template) could need to be much more complex than it is here; and second, you
might put the complex, “generic” part of this example into another makefile, then include
it in all the individual makefiles. Now your individual makefiles are quite straightforward.

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)

This Works (For Me)

This is the output from the GNU makefile just below:

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)

The difference is in the wildcard invocations:

ifneq ($(wildcard  $($(1)_include_home)/$(2)),)    # Fails
ifneq ($(wildcard $($(1)_include_home)/$(2)),)    # Works

I have half an intuition about when double-dollars and when single-dollars are needed; I am not sure I can articulate the decision, though.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文