如何说服Go去寻找C库

时间:2016-07-10 20:42:05

标签: cgo go-imagick

在构建使用已安装到非标准位置的ImageMagick库的go程序时,有人能告诉我我做错了什么。

我认为我看到的是程序构建,但是一个告诉程序查看动态库的非标准位置的标志没有设置某处所以程序无法找到图书馆。

重现的步骤是:

将ImageMagick配置为安装到非标准目录并构建它:

# ./configure --prefix="/temp/imagemagick-temp" --without-magick-plus-plus --without-perl --disable-openmp --with-gvc=no
# make install

将pkgconfig目录添加到PKG_CONFIG_PATH,以便pkg-config可以找到它。

# export PKG_CONFIG_PATH=/temp/imagemagick-temp/lib/pkgconfig

检查pkg-config是否满意并且可以找到它:

# pkg-config --cflags --libs MagickWand MagickCore
-DMAGICKCORE_HDRI_ENABLE=0 -DMAGICKCORE_QUANTUM_DEPTH=16 -I/temp/imagemagick-temp/include/ImageMagick-6  -L/temp/imagemagick-temp/lib -lMagickWand-6.Q16 -lMagickCore-6.Q16

构建程序并捕获所有输出:

# go build -v -x debug.go > debug_build.txt 2>&1

尝试运行它:

# ./debug
./debug: error while loading shared libraries: libMagickWand-6.Q16.so.2: cannot open shared object file: No such file or directory

我还通过strace运行程序来捕获所有系统调用,下面是捕获。它表明程序没有在libary文件的正确位置查找。

我需要做些什么才能使程序能够在该自定义位置找到该库?

如果我手动设置CGO_CFLAGS和CGO_LDFLAGS,然后使用'no_pkgconfig'选项集进行构建,我会得到相同的结果。

# export CGO_CFLAGS="-DMAGICKCORE_HDRI_ENABLE=0 -DMAGICKCORE_QUANTUM_DEPTH=16 -I/temp/imagemagick-temp/include/ImageMagick-6"
# export CGO_LDFLAGS="-L/temp/imagemagick-temp/lib -lMagickWand-6.Q16 -lMagickCore-6.Q16"
# go build -tags no_pkgconfig debug.go
# ./debug
./debug: error while loading shared libraries: libMagickWand-6.Q16.so.2: cannot open shared object file: No such file or directory

如果重要我在Centos6.4上使用“go version go1.6.2 linux / amd64”

debug.go源文件

package main

/*
#cgo !no_pkgconfig pkg-config: MagickWand MagickCore
#include <wand/MagickWand.h>
*/
import "C"
import "fmt"

type KernelInfoType int

const (
    KERNEL_UNDEFINED     KernelInfoType = C.UndefinedKernel
)

func main() {
    fmt.Println("Hello world")
}

这是构建的输出:

WORK=/tmp/go-build568335569
command-line-arguments
mkdir -p $WORK/command-line-arguments/_obj/
mkdir -p $WORK/command-line-arguments/_obj/exe/
cd /home/github/golang/goworkspace/src/debug
pkg-config --cflags MagickWand MagickCore
pkg-config --libs MagickWand MagickCore
CGO_LDFLAGS="-g" "-O2" "-L/temp/imagemagick-temp/lib" "-lMagickWand-6.Q16" "-lMagickCore-6.Q16" /home/github/golang/go/pkg/tool/linux_amd64/cgo -objdir $WORK/command-line-arguments/_obj/ -importpath command-line-arguments -- -DMAGICKCORE_HDRI_ENABLE=0 -DMAGICKCORE_QUANTUM_DEPTH=16 -I/temp/imagemagick-temp/include/ImageMagick-6 -I $WORK/command-line-arguments/_obj/ debug.go
gcc -I . -fPIC -m64 -pthread -fmessage-length=0 -DMAGICKCORE_HDRI_ENABLE=0 -DMAGICKCORE_QUANTUM_DEPTH=16 -I/temp/imagemagick-temp/include/ImageMagick-6 -I $WORK/command-line-arguments/_obj/ -g -O2 -o $WORK/command-line-arguments/_obj/_cgo_main.o -c $WORK/command-line-arguments/_obj/_cgo_main.c
gcc -I . -fPIC -m64 -pthread -fmessage-length=0 -DMAGICKCORE_HDRI_ENABLE=0 -DMAGICKCORE_QUANTUM_DEPTH=16 -I/temp/imagemagick-temp/include/ImageMagick-6 -I $WORK/command-line-arguments/_obj/ -g -O2 -o $WORK/command-line-arguments/_obj/_cgo_export.o -c $WORK/command-line-arguments/_obj/_cgo_export.c
gcc -I . -fPIC -m64 -pthread -fmessage-length=0 -DMAGICKCORE_HDRI_ENABLE=0 -DMAGICKCORE_QUANTUM_DEPTH=16 -I/temp/imagemagick-temp/include/ImageMagick-6 -I $WORK/command-line-arguments/_obj/ -g -O2 -o $WORK/command-line-arguments/_obj/debug.cgo2.o -c $WORK/command-line-arguments/_obj/debug.cgo2.c
gcc -I . -fPIC -m64 -pthread -fmessage-length=0 -o $WORK/command-line-arguments/_obj/_cgo_.o $WORK/command-line-arguments/_obj/_cgo_main.o $WORK/command-line-arguments/_obj/_cgo_export.o $WORK/command-line-arguments/_obj/debug.cgo2.o -g -O2 -L/temp/imagemagick-temp/lib -lMagickWand-6.Q16 -lMagickCore-6.Q16
/home/github/golang/go/pkg/tool/linux_amd64/cgo -objdir $WORK/command-line-arguments/_obj/ -dynpackage main -dynimport $WORK/command-line-arguments/_obj/_cgo_.o -dynout $WORK/command-line-arguments/_obj/_cgo_import.go
cd $WORK
gcc -I . -fPIC -m64 -pthread -fmessage-length=0 -no-pie -c trivial.c
cd /home/github/golang/goworkspace/src/debug
gcc -I . -fPIC -m64 -pthread -fmessage-length=0 -o $WORK/command-line-arguments/_obj/_all.o $WORK/command-line-arguments/_obj/_cgo_export.o $WORK/command-line-arguments/_obj/debug.cgo2.o -g -O2 -L/temp/imagemagick-temp/lib -Wl,-r -nostdlib -Wl,--build-id=none
/home/github/golang/go/pkg/tool/linux_amd64/compile -o $WORK/command-line-arguments.a -trimpath $WORK -p main -buildid f97632daf57e18f83c78ba78cc2d1ac8f96a4d1f -D _/home/github/golang/goworkspace/src/debug -I $WORK -pack $WORK/command-line-arguments/_obj/_cgo_gotypes.go $WORK/command-line-arguments/_obj/debug.cgo1.go $WORK/command-line-arguments/_obj/_cgo_import.go
pack r $WORK/command-line-arguments.a $WORK/command-line-arguments/_obj/_all.o # internal
cd .
/home/github/golang/go/pkg/tool/linux_amd64/link -o $WORK/command-line-arguments/_obj/exe/a.out -L $WORK -extld=gcc -buildmode=exe -buildid=f97632daf57e18f83c78ba78cc2d1ac8f96a4d1f $WORK/command-line-arguments.a
cp $WORK/command-line-arguments/_obj/exe/a.out debug

