CMake links against wrong version of library

时间:2018-12-03 13:05:17

标签: c++ linux cmake linker shared-libraries

I have some CMake packages that depend on Protobuf v2.5, and one that depend on Protobuf v3.4. I have v2.5 installed system-wide in /usr, whereas v3.4 is only used in a single package. Therefore, I put the headers for v3.4 in a 3rdparty subdirectory inside the package where it is being used, and then I call include_directories(3rdparty) in my CMakeLists.txt so it can be found.

As for the shared libraries, the .so files for v2.5 are present in /usr/lib/x86_64-linux-gnu, and I installed the .so files for v3.4 to /usr/lib. In short, this is what the directory structure looks like:

v2.5:
headers: /usr/include
libraries: /usr/lib/x86_64-linux-gnu

v3.4:
headers: <MY_PACKAGE_SRC_DIRECTORY>/3rdparty
libraries: /usr/lib

Now, the problem arises when I try to link against v3.4. To simplify things, I don't use any CMake module files to find protobuf v3.4, rather I just add a hard-coded path /usr/lib/libprotobuf.so to the list of libraries to link against when creating a target. But even so, when I run ldd my_target_executable, the result is:

libprotobuf.so.8 => /usr/lib/x86_64-linux-gnu/libprotobuf.so.8

meaning that it is linking against the libraries for v2.5 in /usr/lib/x86_64-linux-gnu, even though I added a hard-coded path to the correct .so file in /usr/lib in the call to target_link_libraries when building this executable.

What is worth noting is that if I remove the .so files in /usr/lib/x86_64-linux-gnu, then it does link against the correct .so file in /usr/lib, so it appears that for some reason, CMake searches in /usr/lib/x86_64-linux-gnu before using the library path that I provide it. How can I change this behavior, or fix this problem in any other way?

UPDATE
The library file for v3.4 /usr/lib/x86_64-linux-gnu/libprotobuf.so is a link to /usr/lib/x86_64-linux-gnu/libprotobuf.so.14 which in turn is a link to the actual file /usr/lib/x86_64-linux-gnu/libprotobuf.so.14.0.0.

Now, if I change the hard-coded path that I give in target_link_libraries from /usr/lib/x86_64-linux-gnu/libprotobuf.so to either the second symlink /usr/lib/x86_64-linux-gnu/libprotobuf.so.14, or to the actual file /usr/lib/x86_64-linux-gnu/libprotobuf.so.14.0.0, then my executable correctly links againt v3.4. It appears that the name of the provided symlink has some effect on CMake's behavior.

1 个答案:

答案 0 :(得分:1)

这不是专门的问题,而是在具有gcc和共享库的Linux上的工作方式。

http://www.yolinux.com/TUTORIALS/LibraryArchives-StaticAndDynamic.html

当您指定@Lock时,会将链接设置为target_link_libraries( target /usr/lib/x86_64-linux-gnu/libprotobuf.so)。在这种情况下,它应该只使用它首先找到的任何版本的库。

-lprotobuf调整cmake生成的链接行以使用特定的库版本。这似乎告诉gcc链接到该版本,它将更改运行时和库搜索时发生的情况。

target_link_libraries

  

在某些情况下,CMake可能会要求链接程序搜索该库(例如/usr/lib/libfoo.so变为-lfoo),例如,当检测到共享库中没有SONAME字段时。有关其他情况的讨论,请参阅策略CMP0060。