定义等同于多个管道函数的自定义 gmake 函数

Define custom gmake function equivalent to multiple piped functions

我正在尝试定义一个适合 $(patsubst %,$(OBJDIR)/%.o,$(basename $(ARG1)))

工作的函数

类似;

define getobj
    $(1): $(patsubst %,$(OBJDIR)/%.o,$(basename $(1)))
endef

我要改进的上下文是:

OBJDIR = objects
TESTHNF_CPPS = testhnf.cpp timings.cpp LongModular.cpp VeryLong.cpp VeryLongModular.cpp squfof.cpp
TESTHNF_CS = mt19937int.c lip.c
TESTHNF_OBJS = $(patsubst %,$(OBJDIR)/%.o,$(basename $(TESTHNF_CPPS) $(TESTHNF_CS)))
TESTHNF_OBJS2 = $(getobj $(TESTHNF_CPPS) $(TESTHNF_CS))

此处,$(TESTHNF_OBJS2) 为空。我应该如何编写函数?

您的 getobj 宏看起来像是您要声明的规则 (target: prerequisites)。但是你尝试使用它看起来像是你试图将它的扩展结果分配给一个变量,这实际上没有意义。

因此,让我们忽略规则外观并专注于您的目标(据我所知):定义一个宏,获取传递的每个单词的 basename 并将其替换为 $(OBJDIR)/<basename>.o.你快到了:

getobj = $(patsubst %,$(OBJDIR)/%.o,$(basename $(1)))

应该可以,其中 $(1) 是宏的参数,space 分隔的单词列表。你用 call make function:

来称呼它
TESTHNF_OBJS2 = $(call getobj,$(TESTHNF_CPPS) $(TESTHNF_CS))

call make 函数将 $(1) 替换为 getobj 定义中的 $(TESTHNF_CPPS) $(TESTHNF_CS) 参数和 returns 结果。在您的情况下,它相当于:

TESTHNF_OBJS2 = $(patsubst %,$(OBJDIR)/%.o,$(basename $(TESTHNF_CPPS) $(TESTHNF_CS)))

TESTHNF_OBJS2 展开时,结果将是:

objects/testhnf.o objects/timings.o ... objects/lip.o

回到规则看。如果您想要的是实例化一个 make 规则:

<basename>: $(OBJDIR)/<basename>.o

对于列表中的每个 <basename>,加上定义一个 TESTHNF_OBJS 变量列出所有相应的目标文件,您可以使用 foreach, eval and call 的组合。但是事情有点棘手,因为 make 扩展了 eval 参数一次,将结果实例化为 make 构造,并在将其解析为任何常规 make 构造时再次扩展它。因此,有时必须通过加倍 $ 符号来避免双重扩展;这不是你的情况,但在使用这些东西时最好记住这一点。

OBJDIR = objects
TESTHNF_CPPS = testhnf.cpp timings.cpp LongModular.cpp VeryLong.cpp VeryLongModular.cpp squfof.cpp
TESTHNF_CS = mt19937int.c lip.c
TESTHNF_OBJS :=

# $(1): basename of one source file
define getobj
    $(1): $(OBJDIR)/$(1).o

    TESTHNF_OBJS += $(OBJDIR)/$(1).o
endef
$(foreach b,$(basename $(TESTHNF_CPPS) $(TESTHNF_CS)),$(eval $(call $(b))))

clean:
    rm -f $(TESTHNF_OBJS)

由于所有这些都相当复杂,而且收益很低,因此最好坚持使用更简单的构造,更容易理解和维护:

OBJDIR       := objects
TESTHNF_CPPS := testhnf.cpp timings.cpp LongModular.cpp VeryLong.cpp VeryLongModular.cpp squfof.cpp
TESTHNF_CS   := mt19937int.c lip.c
BASENAMES    := $(basename $(TESTHNF_CPPS) $(TESTHNF_CS))
TESTHNF_OBJS := $(addprefix $(OBJDIR)/,$(addsuffix .o,$(BASENAMES)))

$(BASENAMES): %: $(OBJDIR)/%.o

clean:
    rm -f $(TESTHNF_OBJS)

规则是 static pattern rule.