Golang构建脚本:如何在构建Go模块时运行命令

Golang构建脚本:如何在构建Go模块时运行命令 我有一个使用Rust库的Go模块。这个Rust库具有C绑定,因此我可以使用cgo与Rust进行交互,这很方便。除了安装环节外,一切都很顺利。为什么呢?因为Rust代码需要使用cargo/rustc进行编译。我可以嵌入动态库(.so.dylib.dll),但这会增加一些复杂性,在当前情况下我想避免采用这种方法。

我可以告诉用户先运行go get -d …,然后运行go generate …,最后运行go install,其中go generate会执行编译Rust部分的命令(基本上是cargo build --release)。但是,我希望我的Go模块能够作为其他任何Go模块的依赖项使用(它是一个库,而不是二进制文件),在这种情况下,无法自动运行go generate。如果我的理解正确:go install运行go build,而它不会运行go generate

所以我的问题是:当用户将我的模块作为依赖项安装时(例如常规的go get),我该如何运行像cargo build --release这样的命令?这甚至可能吗?

谢谢!


更多关于Golang构建脚本:如何在构建Go模块时运行命令的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

我认为没有办法让 go get 同时编译 C 和 Rust 代码并通过 cgo 进行链接。我建议使用 Mage 或 Make 来编写构建脚本。

更多关于Golang构建脚本:如何在构建Go模块时运行命令的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go模块中自动执行外部构建命令(如cargo build)是可能的,但需要谨慎处理。以下是几种解决方案:

方案1:使用//go:generate指令(推荐)

在Go文件中添加generate指令,用户可以通过go generate触发构建:

//go:generate bash -c "cd rustlib && cargo build --release"
package mymodule

// #cgo LDFLAGS: -L./rustlib/target/release -lrustlib
import "C"

// Your Go code here

但注意:这需要用户手动运行go generate,无法在go get时自动执行。

方案2:使用构建约束和自定义构建脚本

创建build.go文件,利用go:build约束:

//go:build build_rust
// +build build_rust

package main

import (
    "os"
    "os/exec"
)

func main() {
    cmd := exec.Command("cargo", "build", "--release")
    cmd.Dir = "./rustlib"
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    if err := cmd.Run(); err != nil {
        os.Exit(1)
    }
}

然后在模块根目录创建Makefile

.PHONY: build
build:
    go run -tags=build_rust build.go
    go build -o mymodule .

方案3:预编译二进制文件分发

最可靠的方法是在发布时预编译Rust库,与Go模块一起分发:

// +build linux
// #cgo LDFLAGS: -L./lib/linux -lrustlib

// +build darwin
// #cgo LDFLAGS: -L./lib/darwin -lrustlib

// +build windows
// #cgo LDFLAGS: -L./lib/windows -lrustlib

重要限制

需要明确的是:标准的go getgo install无法自动运行外部构建命令。这是Go工具链的故意设计,出于安全考虑。

实际解决方案

对于库模块,最实用的方法是:

  1. 预编译分发:在发布版本中包含预编译的Rust库
  2. 提供安装脚本:创建安装脚本供用户使用
  3. 文档说明:在README中明确安装步骤

示例安装脚本install.sh

#!/bin/bash
set -e

echo "Building Rust library..."
cd rustlib && cargo build --release
cd ..

echo "Installing Go module..."
go install .

这样用户可以通过./install.sh完成完整安装,而作为依赖使用时,预编译的库已经包含在模块中。

回到顶部