针对特定目标的Makefile环境变量

3
我正在处理一个类似下面的Makefile的Go项目。请注意,“release”目标设置了两个环境变量,以便“build”目标可以进行交叉编译以针对特定架构(可能不是构建系统的架构)。"最初的回答"
# Generates a container release artifact.
release: export GOOS=linux
release: export GOARCH=amd64
release: build
  docker build ...

# Generates an executable for local use.
build: test
  go build ...

test: fmt vet
  go test ./...

...

问题在于"go test"命令也会检测到"GOOS"和"GOARCH"环境变量,这导致该步骤失败,因为显然不支持跨平台测试
换句话说,就像我想清除"test"目标的环境变量,但是下面的示例似乎没有按预期取消设置变量。
unexport GOOS
unexport GOARCH
test: fmt vet
    go test ./...

我可以为“build”目标删除“test”依赖项,这样就能正常运行,但这似乎是错误的方法,因为如果测试失败,我不想构建或发布二进制文件。
我是否可以以某种方式修改Makefile,使得“release”目标设置GOOSGOARCH环境变量,并由“build”目标使用,但不使用相关的“test”目标?
也许还有其他方法进行跨平台编译并作为依赖项运行测试,而不会使事情变得更加复杂(例如通过Docker构建等)。请注意,由于发布和构建目标有几个标志,因此make目标比上面的示例要复杂一些。

Go使用相同的源代码适用于所有操作系统,因此您只需创建一个测试文件,并将其用于每个操作系统。 - Pizza lord - on strike
你可以将发布版本的构建和测试放入Docker中,在容器内运行它。 - Mad Wombat
@MadWombat 当然可以,但我不想在本地构建和Docker构建中重复编写Makefile代码(问题中的最小示例只展示了一小部分)。 - maerics
3个回答

5
我会这样做:

我会采取这种方式:

test: export GOOS=
test: export GOARCH=
test: fmt vet
    go test ./...

是的,这个方法非常好用,而且可能比我自己的解决方案读起来更顺畅一些。从根本上说,这是正确的修复方法,因为测试只能在本地平台上进行,所以这些环境变量不应该设置给测试目标。小问题:拼写错误的是"test",而不是"text"。 - maerics

2
为什么不这样做呢?在go执行期间,它只会设置那些环境变量。最初的回答。
    # Generates a container release artifact.
release: build
  docker build ...

# Generates an executable for local use.
build: test
  GOOS=linux GOARCH=amd64 go build ...

test: fmt vet
  go test ./...

...

因为我也想在我的本地系统上构建可执行文件。所以当通过“release”调用时,“build”应该只进行交叉编译。 - maerics
啊...这样就说得通了。在这种情况下,你有两个选择。a. 将环境变量定义放在Dockerfile中,或者b. 在Makefile中编写一个if语句,运行两个不同的go build ...命令。 - Konstantin Itskov
或者c.编写另一个Makefile目标,由release运行,与您在本地运行的目标分开。不要过度设计。 :) - Konstantin Itskov
等一下 - 你关于在命令行上设置环境变量的观察启发了答案,我可以在"test"命令中取消设置它们,这样它就会使用本地系统的操作系统和架构! - maerics

0
我刚意识到我可以在有问题的测试命令中取消设置环境变量。
test: fmt vet
    GOOS= GOARCH= go test ./...

这样,“go test”命令将始终使用本地系统的操作系统和架构(正如它应该做的!)。
感谢@KonstantinItskov的启发。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接