问题 CMake无法使用相对文件路径找到静态库


我想玩弄 快板 库,但我似乎无法让我的测试项目正确链接。确切地说,我得到了 cannot find -l<...> 错误,在哪里 <...> 是我指定使用的文件 target_link_libraries。 (详见下文。)

为了记录,我并不是所有关于构建过程的知识,我通常的方法是“单击一个按钮,希望弹出一个可执行文件,如果没有,则依靠试错。”我在这里发现了很多类似的问题,但似乎问题或解决方案与我所遇到的不同。我希望有一个明确的“这就是你做错了什么,而这就是做什么”。

那就是说,这是我的项目结构:

/include
/lib
/src
    main.cpp
CMakeLists.txt

我从中复制的include和lib目录 Allegro二进制包和lib是所有.a文件所在的位置。

这是我的CMakeLists.txt所说的:

cmake_minimum_required(VERSION 3.2)
project(AllegroTest)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -static-libgcc -static-libstdc++ -fpermissive")
add_definitions( -DALLEGRO_STATICLINK )

file(GLOB SOURCES src/*.cpp)
set(SOURCE_FILES ${SOURCES})
add_executable(AllegroTest ${SOURCE_FILES})

include_directories(include)

target_link_libraries(AllegroTest
    liballegro-5.0.10-static-mt.a
    liballegro_acodec-5.0.10-static-mt.a
    liballegro_audio-5.0.10-static-mt.a
    libvorbisfile-1.3.2-static-mt.a
    libvorbis-1.3.2-static-mt.a
    liballegro_color-5.0.10-static-mt.a
    liballegro_dialog-5.0.10-static-mt.a
    liballegro_font-5.0.10-static-mt.a
    liballegro_image-5.0.10-static-mt.a
    liballegro_memfile-5.0.10-static-mt.a
    liballegro_physfs-5.0.10-static-mt.a
    liballegro_primitives-5.0.10-static-mt.a
    liballegro_ttf-5.0.10-static-mt.a
    libdumb-0.9.3-static-mt.a
    libFLAC-1.2.1-static-mt.a
    libfreetype-2.4.8-static-mt.a
    libogg-1.2.1-static-mt.a
    libzlib-1.2.5-static-mt.a
    libopenal-1.14-static-mt.a
)

target_link_libraries(AllegroTest
    libgdiplus.a
    libuuid.a
    libkernel32.a
    libwinmm.a
    libpsapi.a
    libopengl32.a
    libglu32.a
    libuser32.a
    libcomdlg32.a
    libgdi32.a
    libshell32.a
    libole32.a
    libadvapi32.a
    libws2_32.a
    libshlwapi.a
)

这些是我得到的错误:

c:/mingw/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: cannot find -lallegro-5.0.10-static-mt
c:/mingw/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: cannot find -lallegro_acodec-5.0.10-static-mt
c:/mingw/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: cannot find -lallegro_audio-5.0.10-static-mt
<etc.>

我已经尝试以各种可想象的方式指定路径 - 包括将其与用法相结合 link_directories(lib)  - 似乎没有任何效果。

唯一的事情 没有 工作是指定绝对路径(C:/Users/<...>/lib/liballegro-5.0.10-static-mt.a),但我发现这远非理想的方式。

我在这里犯了什么错误,推荐的解决方法是什么?


3687
2018-05-16 11:16


起源



答案:


我推荐的方式  使用绝对路径。我不确定为什么你认为这远非理想;实现目标是微不足道的:

target_link_libraries(AllegroTest
    ${CMAKE_CURRENT_SOURCE_DIR}/lib/liballegro-5.0.10-static-mt.a
    ${CMAKE_CURRENT_SOURCE_DIR}/lib/liballegro_acodec-5.0.10-static-mt.a
    etc.
)

9
2018-05-16 13:07



我觉得,凭借绝对的道路,项目将不再是自成一体的,而是依赖于其环境。我想 CMAKE_CURRENT_SOURCE_DIR 是一种方法,所以谢谢你提到。但是真的没有办法与真正的相对路径合作吗?在我看来应该有。 - vvye
我本来期待的 link_directories(lib) 说实话,但使用 link_directories 气馁 - 即使在其中 自己的文件。找到实例很常见 CMAKE_SOURCE_DIR 和 CMAKE_CURRENT_SOURCE_DIR  - 我认为这实际上是一种很好的做法。它可以节省您必须检查文档的命令,而您不确定它们是否将路径视为相对于源根目录或构建根目录。 - Fraser
至少现在我理解你的不情愿,如果你认为你必须从你自己的机器硬编码绝对路径 - 确实应该不惜一切代价避免:) - Fraser
作为替代方案,您可以随时插入其他内容 find_library 呼叫 这需要硬编码 ${CMAKE_CURRENT_SOURCE_DIR}/lib/... 作为提示,以及可由用户自定义的第二个提示。我个人喜欢留出一个环境变量,允许用户为库注入一个优先于任何硬编码路径的自定义路径。 - ComicSansMS
另外不要忘记清除cmake缓存。有时你需要手动修复配置怪癖。 - Montdidier


答案:


我推荐的方式  使用绝对路径。我不确定为什么你认为这远非理想;实现目标是微不足道的:

target_link_libraries(AllegroTest
    ${CMAKE_CURRENT_SOURCE_DIR}/lib/liballegro-5.0.10-static-mt.a
    ${CMAKE_CURRENT_SOURCE_DIR}/lib/liballegro_acodec-5.0.10-static-mt.a
    etc.
)

9
2018-05-16 13:07



我觉得,凭借绝对的道路,项目将不再是自成一体的,而是依赖于其环境。我想 CMAKE_CURRENT_SOURCE_DIR 是一种方法,所以谢谢你提到。但是真的没有办法与真正的相对路径合作吗?在我看来应该有。 - vvye
我本来期待的 link_directories(lib) 说实话,但使用 link_directories 气馁 - 即使在其中 自己的文件。找到实例很常见 CMAKE_SOURCE_DIR 和 CMAKE_CURRENT_SOURCE_DIR  - 我认为这实际上是一种很好的做法。它可以节省您必须检查文档的命令,而您不确定它们是否将路径视为相对于源根目录或构建根目录。 - Fraser
至少现在我理解你的不情愿,如果你认为你必须从你自己的机器硬编码绝对路径 - 确实应该不惜一切代价避免:) - Fraser
作为替代方案,您可以随时插入其他内容 find_library 呼叫 这需要硬编码 ${CMAKE_CURRENT_SOURCE_DIR}/lib/... 作为提示,以及可由用户自定义的第二个提示。我个人喜欢留出一个环境变量,允许用户为库注入一个优先于任何硬编码路径的自定义路径。 - ComicSansMS
另外不要忘记清除cmake缓存。有时你需要手动修复配置怪癖。 - Montdidier


我之前做过类似的事情,我做的是这样的:

link_directories(lib)
target_link_libraries(my_target
    allegro-5.0.10-static-mt
    allegro_acodec-5.0.10-static-mt
    ...
)

注意没有领先 lib 和尾随 .a


1
2018-05-25 07:22



我不是在贬低,因为这应该有效,但是 docs for docs link_directories 不鼓励使用它来支持通过完整的路径 target_link_libraries。 - Fraser
这对我不起作用。 (很确定这也是我已经尝试过的事情之一。) - vvye
@vvye确实有效。但是“该命令仅适用于调用后创建的目标。”所以说 link_directories 之前 add_executable 解决你的问题。 - duleshi