2.10.3 pkg-config
为不同C/C++库提供编译和链接参数是一项非常繁琐的工作,因此cgo提供了对应pkg-config
工具的支持。 我们可以通过#cgo pkg-config xxx
命令来生成xxx库需要的编译和链接参数,其底层通过调用 pkg-config xxx --cflags
生成编译参数,通过pkg-config xxx --libs
命令生成链接参数。 需要注意的是pkg-config
工具生成的编译和链接参数是C/C++公用的,无法做更细的区分。
pkg-config
工具虽然方便,但是有很多非标准的C/C++库并没有实现对其支持。 这时候我们可以手工为pkg-config
工具创建对应库的编译和链接参数实现支持。
比如有一个名为xxx的C/C++库,我们可以手工创建/usr/local/lib/pkgconfig/xxx.bc
文件:
Name: xxx
Cflags:-I/usr/local/include
Libs:-L/usr/local/lib –lxxx2
其中Name是库的名字,Cflags和Libs行分别对应xxx使用库需要的编译和链接参数。如果bc文件在其它目录, 可以通过PKG_CONFIG_PATH环境变量指定pkg-config
工具的检索目录。
而对应cgo来说,我们甚至可以通过PKG_CONFIG 环境变量可指定自定义的pkg-config程序。 如果是自己实现CGO专用的pkg-config程序,只要处理--cflags
和--libs
两个参数即可。
下面的程序是macos系统下生成Python3的编译和链接参数:
// py3-config.go
func main() {
for _, s := range os.Args {
if s == "--cflags" {
out, _ := exec.Command("python3-config", "--cflags").CombinedOutput()
out = bytes.Replace(out, []byte("-arch"), []byte{}, -1)
out = bytes.Replace(out, []byte("i386"), []byte{}, -1)
out = bytes.Replace(out, []byte("x86_64"), []byte{}, -1)
fmt.Print(string(out))
return
}
if s == "--libs" {
out, _ := exec.Command("python3-config", "--ldflags").CombinedOutput()
fmt.Print(string(out))
return
}
}
}
然后通过以下命令构建并使用自定义的pkg-config
工具:
$ go build -o py3-config py3-config.go
$ PKG_CONFIG=./py3-config go build -buildmode=c-shared -o gopkg.so main.go
具体的细节可以参考Go实现Python模块章节。
学员评价