【问题标题】:Go/Cgo: produce static library without definitions of Go runtime functionsGo/Cgo:生成没有 Go 运行时函数定义的静态库
【发布时间】:2021-04-24 13:58:06
【问题描述】:

有没有办法从 Go 代码生成 C 静态库,但没有 Go 运行时函数定义

理由

  • Project A 使用 go build -buildmode=c-archivelibA.a 创建一个 C 静态库。
  • 运行良好:project B 使用纯 C,能够轻松创建可执行文件,与 libA.a 静态链接,一切都很好。
  • 问题 1:project C 恰好也使用 Go,但想将 libA.a 用作常规 C 库。现在它有一个链接问题:Go 运行时函数,例如 e.g. _cgo_panic 现在在 project C 运行时(因为它使用 Go)和 libA.a 中定义。
  • 问题 2:project D 使用纯 C,与 B 相同。但它想使用来自 project A 的两个不同库,例如libA.a 和一些 libA2.a。遗憾的是,它也没有链接,因为 Go 运行时函数现在在 libA.alibA2.a 中定义。

project Cproject D 面临的问题可以很容易地解决,如果 project A 可以在没有 Go 运行时定义的情况下生成其库。 Project C 可以与 libA.a 链接。 Project D 将与 libA.alibA2.a 和一些 libGo.a 链接,它们将包含所有 Go 运行时内容的定义。

我尝试了什么:

  • 在“项目 C”级别使用链接器标志,例如 -Wl,--allow-multiple-definition。现在它的构建失败并显示一条神秘消息“function symbol table not sorted by program counter”。
  • 从“libA.a”中手动删除go.o(因为它只是一个“ar”存档):不起作用,因为“go.o”还包含我导出函数的实现,所以我删除了太多.
  • 使用go build -buildmode=c-shared。正如预期的那样,它生成了一个使用另一种格式的动态库,所以我不能直接将它用作静态库。

客户端的任何解决方案(例如在project C 的链接阶段找到忽略重复定义的适当方法)也将被视为有效答案。
如果提供足够的证据,我也可以接受否定答案(没有解决方案)。

更新:查看相关问题Is there a way to include multiple c-archive packages in a single binary

【问题讨论】:

  • Go 代码需要 go runtime,不支持加载 go runtime 的多个实例。你不能以这种方式使用 go。
  • 谢谢,这可能是答案。这在任何地方都有记录吗?
  • 据我所知,它只是通过遗漏记录的,除非特别允许,否则我不希望它起作用。让多个 Go 运行时实例在同一个进程空间内协作并非易事。

标签: c go linker static-libraries cgo


【解决方案1】:

正如您所发现的,在当前的实现中,多次使用-buildmode=c-archive 并将结果放入多个共享库是行不通的。基本问题是 Go 运行时必须只有一个,但你有多个运行时。使用-buildmode=c-archive 时,无法隔离不同的运行时。

-buildmode=c-shared 库与 buildmode=c-archive 的不同之处在于它们是使用 -Bsymbolic 构建的,这会强制其所有本地引用都是本地的。效果是我们有多个 Go 运行时,但它们不会相互引用,因此不会造成混淆。

如果您的 C 代码不介意与 -Bsymbolic 链接,您可以尝试添加 -Wl,-Bsymbolic 以在 c-archive 中构建包含 Go 代码的每个共享库。

祝你好运。

【讨论】:

  • 感谢您的回答。我尝试了以下方法: go build -buildmode=c-archive -ldflags="-extldflags '-Wl,-Bsymbolic'" 来构建我的库。好像没有效果。您是否看到任何其他传播链接器标志的方式?
  • 这些标志适用于您的 C 代码,而不适用于 Go、clang -Wl,-Bsymbolic -shared ...g++ -shared -Wl,-Bsymbolic -Wall ...。 go 存档将与以前相同,您只是使用对全局定义的符号引用。
  • 我也在客户端将标志添加到我的 CGO_CFLAGS 和 CGO_LDFLAGS 中。
猜你喜欢
  • 2016-06-25
  • 1970-01-01
  • 2016-10-17
  • 2016-07-12
  • 2021-08-13
  • 2021-10-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多