macos golang 程序依赖 cgo 编译不兼容问题解决方案

在本地macos环境上编译程序,上传到linux环境,发现运行失败,失败信息如下:

1
[error] failed to initialize database, got error Binary was compiled with 'CGO_ENABLED=0', go-sqlite3 requires cgo to work. This is a stub

提示程序中使用了github.com/mattn/go-sqlite3, 依赖cgo,编译需要开启 CGO_ENABLED=1

go-sqlite3 is cgo package. If you want to build your app using go-sqlite3, you need gcc. However, after you have built and installed go-sqlite3 with go install github.com/mattn/go-sqlite3 (which requires gcc), you can build your app without relying on gcc in future.

Important: because this is a CGO enabled package, you are required to set the environment variable CGO_ENABLED=1 and have a gcc compiler present within your path.

SQLite使用示例:

1
2
3
4
5
6
7
8
9
import (
    "gorm.io/driver/sqlite" // Sqlite driver based on CGO
    // "github.com/glebarez/sqlite" // Pure go SQLite driver, checkout https://github.com/glebarez/sqlite for details
    "gorm.io/gorm"
)

// github.com/mattn/go-sqlite3
db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{})

开启CGO_ENABLED=1后编译失败,报错信息如下:

1
2
3
4
5
6
7
# runtime/cgo
linux_syscall.c:67:13: error: implicit declaration of function 'setresgid' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
linux_syscall.c:67:13: note: did you mean 'setregid'?
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/unistd.h:593:6: note: 'setregid' declared here
linux_syscall.c:73:13: error: implicit declaration of function 'setresuid' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
linux_syscall.c:73:13: note: did you mean 'setreuid'?
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/unistd.h:595:6: note: 'setreuid' declared here

提示macos下cgo系统依赖库不兼容,需要安装linux环境版本

解决方法

参考github.com/mattn/go-sqlite3的macos安装说明

Cross Compiling from macOS

  1. Install musl-cross
1
brew install FiloSottile/musl-cross/musl-cross
  1. Set build parameters
1
CC=x86_64-linux-musl-gcc CXX=x86_64-linux-musl-g++ GOARCH=amd64 GOOS=linux CGO_ENABLED=1 go build -ldflags "-linkmode external -extldflags -static"

在安装musl-cross时,可能出现网络问题导致安装失败,如下:

1
2
3
4
curl: (28) Failed to connect to cyfuture.dl.sourceforge.net port 443 after 75011 ms: Couldn't connect to server                                                          #    #  # #

Error: musl-cross: Failed to download resource "musl-cross--isl-0.21.tar.bz2"
Download failed: https://downloads.sourceforge.net/project/libisl/isl-0.21.tar.bz2

这个时候可以考虑使用Docker编译部署

如果都不行,还有一个解决办法,就是使用纯Go的解决方案,

github.com/glebarez/sqlite 是一个纯Go驱动的sqlite,不需要cgo,

直接依赖github.com/glebarez/go-sqlite项目,一个纯Go编写的sqlite嵌入式项目,

嵌入modernc.org/sqlite

使用示例:

1
2
3
4
5
6
import (
    "github.com/glebarez/sqlite"
    "gorm.io/gorm"
)

db, err := gorm.Open(sqlite.Open("sqlite.db"), &gorm.Config{})

参考