我花了大部分时间试图弄清楚这一点。我想使用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
这是这样做的好方法吗?如果是这样,我的误解在哪里。
非常感谢
答案 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) $@