Go语言与C库的包链接

huangapple go评论88阅读模式
英文:

Go package linkage with a C library

问题

希望这是一个基本问题。我正在尝试构建一个Go包,其中包含来自用C编写的库的函数。结构基本如下:

package too

/*
#cgo LDFLAGS: -L/usr/local/lib include -lbar
#include mybar.h
*/
import "C"

func MyGoWrapper() {
  C.orig_func()
}

运行go build foo.go会出现对orig_func的"undefined reference"错误。请注意,头文件是mybar.h;我为orig_func创建了一个原型,但它没有包含在原始库中。在进行Go构建之前,我需要重新编译库,包括这个头文件吗?还是我对其他事情有误解?

英文:

I hope this is a basic question. I am trying to build a Go package which includes functions from a library written in C. The structure is basically as follows:

package too

/*
#cgo LDFLAGS: -L/usr/local/lib include -lbar
#include mybar.h
*/
import "C"

func MyGoWrapper () {
  C.orig_func()
}

Running go build foo.go fails with an "undefined reference" for orig_func. Note that the header is mybar.h; I created a prototype for orig_func that was not included in the original library. Do I need to recompile the library first, including this header file, before it will link with the Go build? Or am I misunderstanding something else entirely?

答案1

得分: 3

当链接外部库时,您确实需要为目标架构单独编译它。cgo 无法替代 configure/make(或其他)来编译库;它只知道如何构建包目录中的一些 .c 文件,而库的构建过程可能更复杂。

对于在交叉编译时链接外部库的更大任务,我不太确定如何完成(也不确定您已经完成了哪些步骤)。这个(已关闭的)关于使用 cgo 进行交叉编译的 Go bug 在这里可能会有用。 您可能希望在构建 Go 工具链时设置一些环境变量,这些变量在 godoc cmd/cgo 中有描述:

> 要在交叉编译构建期间启用 cgo,请在使用 make.bash 构建 Go 工具时将 CGO_ENABLED 环境变量设置为 1。此外,将 CC_FOR_TARGET 设置为目标的 C 交叉编译器。在为主机编译时将使用 CC。

> 构建完 Go 工具后,在运行 go 命令时,将忽略 CC_FOR_TARGET。运行 make.bash 时,CC_FOR_TARGET 的值是默认编译器。但是,您可以设置环境变量 CC(而不是 CC_FOR_TARGET)来控制运行 go 工具时使用的编译器。

> 对于 C++ 代码,CXX_FOR_TARGET 的工作方式类似。

该 bug 还提到有人使用 -ldflags="-extld=$(CC)"(其中 $(CC) 是他们想要使用的交叉编译器的名称)。

在您的示例代码中,有一个明确的 -L/usr/local/lib,我认为这样不会起作用:我认为当您为目标构建库时,您将希望将它们放在与主机架构的 lib 不同的目录中。例如,这个 ARM 交叉编译 HOWTO 在某些地方使用了 /usr/local/arm-linux 前缀或 install_root。

英文:

When linking against an external library, you do need to separately compile it for your target architecture. cgo can't replace the configure/make (or whatever) to compile the library; it only knows how to build a few .c files in your package directory, and a library's build process might be more complex.


I'm less sure of how to accomplish the larger task of linking in an external library when cross-compiling (and I'm not sure what you've already done). The (closed) Go bug on cross-compilation with cgo looks useful here. You may want to build the Go toolchain with some environment variables set that are described in godoc cmd/cgo:

> To enable cgo during cross compiling builds, set the CGO_ENABLED
environment variable to 1 when building the Go tools with make.bash.
Also, set CC_FOR_TARGET to the C cross compiler for the target. CC will
be used for compiling for the host.

> After the Go tools are built, when running the go command, CC_FOR_TARGET
is ignored. The value of CC_FOR_TARGET when running make.bash is the
default compiler. However, you can set the environment variable CC, not
CC_FOR_TARGET, to control the compiler when running the go tool.

> CXX_FOR_TARGET works in a similar way for C++ code.

The bug also mentions someone who uses -ldflags="-extld=$(CC)" (where $(CC) is the name of the cross-compiler they want to use).

In your example code there's an explicit -L/usr/local/lib and I don't think that'll work: I think when you build libraries for the target, you're going to want to put them in a directory distinct from the lib for your host arch. For example, this ARM cross-compilation HOWTO uses a /usr/local/arm-linux prefix or install_root in some places.

huangapple
  • 本文由 发表于 2014年11月29日 13:40:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/27199268.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定