GoLang交叉编译的Makefile

huangapple go评论89阅读模式
英文:

Makefile for GoLang Cross Compilation

问题

我正在尝试为交叉编译Go二进制文件创建一个Makefile。如下所示,有很多重复的部分。我也不喜欢我必须重新使用带参数的make命令,而不是匹配一个已存在的目标。有没有更符合惯用方式的方法来实现我想做的事情?

我尝试使用通配符目标来消除一些逻辑重复,例如:

windows-%: app.config
    make os=windows arch=$*

但是每当我尝试以这种方式运行它(即make windows-arm64),我会得到以下结果:

make: Nothing to be done for `windows-arm64'.

编辑:根据@norbert的建议更新了makefile。我认为唯一剩下的复杂之处是在目标内部重新调用make

tags =
executable_base = app
executable_ext =

# go version prints, i.e.: go version go1.18.5 darwin/arm64
# so we can use that as an os-independent way to figure out our current os and arch
os_arch = $(word 4, $(shell go version))
os = $(word 1,$(subst /, ,$(os_arch)))
arch = $(word 2,$(subst /, ,$(os_arch)))


ifeq (${os}, windows)
	executable_ext = .exe
endif


supported_distributions := $(shell go tool dist list | grep -E 'linux|windows|darwin' | grep -E 'amd64|arm64|386')


.PHONY: build all $(supported_distributions)

$(supported_distributions): output_dir = dist/${os}/${arch}
$(supported_distributions):
	make build os=$(word 1,$(subst /, ,$@)) arch=$(word 2,$(subst /, ,$@)) output_dir=${output_dir}

build: output_dir = dist/${os}/${arch}
build: app.config
	GOOS=${os} GOARCH=${arch} go build -tags "${tags}" -o ${output_dir}/${executable_base}${executable_ext} main.go
ifneq (${output_dir},.)
	cp -n ocrunner.config ${output_dir}/ || true
endif

all: $(supported_distributions)

app.config:
	go run cli/main.go create_config

英文:

I'm trying to create a Makefile for cross compiling a go binary. As you can see below, there's a lot of repetition. I also don't like that I have to re-invoke make with the arguments, rather than it matching an existing target already. Is there a more idiomatic way of achieving what I am trying to do?

I tried using wildcard targets to deduplicate some logic, for example

windows-%: app.config
    make os=windows arch=$*

but whenever I try and run it with this (i.e. make windows-arm64), I get back

make: Nothing to be done for `windows-arm64'.

EDIT: updated makefile after @norbert's suggestions. I think the only remaining complication is having to re-invoke make from within the target

tags =
executable_base = app
executable_ext =

# go version prints, i.e.: go version go1.18.5 darwin/arm64
# so we can use that as an os-independent way to figure out our current os and arch
os_arch = $(word 4, $(shell go version))
os = $(word 1,$(subst /, ,$(os_arch)))
arch = $(word 2,$(subst /, ,$(os_arch)))


ifeq (${os}, windows)
	executable_ext = .exe
endif


supported_distributions := $(shell go tool dist list | grep -E 'linux|windows|darwin' | grep -E 'amd64|arm64|386')


.PHONY: build all $(supported_distributions)

$(supported_distributions): output_dir = dist/${os}/${arch}
$(supported_distributions):
	make build os=$(word 1,$(subst /, ,$@)) arch=$(word 2,$(subst /, ,$@)) output_dir=${output_dir}

build: output_dir = dist/${os}/${arch}
build: app.config
	GOOS=${os} GOARCH=${arch} go build -tags "${tags}" -o ${output_dir}/${executable_base}${executable_ext} main.go
ifneq (${output_dir},.)
	cp -n ocrunner.config ${output_dir}/ || true
endif

all: $(supported_distributions)

app.config:
	go run cli/main.go create_config

答案1

得分: 1

不是一个惯用的方式。可能有更简短的方法。

go tool dist list

可以获取所有的构建。

现在只需要在列表中查找${os}的前两个小写字符,查找指定的架构,至少它能够对golang能力的变化做出响应。

至于Darwin 386:那可能是你唯一的例外(不知道你会在哪里遇到这个问题)。

英文:

Not an idiomatic way. Shorter might be possible

go tool dist list

Gets you all builds.

By now just looking for the first 2 lowercase characters of the OS in the list against the ${os}, look for the arch as indicated, and at least it becomes responsive to the changes in golang capabilities.

As for Darwin 386: That is probably your only exception (Don't know where you would hit that one though)

huangapple
  • 本文由 发表于 2022年8月11日 07:02:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/73313593.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定