Terraform 如何从源码构建可执行文件并设置 ldflags 与 CGO_ENABLED
【免费下载链接】terraformTerraform enables you to safely and predictably create, change, and improve infrastructure. It is a source-available tool that codifies APIs into declarative configuration files that can be shared amongst team members, treated as code, edited, reviewed, and versioned.项目地址: https://gitcode.com/GitHub_Trending/te/terraform
如果你不想使用官方预编译的二进制文件,或者希望在构建产物中控制版本标记与实验特性开关,就需要用 Go 工具链从源码构建 Terraform。仓库的 BUILDING.md 给出了构建前提、构建时ldflags选项和CGO_ENABLED的取值约定。按照本文操作后,你会得到一个可执行的terraform二进制文件,并知道如何验证每个选项是否生效。
构建前置条件
- 安装
.go-version文件指定的 Go 版本。BUILDING.md 要求按该文件声明的版本安装 Go,当前仓库中该文件内容为1.26.4。 - 将本仓库克隆到本地任意位置,后续所有命令都在仓库根目录下执行。
基本构建命令
BUILDING.md 中的构建命令都基于同一条go build:
go build -ldflags "-w -s -X 'github.com/hashicorp/terraform/version.dev=no'" -o bin/ .各部分的作用(依据 BUILDING.md 及仓库内说明):
-o bin/ .:把当前模块(.)编译出的二进制文件输出到bin/目录;-ldflags:向链接器传递构建期选项,Terraform 接受若干此类选项来控制构建产物的行为;-w -s:scripts/build.sh 中对这一组合的注释解释是,发布构建不希望在二进制中保留调试信息;-X 'github.com/hashicorp/terraform/version.dev=no':在链接时把 version/version.go 中的dev变量设置为no,该变量控制版本报告中是否带-dev标记。
不传-ldflags时使用代码默认值:dev在源码中初始化为"yes",experiments.go 中的experimentsAllowed初始化为空字符串,即实验特性不可用。
用 ldflags 控制构建行为
控制版本报告中的 -dev 标记
Terraform 在报告自身版本时会包含-dev标记(文档示例:1.5.0-dev),除非把version.dev设置为no:
go build -ldflags "-w -s -X 'github.com/hashicorp/terraform/version.dev=no'" -o bin/ .开启实验特性
Terraform 的实验特性默认是禁用的,除非把main.experimentsAllowed设置为yes:
go build -ldflags "-w -s -X 'main.experimentsAllowed=yes'" -o bin/ .这对应根目录 experiments.go 中的experimentsAllowed变量:默认为空字符串,任何非空值即视为开启。BUILDING.md 同时说明,官方构建流程只在 alpha 版本中允许实验特性,并建议第三方分发者沿用这一惯例以减少用户混淆。
如果一次构建既要去掉-dev标记又要开启实验特性,可以把两个-X写进同一段 ldflags(这是上面两项设置的组合写法):
go build -ldflags "-w -s -X 'github.com/hashicorp/terraform/version.dev=no' -X 'main.experimentsAllowed=yes'" -o bin/ .按平台选择 CGO_ENABLED
BUILDING.md 说明,Terraform 的发布流程总体依赖 Go 工具链针对目标操作系统和处理器架构的默认值,唯一被显式设置的例外是CGO_ENABLED:
- 大多数平台使用
CGO_ENABLED=0构建,以产生静态链接的二进制文件:
CGO_ENABLED=0 go build -ldflags "-w -s" -o bin/ .- MacOS/Darwin 系统使用
CGO_ENABLED=1构建,以规避平台特有的 DNS 解析问题:
CGO_ENABLED=1 go build -ldflags "-w -s" -o bin/ .命令前缀中的CGO_ENABLED=...是只对这一次构建生效的环境变量设置,不会修改系统环境。
验证构建结果
构建完成后直接运行产物:
bin/terraform versionmain.go 会把-v、-version、--version参数快捷映射到version子命令,因此bin/terraform -v效果相同。
判断各选项是否生效:
- 默认构建:版本字符串中带
-dev预发布标记。需要注意,当前源码树的 version/VERSION 文件内容本身是1.17.0-dev,所以从这份源码构建出的二进制,其版本输出会包含-dev标记; - 设置
version.dev=no后:不再由代码强制附加dev标记。version/version.go 的逻辑是此时直接取 VERSION 文件自带的 prerelease 部分,没有则为空。也就是说,去掉-dev的效果在 VERSION 文件不含预发布标记的版本号上才直观可见; - 实验特性:
main.experimentsAllowed为空时实验特性不可用;设置为非空值(如yes)后实验特性才可用。
可选:用 scripts/build.sh 做多平台构建
scripts/build.sh 用于一次为多个平台构建二进制文件,面向发布场景。在仓库根目录执行:
./scripts/build.sh执行前需要了解它的副作用与行为:
- 脚本开头会执行
rm -f bin/*和rm -rf pkg/*,删除bin/与pkg/目录下的旧构建产物; - 如果本机没有
gox,脚本会自动执行go install github.com/mitchellh/gox联网安装该工具; - 脚本固定
export CGO_ENABLED=0(注释说明是为了让 gox 构建静态链接二进制),并设置GOFLAGS=-mod=readonly以避免构建隐含更新 go.mod; - 默认构建平台为
linux darwin windows freebsd openbsd solaris乘以386 amd64 arm,并排除darwin/arm与darwin/386。
通过环境变量调整行为:
TF_DEV:设置为非空值(例如TF_DEV=1 ./scripts/build.sh)时只构建当前操作系统/架构,产物拷贝到bin/和$GOPATH/bin,并跳过最后的打包步骤;TF_RELEASE:设置为非空值(例如TF_RELEASE=1 ./scripts/build.sh)时,ldflags 变为-s -w -X 'github.com/hashicorp/terraform/version.dev=no',即发布模式:不带调试信息、不带-dev版本标记。
注意该脚本对所有交叉构建统一使用CGO_ENABLED=0。如果你需要按 BUILDING.md 的约定在 macOS 上构建CGO_ENABLED=1的二进制,应改用前文的手动go build命令。
本地单平台构建直接用前文的go build命令即可,build.sh只在需要批量产出多平台二进制时使用。按 BUILDING.md 的建议,分发时只在 alpha 构建中开启实验特性,也能降低使用方的混淆。
【免费下载链接】terraformTerraform enables you to safely and predictably create, change, and improve infrastructure. It is a source-available tool that codifies APIs into declarative configuration files that can be shared amongst team members, treated as code, edited, reviewed, and versioned.项目地址: https://gitcode.com/GitHub_Trending/te/terraform
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考