gcc 链接器找不到库(openNI)

Posted

技术标签:

【中文标题】gcc 链接器找不到库(openNI)【英文标题】:gcc linker can't find library (openNI) 【发布时间】:2011-11-15 17:03:01 【问题描述】:

谁能给我一些解决这个问题的提示?

我正在尝试编译 "Kinect Matlab"(在 Mac OS 10.7 上),在编译脚本中是以下行:

mex('-v','-L/usr/lib/','-lOpenNI',[...],Filename);

这是 mex 运行的完整命令:(1)

gcc-4.2 -O -Wl,-twolevel_namespace -undefined error -arch x86_64 -Wl,-syslibroot,/Developer/SDKs/MacOSX10.6.sdk -mmacosx-version-min=10.5 -bundle -Wl,-exported_symbols_list,/Applications/MATLAB_R2011a.app/extern/lib/maci64/mexFunction.map -o  "mxNiChangeDepthViewPoint.mexmaci64"  mxNiChangeDepthViewPoint.o  -L/usr/lib/ -lOpenNI -L/Applications/MATLAB_R2011a.app/bin/maci64 -lmx -lmex -lmat -lstdc++

然后我收到以下错误:

ld: library not found for -lOpenNI
collect2: ld returned 1 exit status

    mex: link of ' "mxNiChangeDepthViewPoint.mexmaci64"' failed.

/usr/lib/libOpenNI.dylib 肯定有一个文件。

什么样的事情会导致ld抛出这个错误?

我尝试了什么:

我尝试创建一个名为 libOpenNI.so 的符号链接,就像 jmlopez 建议的那样,没有效果。 难道libOpenNI 是一个32 位库,而ld 因为这个原因看不到它?或者错误会有所不同? 关于上述几点,它表示构建是“通用 x86/x64”

环境变量:

我尝试使用以下命令从 matlab 终端将库添加到环境变量中。没有效果。

setenv('DYLD_LIBRARY_PATH', [getenv('DYLD_LIBRARY_PATH') ':/usr/lib/']);

在 bash 中:

按照这里的建议调用 gcc https://serverfault.com/questions/54736/how-to-check-if-a-library-is-installed 没有问题。

$ gcc -lOpenNi
Undefined symbols for architecture x86_64:
  "_main", referenced from:
      start in crt1.10.6.o

但是,如果我先运行 g++,然后在 (1) 中运行 gcc,则与之前的错误相同。 (找不到库)。为什么 gcc 可以找到库,但是当 matlab 在 (1) 中添加内容时,它会搞砸?

因此,与上述内容相关,我开始从 (1) 中删除所有参数,直到出现不同的错误。我删除了-Wl,-syslibroot,这意味着-syslibroot 将不再传递给ld,这似乎已经修复了它。所以-syslibroot 搞乱了图书馆搜索目录!现在想办法从mex() 调用中删除这个参数。

【问题讨论】:

我之前在使用gcc的时候也遇到过类似的问题。我不太记得扩展名是否是 dylib,但我最终做的是创建一个指向它的符号链接。因此,既然您有 libOpenNI.dylib,请尝试创建一个名为 libOpenNI.so 的链接 【参考方案1】:

您是否尝试将OpenNi 添加到您的LIBRARY_PATH 中?

export LIBRARY_PATH=$LIBRARY_PATH:/YOUR-PATH/OpenNi

【讨论】:

但是如何在终端中输入这个让 Matlab 知道呢? @Noio:你必须把它作为一个环境变量,gcc 或编译make 正在运行。您可以简单地将它放在make 之前或将命令编译为LIBRARY_PATH=$LIBRARY_PATH:/YOUR-PATH/OpenNi make。或者,正如我之前所展示的 export LIBRARY_PATH=$LIBRARY_PATH:/YOUR-PATH/OpenNi; make gcc 在您调用 mex() 时从 matlab 运行。所以环境将是matlab终端。我没有从普通终端运行make 另外,-L 开关不应该处理这个问题吗?:"[...] LD_LIBRARY_PATH 也将在使用 -L 指定的目录之后的链接 (ld) 阶段进行搜索(也如果没有给出 -L 标志)。”【参考方案2】:

第一个选项:如果 libOpenNi 与您正在编译的二进制文件的架构不同,则整个编译器套件可能会忽略它。如果您确实设法让它链接,它可能会崩溃。找到一个本地 64 位库并链接到它。

第二个选项:我对此不是 100% 确定的,但是每当我尝试在一些深奥的 linux 项目上进行链接时,我都会从 -L 指定的路径中的 .a 对象存档开始。如果它链接,那么我将在 x86_64 上添加 -fPIC -shared 以使其针对共享库进行编译。我不确定这是否适用于 OSX:我还没有在那个平台上进行过开发。

【讨论】:

如果架构错误,链接器会抛出那种警告(“未找到”)吗?该库是“通用 x86/x64”。【参考方案3】:

轰!它有效!

好的,这里是:

gcc 调用 (1) 中的-Wl,-syslibroot 选项正在向链接器发送一个-syslibroot 选项,并且不知何故它被预先添加到库搜索路径中(即使它不应该根据cannot specify root sdk directory with syslibroot when linking)

所以,删除这个-syslibroot 可以解决我们的问题,这可以在mexopts.sh 中完成。从默认位置复制 matlab 的版本:

cp /Applications/MATLAB_R2011a.app/bin/mexopts.sh ~/.matlab/R2011a/

然后改变这一行(201):

LDFLAGS="-Wl,-twolevel_namespace -undefined error -arch $ARCHS -Wl,-syslibroot,$SDKROOT -mmacosx-version-min=$MACOSX_DEPLOYMENT_TARGET"

删除-Wl,-syslibroot,$SDKROOT 参数。

此外,我可以从对 mex 的调用中删除 -L/usr/lib 参数,使其变得简单:

 mex('-v','-lOpenNI',['-I' OpenNiPathInclude],Filename);

【讨论】:

以上是关于gcc 链接器找不到库(openNI)的主要内容,如果未能解决你的问题,请参考以下文章

ld 链接器找不到 so 库

ld 链接器找不到 so 库

链接器找不到 Lua 库定义

编译成功后找不到openni2库

gcc找不到静态库中的函数

链接器找不到重载的运算符