Saki's 研究记录

Golang 交叉编译报错 XX is invalid in C99

字数统计: 632阅读时长: 2 min
2021/11/29

环境

Mac ProductVersion: 11.6.1
gcc version: apple clang version 13.0.0 (clang-1300.0.29.3)
Ubuntu: 16.04.6 LTS
CentOS: Linux release 8.4.2105 (Core)

背景

最近在使用redis-full-check来对比两个redis的数据是否一致,我本地的开发环境是macos来进行代码编译,编译后的程序会上传到ubuntu系统的机器上运行。

问题

这就导致我需要使用到golang的交叉编译,golang默认支持交叉编译,只在编译时配置对应平台的编译参数即可:

1
2
3
4
5
6
# linux
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -o BIN_NAME
# windows
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o BIN_NAME
# macos
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o BIN_NAME

本地go run编译并运行程序没有问题,但在我编译二进制文件时候遇到了麻烦(应该是项目里使用了sqlite3导致的):

1
2
3
4
5
6
7
8
9
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -o ./build/redis_full_check_agent_linux64 main.go
# 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
make: *** [linux] Error 2

原因及解决方法

安装musl

这是因为macos本身系统库不兼容导致的问题,因为是在macos上编译linux的程序,所以需要在mac上安装musl

musl 是一个轻量级的 libc 库, 与 glibc 相比, 它的代码比较简洁, 体积也更小, 更方便静态编译到程序中。

1
brew install FiloSottile/musl-cross/musl-cross

修改编译参数

修改编译参数入下:

1
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 CC=x86_64-linux-musl-gcc CXX=x86_64-linux-musl-g++ go build -o BIN_NAME

运行程序

通过两个步骤就能正常交叉编译出linux二进制文件了,但上传ubuntu机器上运行可能会报错:

1
2
Failed to execute process './redis_full_check_agent_linux64'. Reason:
The file './redis_full_check_agent_linux64' does not exist or could not be executed.

这是因为ubuntu机器上没有安装musl导致,安装步骤:

1
2
3
4
5
6
# ubuntu
apt-get update -y
apt-get install -y musl
# centos
wget https://copr.fedorainfracloud.org/coprs/ngompa/musl-libc/repo/epel-7/ngompa-musl-libc-epel-7.repo -O /etc/yum.repos.d/ngompa-musl-libc-epel-7.repo
yum install -y musl-libc-static

安装完后,就能正常运行二进制文件了:

1
2
./BIN_NAME
-s, --source or -t, --target not specified

Reference

. 使用go语言进行交叉编译的时候遇到的一些问题
. 使用 musl 库静态编译 rust 程序
. Wiki-Musl

Done.

CATALOG
  1. 1. 环境
  2. 2. 背景
  3. 3. 问题
  4. 4. 原因及解决方法
    1. 4.1. 安装musl
    2. 4.2. 修改编译参数
    3. 4.3. 运行程序
  5. 5. Reference