Golang中CGO在Mac上如何链接整个库

Golang中CGO在Mac上如何链接整个库 我正在使用一个.a文件格式的库,该库需要在链接过程中被完整导入。

不幸的是,标志-Wl,-all_load在MacOS上不起作用,而标志-Wl,--whole-archive在Linux上不起作用:

#cgo darwin LDFLAGS: -L.. -Wl,-all_load -lmy_lib

go build _/Users/thierryfournier/git/my-lib/my_lib: invalid flag in #cgo LDFLAGS: -Wl,-all_load

在Linux上使用完整归档也不行:

#cgo LDFLAGS: -L.. -Wl,--whole-archive -lmy_lib

go build _/home/thierry/my_lib/my_lib: invalid flag in #cgo LDFLAGS: -Wl,--whole-archive

因此,我找不到任何方法来嵌入整个库。

  • 我找不到理解链接器如何被调用的方法。
  • 我找不到关于支持哪些标志的文档。

如果有人有解决方案或线索,将不胜感激。

谢谢。


更多关于Golang中CGO在Mac上如何链接整个库的实战教程也可以访问 https://www.itying.com/category-94-b0.html

7 回复

“不起作用”具体是什么意思?你遇到错误了吗?

更多关于Golang中CGO在Mac上如何链接整个库的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


谢谢。我会试试。

嗨,

这是正确的解决方案!

我添加了一个不太优雅的 CGO_LDFLAGS_ALLOW='*' 环境变量,然后它就工作了。

是的,帖子中的错误是:

go build _/home/thierry/my_lib/my_lib: invalid flag in #cgo LDFLAGS: -Wl,--whole-archive

invalid flag in #cgo LDFLAGS: -Wl,--whole-archive

cgo 似乎无法识别包含逗号的子选项。

请在 golang-nuts 上发布你的问题。

采用Ian的建议,

https://groups.google.com/d/msg/golang-nuts/0ANTUXa59aU/yFTAHuRCBQAJ 将这些标志添加到CGO_LDFLAGS_ALLOW环境变量中。

Command cgo

Using cgo with the go command

出于安全原因,只允许使用有限的标志集,特别是-D、-U、-I和-l。要允许额外的标志,请将CGO_CFLAGS_ALLOW设置为匹配新标志的正则表达式。要禁止原本允许的标志,请将CGO_CFLAGS_DISALLOW设置为匹配必须禁止的参数的正则表达式。在这两种情况下,正则表达式必须匹配完整的参数:要允许-mfoo=bar,请使用CGO_CFLAGS_ALLOW=’-mfoo.*’,而不仅仅是CGO_CFLAGS_ALLOW=’-mfoo’。类似命名的变量控制允许的CPPFLAGS、CXXFLAGS、FFLAGS和LDFLAGS。

对于Linux,

#cgo linux LDFLAGS: -L.. -Wl,--whole-archive -lmy_lib -Wl,--no-whole-archive
CGO_LDFLAGS_ALLOW='-Wl,--(?:no-)?whole-archive' go build

在Golang的CGO中,MacOS和Linux平台确实需要使用不同的链接器标志来链接整个静态库。问题在于#cgo指令中不能直接使用-Wl,前缀的链接器标志,需要通过CGO_LDFLAGS环境变量或构建标签来设置。

以下是解决方案:

1. 使用环境变量设置(推荐)

对于MacOS:

export CGO_LDFLAGS="-L.. -Wl,-all_load -lmy_lib"
go build

对于Linux:

export CGO_LDFLAGS="-L.. -Wl,--whole-archive -lmy_lib -Wl,--no-whole-archive"
go build

2. 在Go文件中使用构建标签

创建两个文件,分别处理不同平台:

my_lib_darwin.go

//go:build darwin
// +build darwin

package main

/*
#cgo darwin LDFLAGS: -L.. -lmy_lib
*/
import "C"

my_lib_linux.go

//go:build linux
// +build linux

package main

/*
#cgo linux LDFLAGS: -L.. -lmy_lib
*/
import "C"

然后在构建时通过环境变量传递链接器标志:

# MacOS
CGO_LDFLAGS="-Wl,-all_load" go build

# Linux
CGO_LDFLAGS="-Wl,--whole-archive -Wl,--no-whole-archive" go build

3. 使用Makefile或构建脚本

创建Makefile

UNAME := $(shell uname)

ifeq ($(UNAME), Darwin)
CGO_LDFLAGS = -Wl,-all_load
else
CGO_LDFLAGS = -Wl,--whole-archive -Wl,--no-whole-archive
endif

build:
    CGO_LDFLAGS="$(CGO_LDFLAGS)" go build -o myapp

4. 直接指定库文件路径

如果.a文件路径明确,可以直接链接文件而不是使用-l选项:

/*
#cgo darwin LDFLAGS: ../libmy_lib.a -Wl,-all_load
#cgo linux LDFLAGS: ../libmy_lib.a -Wl,--whole-archive
*/
import "C"

调试链接器调用

go build -x -work

这会显示详细的构建过程,包括链接器调用的完整命令。

回到顶部