Caffe编译错误:gflags.cc'静态和动态地链接到此可执行文件中

时间:2015-05-27 07:06:47

标签: c++ makefile deep-learning caffe gflags

我正在尝试按照此tutorial

安装caffe

当我输入最后一个make命令时,基本上我有以下错误:

me@dl-01:/home/me/caffe-master$ make runtest

.build_release/tools/caffe

caffe: command line brew

usage: caffe command args

commands:

train           train or finetune a model

test            score a model

device_query    show GPU diagnostic information

time            benchmark model execution time

Flags from tools/caffe.cpp:
 -gpu (Run in GPU mode on given device ID.) type: int32 default: -1
 -iterations (The number of iterations to run.) type: int32 default: 50
 -model (The model definition protocol buffer text file..) type: string
      default: ""
 -snapshot (Optional; the snapshot solver state to resume training.)
 type: string default: ""
 -solver (The solver definition protocol buffer text file.) type: string
 default: ""
 -weights (Optional; the pretrained weights to initialize finetuning. Cannot
      be set simultaneously with snapshot.) type: string default: ""
.build_release/test/test_all.testbin 0 --gtest_shuffle 
ERROR: something wrong with flag 'flagfile' in file '/root/glog-0.3.3/gflags-master/src/gflags.cc'.  One possibility: file '/root/glog-0.3.3/gflags-master/src/gflags.cc' is being linked both statically and dynamically into this executable.
make: *** [runtest] Error 1

我不明白如何解决此错误。有人之前发现过这个错误吗?我怎么解决呢?

3 个答案:

答案 0 :(得分:10)

你是否已经在其他地方解决了这个问题,我在这里发布答案,以防其他人遇到同样的问题。

首先,这个问题似乎已经出现,因为我们并不总是正确地阅读并盲目地遵循所有指示,认为它们都适用于我们的案例。 提示:他们没有。

在Caffe的安装说明中(假设Ubuntu说明),有一节说明:

  

所有内容都打包在14.04。

sudo apt-get install libgflags-dev libgoogle-glog-dev liblmdb-dev protobuf-compiler

盲目地忽略下一个标题,其中明确指出:

  

剩余依赖项,12.04

我们继续安装这些依赖项,根据需要进行构建和安装,导致出现2个版本的libgflags,一个动态(/usr/lib[/x86_x64]/usr/local/lib中的一个静态)的不幸副作用/ p>

解决

  1. 承诺我们自己会失败,下次我们会正确阅读说明书。
  2. 卸载libgflags

    sudo apt-get remove -y libgflags
    
  3. 删除make install个版本

    sudo rm -f /usr/local/lib/libgflags.a /usr/local/lib/libgflags_nothreads.a
    sudo rm -rf  /usr/local/include/gflags
    
  4. 清洁Caffe构建

    cd <path>/<to>/caffe
    make clean
    
  5. 重新安装libgflags包

    sudo apt-get install -y libgflags-dev
    
  6. 重建Caffe

    make all
    make test
    make runtest
    
  7. Et Voila。现在所有的测试都应该进行,你已经准备好开始学习深海了。

答案 1 :(得分:1)

我还安装了两个库,一个共享的.so库和一个静态的.a库。我删除了它们以及/ usr / local / include / glog文件夹。 当我(交叉)编译系统时,我带来的.so文件,而.a来自本地和最新版本。 最终它归结为以提供.so文件的方式构建glog(本机)。 我从一个干净的下载开始:

git clone git://github.com/google/glog

然后我编辑了CMakeLists.txt。 在哪里说:

add_library (glog
  ${GLOG_SRCS}
)

我把它改为:

add_library (glog SHARED
  ${GLOG_SRCS}
)

接下来,您应该可以按照其他说明进行操作。对于我的特殊情况,我不得不使用稍微不同的说明,而不是说你必须这样做。对我来说是: mkdir build cd build

export CXXFLAGS="-fPIC"
cmake ..
make
sudo make install

这给了我.so文件并将它们放在正确的位置。然后我从caffe开始,它为我修复了错误。

答案 2 :(得分:0)

我已经找到一种方法来分析该问题。就我而言,我是为较旧的ABI进行交叉编译的,因此apt-get不是一个选择,而是手动编译所有依赖项。

首先让我们看一下这个问题实际上是什么。在Google GFlags库中,标志是通过全局对象声明的。运行全局对象的构造函数时,它将调用GFlags库以注册该命令行标志。如果全局构造函数多次运行(由于包含该全局构造函数的库的多个版本已加载到内存中),则GFlags注册方法将因错误而终止。

GLog与这有什么关系?好吧,GLog使用GFlags,它具有全局声明的标志对象。即使GFlags正确链接,但如果多次加载GLog库,也会在GLog中出现指向logging.cc的错误。