这是strace捕获的输出,表明程序没有找到正确的位置。

execve("./debug", ["./debug"], [/* 28 vars */]) = 0
brk(0)                                  = 0xc44000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7facec440000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=30417, ...}) = 0
mmap(NULL, 30417, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7facec438000
close(3)                                = 0
open("/lib64/tls/x86_64/libMagickWand-6.Q16.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat("/lib64/tls/x86_64", 0x7fff50c5d9e0) = -1 ENOENT (No such file or directory)
open("/lib64/tls/libMagickWand-6.Q16.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat("/lib64/tls", {st_mode=S_IFDIR|0555, st_size=4096, ...}) = 0
open("/lib64/x86_64/libMagickWand-6.Q16.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat("/lib64/x86_64", 0x7fff50c5d9e0)   = -1 ENOENT (No such file or directory)
open("/lib64/libMagickWand-6.Q16.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat("/lib64", {st_mode=S_IFDIR|0555, st_size=12288, ...}) = 0
open("/usr/lib64/tls/x86_64/libMagickWand-6.Q16.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat("/usr/lib64/tls/x86_64", 0x7fff50c5d9e0) = -1 ENOENT (No such file or directory)
open("/usr/lib64/tls/libMagickWand-6.Q16.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat("/usr/lib64/tls", {st_mode=S_IFDIR|0555, st_size=4096, ...}) = 0
open("/usr/lib64/x86_64/libMagickWand-6.Q16.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat("/usr/lib64/x86_64", 0x7fff50c5d9e0) = -1 ENOENT (No such file or directory)
open("/usr/lib64/libMagickWand-6.Q16.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat("/usr/lib64", {st_mode=S_IFDIR|0555, st_size=20480, ...}) = 0
writev(2, [{"./debug", 7}, {": ", 2}, {"error while loading shared libra"..., 36}, {": ", 2}, {"libMagickWand-6.Q16.so.2", 24}, {": ", 2}, {"cannot open shared object file", 30}, {": ", 2}, {"No such file or directory", 25}, {"\n", 1}], 10./debug: error while loading shared libraries: libMagickWand-6.Q16.so.2: cannot open shared object file: No such file or directory
) = 131
exit_group(127)                         = ?
+++ exited with 127 +++

1 个答案:

答案 0 :(得分:1)

默认情况下,iMagick库设置为依赖于pkg-config,以使其与包管理器的标准ImageMagick安装兼容。它允许您使用构建标记告诉它不要使用pkg-config,而是依靠您自己提供的env来定位包和库。

这实际上是在项目README中定义的:

  

构建代码

     

如果要在构建时手动指定CGO_CFLAGS / CGO_LDFLAGS,   例如静态构建或没有pkg-config,你可以使用   “no_pkgconfig”构建标记:

go build -tags no_pkgconfig gopkg.in/gographics/imagick.v2/imagick

在我自己的使用iMagick的项目中,我使用自定义构建标记和自定义ImageMagick位置。

更新

由于您已经更新了问题,现在很明显您的问题不是Go问题,而是需要在运行时动态加载库的二进制文件的标准linux问题(您可以看到有关共享库的详细信息)工作here

执行以下操作并解决运行时问题:

$ export LD_LIBRARY_PATH=/temp/imagemagick-temp/lib:$LD_LIBRARY_PATH

LD_LIBRARY_PATH包含程序启动时链接器应搜索的路径列表。在构建程序时,您实际上已经成功提供了正确的信息,您可以通过执行以下操作来确认:

$ ldd ./debug

在前面提到的link中,您还可以阅读有关如何在构建二进制文件时提供rpath的信息。这是一个被烘焙到二进制文件中的路径,告诉链接器在该位置搜索依赖项。它允许您避免将LD_LIBRARY_PATH设置为该特定二进制文件的自定义ImageMagick位置。