将assimp库与find_package链接

3

我正在努力将Assimp库与CMake的find_package()函数链接起来。

# ASSIMP search path
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${CMAKE_CURRENT_LIST_DIR}/assimp/)

find_package(assimp REQUIRED)
if (assimp_FOUND)
    link_directories(${ASSIMP_LIBRARY_DIRS})
    include_directories(${ASSIMP_INCLUDE_DIRS})
    target_link_libraries (NervousEngine ${ASSIMP_LIBRARIES})
endif(assimp_FOUND)

我首先的问题是,为什么在使用gcc编译项目时,Cmake没有通过find_package()抛出错误,而是说找不到-lassimp。当然,如果我删除assimp目录的CMAKE_PREFIX_PATH,就可以让它失败。不知何故,CMake未能指示编译命令来链接它???

第二个问题是为什么库无法链接。这是编译命令和ld链接错误:

/usr/bin/c++   -std=gnu++11 -g sourceFiles... o NervousEngine -Wl,-rpath,/home/jointts/CLionProjects/OpenGL/lib/bullet/lib ../lib/bullet/lib/libBulletDynamics.so ../lib/bullet/lib/libBulletCollision.so ../lib/bullet/lib/libLinearMath.so ../lib/bullet/lib/libBulletSoftBody.so -lassimp -lfreetype 
/usr/bin/ld: cannot find -lassimp
collect2: error: ld returned 1 exit status

我不明白为什么链接不正确,我甚至使用了link_directories指令来引导库的搜索。

调试库路径时,我得到了以下结果:

message(${ASSIMP_LIBRARY_DIRS}) -> /home/jointts/CLionProjects/OpenGL/lib/assimp/lib
message(${ASSIMP_LIBRARIES}) -> assimp

所以我认为库的位置本身是正确的,最终会进行下面我输入的库搜索?

${ASSIMP_LIBRARY_DIRS} + ${ASSIMP_LIBRARIES}

/home/jointts/CLionProjects/OpenGL/lib/assimp/lib/libassimp.so

gcc --version输出如下:

gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609

CMake版本为3.9.6


1
link_directories()只会应用于在调用之后创建的目标。所以在你的情况下,它没有任何效果,因为你首先创建了可执行文件,然后才包含lib/CMakeLists.txt - thomas_f
所以顺序应该是link_directories -> add_executable -> target_link_libraries吗? - Jointts
我想我会再制作一个FindAssimp.cmake文件... Bullet似乎可以使用与find_package相同的链接方式进行链接,我猜assimp-config.cmake文件只是有问题。 - Jointts
这里有一个FindASSIMP.cmake文件,适用于任何想要使用相对路径链接库而不使用全局/usr/include /usr/lib文件夹的人 https://gist.github.com/Jointts/a02c15002252fea3dd2c6855bda9090b。理论上,这也可以扩展到任何其他库。我猜编写自己的查找脚本对于CMake来说是必须的;( - Jointts
可能是Cmake无法使用“link_directories”找到库的重复问题。 - Tsyvarev
不是重复的,这只是我尝试过的其中一种解决方案...问题并不特别为 link_directories,因为我也使用了 include_directories(${ASSIMP_INCLUDE_DIRS}) 和 target_link_libraries (NervousEngine ${ASSIMP_LIBRARIES})。 - Jointts
1个回答

0

1:CMake没有抛出错误,因为它找到了该软件包。您通过成功验证ASSIMP_*变量的值来确认了这一点。这些变量由assimp-config.cmake初始化。

2:链接器接收到此标志-lassimp,这需要链接器知道在哪里查找库。由于它未安装在标准位置,因此会失败。在评论中,我们讨论了必须在创建依赖于库的任何目标之前调用link_libraries()。如果在创建目标之前使用link_libraries(),则应该能够简单地将assimp传递给target_link_libraries(),并将其作为-lassimp转发给链接器。

更好的解决方案是向target_link_libraries()提供libassimp.so的绝对路径,target_link_libraries(<target> ${ASSIMP_LIBRARY_DIRS}/libassimp.so)(请注意,这里不使用-l标志前缀库)。但是,请继续阅读。

由于assimp-config.cmake没有创建任何CMake目标,最干净的解决方案是如果CMake能够定位到该软件包,则自己创建一个:

if (assimp_FOUND)
    set(ASSIMP_LIBRARY "assimp")
    add_library(${ASSIMP_LIBRARY} SHARED IMPORTED)
    set_target_properties(${ASSIMP_LIBRARY} PROPERTIES IMPORTED_LOCATION "${ASSIMP_LIBRARY_DIRS}/libassimp.so")
endif(assimp_FOUND)

然后像往常一样链接它:target_link_libraries(<target> ${ASSIMP_LIBRARY})


1
顺便说一下,可以在一个函数中调用assimp_FOUND的if体,方法是使用find_library(ASSIMP_LIBRARY NAMES ${ASSIMP_LIBRARIES} PATH ${ASSIMP_LIBRARY_DIRS})。这样做还可以避免硬编码库文件名。 - Jointts

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接