英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论