在go程序中的交叉编译

本文涉及的产品
可观测可视化 Grafana 版,10个用户账号 1个月
可观测监控 Prometheus 版,每月50GB免费额度
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 【7月更文挑战第9天】本文介绍Go 交叉编译允许在一种平台上构建适用于多平台的二进制文件。`go build -cover`用于覆盖率分析,`-coverpkg`控制分析的包范围,生成的二进制文件运行后,覆盖率数据会写入`GOCOVERDIR`指定的目录。

1 简介

go程序可用通过交叉编译的方式在一个平台输出多个平台可运行的二进制包。
交叉编译示意图:
image.png

两个方式分别为使用cgo的交叉编译和不使用cgo的交叉编译。无需CGO时,直接使用Go的跨平台支持编译。若涉及CGO且目标为ARM,需配置交叉编译环境;若目标为Win/Linux/Mac,推荐使用go-ui-crossbuild工具。设置环境变量如GOOS, GOARCH, CGO_ENABLED来执行编译,例如CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build。Mac上交叉编译至Linux和Windows,Linux反之,Windows亦然,需相应调整环境变量。

如果你的程序没有用到 CGO 的 Golang 程序,直接用编译器自带的跨平台特性即可全平台编译;

如果用到了 CGO 需要发布到ARM平台的Golang程序,推荐自己配置ARM交叉编译环境;

如果用到了 CGO 需要发布到Win/Linux/Mac平台的Golang程序,推荐用使用go-ui-crossbuild 。

2 交叉编译

设置环境信息

export CFLAGS="-arch arm64 -miphoneos-version-min=9.0 -isysroot "$(xcrun -sdk iphoneos --show-sdk-path) 

CGO_ENABLED=1 GOARCH=arm64 CC="clang $CFLAGS" go build -v -x -buildmode=c-archive -o libChinaPYG_arm64.a

这会同时生成libChinaPYG_arm64.a、libChinaPYG_arm64.h两个文件,直接嵌入到C代码中正常使用。

编译 darwin/arm64 的 example 命令就是:

CC=/usr/local/go/misc/ios/clangwrap.sh GOOS=darwin GOARCH=arm64 CGO_ENABLED=1 go build

编译 darwin/arm 的 example 命令是:

CC=/usr/local/go/misc/ios/clangwrap.sh GOOS=darwin GOARCH=arm CGO_ENABLED=1 go build

linux交叉编译windows:

    CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -trimpath  -o bin/main.exe ./cmd/dend-server/main.go

    CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build  -o bin/main.exe ./cmd/dend-server/main.go

3 设置

1.Mac Mac下编译Linux, Windows平台的64位可执行程序:

    CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build test.go

    CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build test.go

参数介绍:

  $CGO_ENABLED:0表示关闭CGO
  $GOOS:目标平台(编译后要运行的目标平台)的操作系统
    (darwin、freebsd、linux、windows)
  $GOARCH:目标平台(编译后要运行的目标平台)的体系架构
    (386、amd64、arm)分别对应(32位、64位、ARM平台)的架构

2.Linux Linux下编译Mac, Windows平台的64位可执行程序:

    CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build test.go

    CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build test.go

3.Windows Windows下编译Mac, Linux平台的64位可执行程序:

cmd:

    set GOARCH=amd64
    go env -w GOPATH=amd64
    set GOOS = linux
    go env -w GOOS=linux

还原:

    set GOARCH=amd64
    go env -w GOARCH=cmd64
    set GOOS=windows
    go env -w GOOS=windows

4 构建测试支持

Go 提供易于使用的支持,用于通过“ go test -coverprofile=... ”命令在包单元测试级别收集覆盖率配置文件。

从 Go 1.20 开始,用户现在可以为更大的集成测试收集覆盖率配置文件:更重量级、更复杂的测试,执行给定应用程序二进制文件的多次运行。

对于单元测试,收集覆盖率概况和生成报告需要两个步骤:go test -coverprofile=...运行,然后调用go tool cover {-func,-html}生成报告。

对于集成测试,需要三个步骤:构建步骤、运行步骤(可能涉及从构建步骤多次调用二进制文件),最后是报告步骤,如下所述。

构建用于覆盖率分析的二进制文件,要构建用于收集覆盖率配置文件的应用程序,请-cover在调用go build应用程序二进制目标时传递标志。

请参阅下面的示例go build -cover调用部分。然后可以使用环境变量设置运行生成的二进制文件以捕获覆盖率配置文件(请参阅下一节运行)。

  • 如何为检测选择包