听起来像是一团糟,呵呵。即使在大多数情况下将GLog和GFlags链接为共享链接,如果另一个库链接到静态版本或某些其他版本,也请使用kaboom。

幸运的是,如果您愿意进行一些棘手的符号分析,我们可以使用GDB和其他工具来调试此问题。 首先,您要在尝试导入caffe的Python解释器上运行GDB:

gdb --args python -c 'import caffe'

现在,一次运行该程序,以便GDB可以提取它导入的所有库:

(gdb) r

现在,我们可以在打印错误消息的函数(FlagRegistry::RegisterFlag())的位置上设置一个断点,然后再次运行它。请注意,此行号来自我的GFlags(2.2.2)版本,您可能必须查看GFlags版本的源代码并获取行号。

(gdb) break gflags.c:728
(gdb) r

希望,GDB应该在错误的第一个实例上中断(如果不是,请检查是否已使用调试符号构建了gflag)。 查看回溯:

(gdb) bt
#0  google::(anonymous namespace)::FlagRegistry::RegisterFlag (this=0xa33b30, flag=0x1249d20) at dev/gflags-2.2.2/src/gflags.cc:728
#1  0x00007ffff0f3247a in _GLOBAL__sub_I_logging.cc () from prefix/lib/libcaffe2.so
#2  0x00007ffff7de76ca in call_init (l=<optimized out>, argc=argc@entry=3, argv=argv@entry=0x7fffffffdb08, env=env@entry=0x7fffffffdb28) at dl-init.c:72
#3  0x00007ffff7de77db in call_init (env=0x7fffffffdb28, argv=0x7fffffffdb08, argc=3, l=<optimized out>) at dl-init.c:30
#4  _dl_init (main_map=main_map@entry=0xd9c2a0, argc=3, argv=0x7fffffffdb08, env=0x7fffffffdb28) at dl-init.c:120
#5  0x00007ffff7dec8f2 in dl_open_worker (a=a@entry=0x7fffffffcf70) at dl-open.c:575
#6  0x00007ffff7de7574 in _dl_catch_error (objname=objname@entry=0x7fffffffcf60, errstring=errstring@entry=0x7fffffffcf68, mallocedp=mallocedp@entry=0x7fffffffcf5f, 
    operate=operate@entry=0x7ffff7dec4e0 <dl_open_worker>, args=args@entry=0x7fffffffcf70) at dl-error.c:187
#7  0x00007ffff7debdb9 in _dl_open (file=0x9aee70 "prefix/lib/python2.7/site-packages/caffe2/python/caffe2_pybind11_state.so", mode=-2147483646, 
    caller_dlopen=0x51bb39 <_PyImport_GetDynLoadFunc+233>, nsid=-2, argc=<optimized out>, argv=<optimized out>, env=0x7fffffffdb28) at dl-open.c:660
#8  0x00007ffff75ecf09 in dlopen_doit (a=a@entry=0x7fffffffd1a0) at dlopen.c:66
#9  0x00007ffff7de7574 in _dl_catch_error (objname=0xabf9f0, errstring=0xabf9f8, mallocedp=0xabf9e8, operate=0x7ffff75eceb0 <dlopen_doit>, args=0x7fffffffd1a0) at dl-error.c:187
#10 0x00007ffff75ed571 in _dlerror_run (operate=operate@entry=0x7ffff75eceb0 <dlopen_doit>, args=args@entry=0x7fffffffd1a0) at dlerror.c:163
#11 0x00007ffff75ecfa1 in __dlopen (file=<optimized out>, mode=<optimized out>) at dlopen.c:87
#12 0x000000000051bb39 in _PyImport_GetDynLoadFunc ()
<snip>

好多事情要处理,但让我们关注实际上很重要的那一行:

#1  0x00007ffff0f3247a in _GLOBAL__sub_I_logging.cc () from prefix/lib/libcaffe2.so

这是对logging.cc(属于GLog的一部分)中的全局变量的构造函数的调用。如您所见,此调用位于libcaffe2.so中,这意味着GLog已静态链接到libcaffe2.so [我使用的是caffe2,但两者的过程应相同]。

然后可以在google::(anonymous namespace)::FlagRegistry::RegisterFlag上设置断点并从头开始重新运行程序。查看对RegisterFlag()的每次调用,并找出该特定标志首次在何处注册。如果提供该标志的库是共享库,则只能从该.so文件中进行注册,而不能在其他任何地方注册。

要确认诊断,可以使用

nm <library> | grep _GLOBAL__sub_I_logging.cc

在库文件中检查该init函数。找到罪魁祸首后,您需要对其进行重建,以使其不会静态链接到GFlags / GLog。