Makefile目标是两个列表的叉积

时间:2018-11-09 12:20:10

标签: makefile gnu-make

我花了大部分时间试图弄清楚这一点。我想使用make来构建具有不同os目标和多个二进制文件的golang项目。我想我想使用gnu make

我剥离的Makefile看起来像:

main= mailworker websocket worker init
os= linux freebsd darwin

all: $(main)

$(main): ensure_build_path
    @echo "Build $@ Version: $(GIT_REV)"
    @rm -rf $(BUILD_PREFIX)/$@
    GO111MODULE=on GOARCH=amd64 $(GO) build  -o $(BUILD_PREFIX)/$@ ./bin/$@/$@.go

现在,我想向构建命令添加GOOS=$(os) /为每个主要的X os组合生成一个目标。我的测试/ lern Makefile看起来像:

os=linux freebsd darwin
main=mailworker websocket worker init

define build_template =
t:=$(addprefix $(1), $(2))
$(info $(t))
$(t):
    @echo $(1) $(2) $$@
endef

$(foreach P, $(main), $(foreach O, $(os), $(eval $$(call build_template, $O, $P))) )

我尝试过至少有十多种。我认为我的主要问题是如何在模板中声明t。我尝试了许多关于make的“ concat”方法。同样,:==也等于t。我认为:=是正确的选择。但是我再也不确定了;)

需要明确的是,我希望“生成”看起来像这样的目标:

mailworker_linux:
    GO111MODULE=on GOOS=linux GOARCH=amd64 $(GO) build mailworker

mailworker_darwin:
    GO111MODULE=on GOOS=darwin GOARCH=amd64 $(GO) build mailworker

这是这样做的好方法吗?如果是这样,我的误解在哪里。

非常感谢

1 个答案:

答案 0 :(得分:4)

您在这里遇到一些问题。首先,您对..., $(eval $(call build_template,$P,$O)).. 的调用是不正确的:您将其转义,这意味着在将其赋给eval之前不会对其进行扩展;这是不正确的,必须先进行扩展。您想要:

$

call前只有一个$@

第二,与eval / call对一起使用的所定义变量的规则是,必须逃避要由eval看到的该变量内的每个宏扩展。在您的情况下,您确实将$$@的转义为$(t),但这很好,但是您需要转义的另一件事是使用eval,因为直到{{1 }进行设置。因此,您需要这样编写变量:

define build_template =
t := $(addprefix $(1)_,$(2))
$$(info $$(t))
$$(t):
        @echo $(1) $(2) $$@
endef

(我在您的_中添加了丢失的addprefix)。此处使用=还是:=都没关系;由于您总是在立即展开式上下文中使用此变量,因此它们的工作方式都相同。

顺便说一句,似乎每个人都直接进行评估和调用,这些功能非常强大,但也难以使用和理解。使用更直接的make构造的替代方法可能是这样的:

getmain = $(word 1,$(subst _, ,$@))
getos = $(word 2,$(subst _, ,$@))

TARGETS := $(foreach P,$(main),$(addprefix $P_,$(os)))

all: $(TARGETS)

$(TARGETS): %:
        @echo $(getmain) $(getos) $@