在给定的“ go build -cover”调用期间,Go 命令将选择主模块中的包进行覆盖率分析;默认情况下,不会包含提供给构建的其他包(go.mod 中列出的依赖项,或作为 Go 标准库一部分的包)。

例如,这是一个玩具程序,包含一个主包、一个本地主模块包greetings和一组从模块外部导入的包,包括(除其他外)rsc.io/quote和fmt(完整程序的链接)。

    $ cat go.mod
    module mydomain.com

    go 1.20

    require rsc.io/quote v1.5.2

    require (
        golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c // indirect
        rsc.io/sampler v1.3.0 // indirect
    )

    $ cat myprogram.go
    package main

    import (
        "fmt"
        "mydomain.com/greetings"
        "rsc.io/quote"
    )

    func main() {
        fmt.Printf("I say %q and %q\n", quote.Hello(), greetings.Goodbye())
    }
    $ cat greetings/greetings.go
    package greetings

    func Goodbye() string {
        return "see ya"
    }
    $ go build -cover -o myprogram.exe .
    $

如果您使用“ -cover”命令行标志构建此程序并运行它,配置文件中将恰好包含两个包:main和mydomain.com/greetings;其他依赖包将被排除在外。

想要更好地控制包含哪些包以进行覆盖的用户可以使用“ -coverpkg”标志进行构建。例子:

    $ go build -cover -o myprogramMorePkgs.exe -coverpkg=io,mydomain.com,rsc.io/quote .
    $

在上面的构建中,选择了 main 包mydomain.com以及rsc.io/quote和io包进行分析;因为 mydomain.com/greetings没有具体列出,所以它将被排除在配置文件之外,即使它位于主模块中。

5 运行覆盖检测的二进制文件

用“”构建的二进制-cover文件在执行结束时将配置文件数据文件写到通过环境变量指定的目录中GOCOVERDIR。例子:

    $ go build -cover -o myprogram.exe myprogram.go
    $ mkdir somedata
    $ GOCOVERDIR=somedata ./myprogram.exe
    I say "Hello, world." and "see ya"
    $ ls somedata
    covcounters.c6de772f99010ef5925877a7b05db4cc.2424989.1670252383678349347
    covmeta.c6de772f99010ef5925877a7b05db4cc
    $

请注意写入目录的两个文件somedata:这些(二进制)文件包含覆盖率结果。有关如何从这些数据文件生成人类可读结果的更多信息,请参阅以下有关报告的部分。

如果GOCOVERDIR未设置环境变量,覆盖检测的二进制文件仍将正确执行,但会发出警告。

目录
相关文章
|
5月前
|
存储 安全 测试技术
【Go语言精进之路】构建高效Go程序:了解map实现原理并高效使用
【Go语言精进之路】构建高效Go程序:了解map实现原理并高效使用
64 3
|
5月前
|
存储 监控 Go
【Go语言精进之路】构建高效Go程序:了解切片实现原理并高效使用
【Go语言精进之路】构建高效Go程序:了解切片实现原理并高效使用
86 3
|
2月前
|
Kubernetes Go 持续交付
一个基于Go程序的持续集成/持续部署(CI/CD)
本教程通过一个简单的Go程序示例,展示了如何使用GitHub Actions实现从代码提交到Kubernetes部署的CI/CD流程。首先创建并版本控制Go项目,接着编写Dockerfile构建镜像,再配置CI/CD流程自动化构建、推送Docker镜像及部署应用。此流程基于GitHub仓库,适用于快速迭代开发。
50 3
|
2月前
|
Kubernetes 持续交付 Go
创建一个基于Go程序的持续集成/持续部署(CI/CD)流水线
创建一个基于Go程序的持续集成/持续部署(CI/CD)流水线
|
2月前
|
IDE Go 数据处理
Go to Learn Go之第一个Go程序
Go to Learn Go之第一个Go程序
25 0
|
3月前
|
Linux Shell Go
如何构建和安装 Go 程序
如何构建和安装 Go 程序
41 1
|
3月前
|
Go
在Go中如何停止程序
在Go中如何停止程序
|
3月前
|
Go 数据库 UED
[go 面试] 同步与异步:程序执行方式的不同之处
[go 面试] 同步与异步:程序执行方式的不同之处
|
3月前
|
存储 缓存 安全
|
3月前
|
编译器 Go 开发者