英文:
linking 3rd party static libs in cgo library
问题
我有一个Go库,提供了对C++ OpenImageIO库(OpenImageiGO)的绑定。我一直通过标准的动态链接到libOpenImageIO来构建我的绑定,但现在我正在尝试进行静态链接。无论我尝试哪种组合的标志,外部链接器都会失败,并出现大量的“未定义引用”错误。我似乎记得过去曾提出过这个问题,说链接器看到符号的顺序有问题。但我似乎找不到这个信息了。
这是我最近一次构建尝试的简要示例,试图将其与静态构建的boost、OpenColorIO和OpenImageIO进行链接:
$ export CGO_CPPFLAGS="\
-I/path/to/boost/include \
-I/path/to/OpenColorIO/include \
-I/path/to/OpenImageIO/include"
$ export CGO_LDFLAGS="\
-L/path/to/boost/lib -lboost_thread_static -lboost_system_static \
-L/path/to/OpenColorIO/lib -lopencolorio \
-L/path/to/OpenImageIO/lib -lOpenImageIO"
$ go build -v -x --ldflags '-extldflags "-static"' github.com/justinfx/openimageigo
...
CGO_LDFLAGS="/path/to/boost/lib/libboost_system_static.a" "/path/to/boost/lib/libboost_thread_static.a" "/path/to/OpenColorIO/lib/libopencolorio.a" "/path/to/OpenImageIO/lib/libOpenImageIO.a" "-lstdc++" /vol/apps/go/1.3.0/pkg/tool/linux_amd64/cgo -objdir $WORK/github.com/justinfx/openimageigo/_obj/ -- -I/path/to/boost/include -I/path/to/OpenColorIO/include -I/path/to/OpenImageIO/include -I./cpp -I $WORK/github.com/justinfx/openimageigo/_obj/ -I/path/to/boost/include -I/path/to/OpenColorIO/include -I/path/to/OpenImageIO/include color.go imagebuf.go imagebufalgo.go imagecache.go imageinput.go imageoutput.go imagespec.go oiio.go roi.go
...
/usr/bin/g++ -I . -fPIC -m64 -pthread -fmessage-length=0 -I/path/to/boost/include -I/path/to/OpenColorIO/include -I/path/to/OpenImageIO/include -I./cpp -I $WORK/github.com/justinfx/openimageigo/_obj/ -g -O2 -o $WORK/github.com/justinfx/openimageigo/_obj/all.cpp.o -c ./all.cpp
/usr/bin/g++ -I . -fPIC -m64 -pthread -fmessage-length=0 -o $WORK/github.com/justinfx/openimageigo/_obj/_cgo_.o $WORK/github.com/justinfx/openimageigo/_obj/_cgo_main.o $WORK/github.com/justinfx/openimageigo/_obj/_cgo_export.o $WORK/github.com/justinfx/openimageigo/_obj/color.cgo2.o $WORK/github.com/justinfx/openimageigo/_obj/imagebuf.cgo2.o $WORK/github.com/justinfx/openimageigo/_obj/imagebufalgo.cgo2.o $WORK/github.com/justinfx/openimageigo/_obj/imagecache.cgo2.o $WORK/github.com/justinfx/openimageigo/_obj/imageinput.cgo2.o $WORK/github.com/justinfx/openimageigo/_obj/imageoutput.cgo2.o $WORK/github.com/justinfx/openimageigo/_obj/imagespec.cgo2.o $WORK/github.com/justinfx/openimageigo/_obj/oiio.cgo2.o $WORK/github.com/justinfx/openimageigo/_obj/roi.cgo2.o $WORK/github.com/justinfx/openimageigo/_obj/all.cpp.o /path/to/boost/lib/libboost_system_static.a /path/to/boost/lib/libboost_thread_static.a /path/to/OpenColorIO/lib/libopencolorio.a /path/to/OpenImageIO/lib/libOpenImageIO.a -lstdc++
这里是一些挑选出来的错误,因为输出非常长:
/path/to/OpenImageIO/lib/libOpenImageIO.a(OpenImageIO_dist^src^libOpenImageIO^color_ocio.cpp.o): 在函数 `ColorConfig' 中:
/path/to/OpenImageIO/OpenImageIO_dist/src/libOpenImageIO/color_ocio.cpp:141: 对 `OpenColorIO::v1::SetLoggingLevel(OpenColorIO::v1::LoggingLevel)' 的未定义引用
...
/path/to/OpenImageIO/lib/libOpenImageIO.a(OpenImageIO_dist^src^libOpenImageIO^imagebufalgo_copy.cpp.o): 在函数 `boost::shared_mutex::lock()' 中:
/path/to/boost/include/boost/thread/pthread/shared_mutex.hpp:138: 对 `boost::this_thread::disable_interruption::~disable_interruption()' 的未定义引用
OpenImageIO似乎找不到OpenColorIO的引用。而且,OpenImageIO似乎找不到boost的引用。看起来发生链接时的顺序不会使OpenImageIO可用于OpenColorIO或boost,所以我得到了一堆符号错误。
我希望我在构建过程中做了一些简单而愚蠢的事情,可以纠正。但是cgo与外部库的静态链接似乎比默认的动态链接方法更复杂一些。
##更新 #1
@james-henstridge给出的答案是正确的,我几乎完全构建完成,只剩下一个小问题。我得到了对OpenColorIO
所需的yaml-cpp
的失败引用,尽管我似乎有正确的顺序。
这是我最新的环境,我已经解决了所有必须添加的显式静态库:
$ export CGO_CPPFLAGS="-I/usr/local/include -I/usr/include"
$ export CGO_LDFLAGS="\
-L/usr/local/lib \
-L/usr/lib \
-L/usr/lib/x86_64-linux-gnu \
-lOpenImageIO \
-lHalf -lIex -lfreetype -lIlmThread -lImath -lIlmImf -lIlmThread \
-lOpenColorIO \
-lyaml-cpp -ltinyxml \
-lboost_regex -lboost_filesystem -lboost_thread -lboost_system \
-ltiff -lgif -lpng -ljpeg -lz \
-lrt -ldl"
$ go test -v -x --ldflags '-extldflags "-static"' github.com/justinfx/openimageigo
...
/home/justin/src/OpenColorIO/src/core/OCIOYaml.cpp:329: 对 `YAML::Node::begin() const' 的未定义引用
...
/home/justin/src/OpenColorIO/build/ext/dist/include/yaml-cpp/nodereadimpl.h:79: 对 `YAML::Node::GetScalar(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&) const' 的未定义引用
...
/usr/local/lib/libOpenColorIO.a(OCIOYaml.cpp.o): 在函数 `_FindFromNodeAtIndex' 中:
/home/justin/src/OpenColorIO/build/ext/dist/include/yaml-cpp/nodeutil.h:53: 对 `YAML::Node::FindAtIndex(unsigned long) const' 的未定义引用
collect2: ld 返回 1 退出状态
##更新 #2
关于更新 #1,请不用担心。它只与OpenColorIO
有关,而不是一般问题。
英文:
I have a Go library that provides bindings for the C++ OpenImageIO library (OpenImageiGO). I've been happily building my bindings via the standard dynamic linking to libOpenImageIO, but am now trying to link statically. I'm running into an issue where no matter which combination of flags I try, the external linker fails with a ton of "undefined reference" errors. I seem to recall seeing this issue raised in the past, saying that there was an issue regarding the order in which the linker saw the symbols. But I can't seem to find this information again.
Here is a brief example of my most recent build attempt, trying to get it to link against static builds of boost, OpenColorIO, and OpenImageIO :
$ export CGO_CPPFLAGS="\
-I/path/to/boost/include \
-I/path/to/OpenColorIO/include \
-I/path/to/OpenImageIO/include"
$ export CGO_LDFLAGS="\
-L/path/to/boost/lib -lboost_thread_static -lboost_system_static \
-L/path/to/OpenColorIO/lib -lopencolorio \
-L/path/to/OpenImageIO/lib -lOpenImageIO"
$ go build -v -x --ldflags '-extldflags "-static"' github.com/justinfx/openimageigo
...
CGO_LDFLAGS="/path/to/boost/lib/libboost_system_static.a" "/path/to/boost/lib/libboost_thread_static.a" "/path/to/OpenColorIO/lib/libopencolorio.a" "/path/to/OpenImageIO/lib/libOpenImageIO.a" "-lstdc++" /vol/apps/go/1.3.0/pkg/tool/linux_amd64/cgo -objdir $WORK/github.com/justinfx/openimageigo/_obj/ -- -I/path/to/boost/include -I/path/to/OpenColorIO/include -I/path/to/OpenImageIO/include -I./cpp -I $WORK/github.com/justinfx/openimageigo/_obj/ -I/path/to/boost/include -I/path/to/OpenColorIO/include -I/path/to/OpenImageIO/include color.go imagebuf.go imagebufalgo.go imagecache.go imageinput.go imageoutput.go imagespec.go oiio.go roi.go
...
/usr/bin/g++ -I . -fPIC -m64 -pthread -fmessage-length=0 -I/path/to/boost/include -I/path/to/OpenColorIO/include -I/path/to/OpenImageIO/include -I./cpp -I $WORK/github.com/justinfx/openimageigo/_obj/ -g -O2 -o $WORK/github.com/justinfx/openimageigo/_obj/all.cpp.o -c ./all.cpp
/usr/bin/g++ -I . -fPIC -m64 -pthread -fmessage-length=0 -o $WORK/github.com/justinfx/openimageigo/_obj/_cgo_.o $WORK/github.com/justinfx/openimageigo/_obj/_cgo_main.o $WORK/github.com/justinfx/openimageigo/_obj/_cgo_export.o $WORK/github.com/justinfx/openimageigo/_obj/color.cgo2.o $WORK/github.com/justinfx/openimageigo/_obj/imagebuf.cgo2.o $WORK/github.com/justinfx/openimageigo/_obj/imagebufalgo.cgo2.o $WORK/github.com/justinfx/openimageigo/_obj/imagecache.cgo2.o $WORK/github.com/justinfx/openimageigo/_obj/imageinput.cgo2.o $WORK/github.com/justinfx/openimageigo/_obj/imageoutput.cgo2.o $WORK/github.com/justinfx/openimageigo/_obj/imagespec.cgo2.o $WORK/github.com/justinfx/openimageigo/_obj/oiio.cgo2.o $WORK/github.com/justinfx/openimageigo/_obj/roi.cgo2.o $WORK/github.com/justinfx/openimageigo/_obj/all.cpp.o /path/to/boost/lib/libboost_system_static.a /path/to/boost/lib/libboost_thread_static.a /path/to/OpenColorIO/lib/libopencolorio.a /path/to/OpenImageIO/lib/libOpenImageIO.a -lstdc++
And here are some of the cherry-picked errors, since it was a very long bit of output:
/path/to/OpenImageIO/lib/libOpenImageIO.a(OpenImageIO_dist^src^libOpenImageIO^color_ocio.cpp.o): In function `ColorConfig':
/path/to/OpenImageIO/OpenImageIO_dist/src/libOpenImageIO/color_ocio.cpp:141: undefined reference to `OpenColorIO::v1::SetLoggingLevel(OpenColorIO::v1::LoggingLevel)'
...
/path/to/OpenImageIO/lib/libOpenImageIO.a(OpenImageIO_dist^src^libOpenImageIO^imagebufalgo_copy.cpp.o): In function `boost::shared_mutex::lock()':
/path/to/boost/include/boost/thread/pthread/shared_mutex.hpp:138: undefined reference to `boost::this_thread::disable_interruption::~disable_interruption()'
OpenImageIO can't seem to find references for OpenColorIO. And, OpenImageIO can't seem to find references for boost. It appears like the order in which things are happening during the linking isn't making the OpenColorIO or boost symbols available to OpenImageIO, so I get a bunch of symbol errors.
I'm hoping I am doing something simple and stupid that can be corrected in my build process. But the cgo static linking with external libs does seem a touch more complicated than the default dynamic linking approach.
##Update #1
The answer given by @james-henstridge was right on, and I am almost fully built, except for one last hiccup. I'm getting failing references for yaml-cpp
, needed by OpenColorIO
, even though it seems I have the correct order.
Here is my latest env, where I have worked through all of the explicit static libs that had to be added:
$ export CGO_CPPFLAGS="-I/usr/local/include -I/usr/include"
$ export CGO_LDFLAGS="\
-L/usr/local/lib \
-L/usr/lib \
-L/usr/lib/x86_64-linux-gnu \
-lOpenImageIO \
-lHalf -lIex -lfreetype -lIlmThread -lImath -lIlmImf -lIlmThread \
-lOpenColorIO \
-lyaml-cpp -ltinyxml \
-lboost_regex -lboost_filesystem -lboost_thread -lboost_system \
-ltiff -lgif -lpng -ljpeg -lz \
-lrt -ldl"
$ go test -v -x --ldflags '-extldflags "-static"' github.com/justinfx/openimageigo
...
/home/justin/src/OpenColorIO/src/core/OCIOYaml.cpp:329: undefined reference to `YAML::Node::begin() const'
...
/home/justin/src/OpenColorIO/build/ext/dist/include/yaml-cpp/nodereadimpl.h:79: undefined reference to `YAML::Node::GetScalar(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&) const'
...
/usr/local/lib/libOpenColorIO.a(OCIOYaml.cpp.o): In function `_FindFromNodeAtIndex':
/home/justin/src/OpenColorIO/build/ext/dist/include/yaml-cpp/nodeutil.h:53: undefined reference to `YAML::Node::FindAtIndex(unsigned long) const'
collect2: ld returned 1 exit status
##Update #2
Nevermind about update #1. It was specifically related to OpenColorIO
and not a general issue.
答案1
得分: 7
-l
标志的顺序在链接静态库时很重要。如果你使用-lfoo -lbar -lbaz
进行链接,那么libbar.a
所需的任何符号只会在libbar.a
和libbaz.a
中搜索。即使libfoo.a
包含你需要的符号,链接器也不会找到它们。
发生的情况是,对于每个库,链接器会解压存档并添加包含之前引用的符号的对象文件。如果存档中的特定对象文件不需要,它将被忽略。
解决方法是确保每个库在链接器标志中列在它所依赖的任何库之前。如果存在任何依赖循环(不应该有),可能需要将库列两次。
英文:
The order of the -l
flags matters when you are linking with static libraries. If you link using -lfoo -lbar -lbaz
, any symbols required by libbar.a
will only be searched for in libbar.a
and libbaz.a
. Even if libfoo.a
contains the symbols you're after, the linker won't find them.
What is happening is that for each library, the linker unpacks the archive and adds the object files that contain symbols referenced by whatever came before. If a particular object file in the archive isn't needed, it is ignored.
The fix is to make sure every library is listed before any it depends on in the linker flags. If there are any dependency loops (which there shouldn't be), it may be necessary to list a library twice.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论