CMake,可执行文件无法找到DLL

9

我正在尝试在Windows上使用CMake设置一个项目。

这是我的项目结构:

  • GameEngine
    • .git
    • build
    • include
    • source
    • testing
    • CMakeLists.txt

想法是"source"目录包含GameEngine库的所有.cpp文件,"include"目录包含所有头文件,而"testing"目录用于测试库。因此,它应该依赖于GameEngine.dll和GameEngine.lib(在Windows上)。

我的顶层CMakeLists.txt包含:

    cmake_minimum_required(VERSION 2.7)
    PROJECT( GameEngine )

    include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include )

    ADD_SUBDIRECTORY( source )
    add_subdirectory( testing )

"source"目录中的CMakeLists.txt包含以下内容:
    project(GameEngineLib)

    file(GLOB src "*.cpp" "../include/*.h")

    add_library(${PROJECT_NAME} SHARED ${src})

"testing"目录下的CMakeLists.txt文件包含:

    project(Testing)

    file(GLOB src "*.h" "*.cpp")

    ADD_EXECUTABLE( ${PROJECT_NAME} ${src})
    target_link_libraries(${PROJECT_NAME} GameEngineLib)

在Linux系统上一切正常。构建后,会得到两个文件夹(加上其他一些文件),"testing"和"source",以及一个Makefile,该文件可以输出一个可执行文件和一个.so文件。而且,可执行文件已经知道在哪里找到.so文件,所以我可以直接运行而不会出现任何错误。
问题出现在使用Visual Studio在Windows上进行构建时。除了Testing可执行文件之外,一切都正常。构建"All_Build"项目后,Testing可执行文件会报错,提示找不到GameEngineLib.dll。
我试图在Google上搜索如何解决这个问题,但大多数解决方案都说你必须手动更改Visual Studio中的设置,以查找dll文件的位置。
但是,如果我与多个开发人员合作,我不希望每个使用Visual Studio的开发人员都必须进入项目并更改设置。
难道没有一种方法可以告诉CMake自动将GameEngineLib.dll复制到Tester.exe的文件夹中吗?

我使用的一个选项是在除了顶层之外的所有项目()中删除,并在add_subdirectory()之前在根CMakeLists.txt中设置输出文件夹。 - drescherjm
有没有办法告诉CMake自动将GameEngineLib.dll复制到Tester.exe的文件夹中?在Stack Overflow上有许多关于使用CMake复制.dll文件的问题,请选择其中一个并继续。 - Tsyvarev
2个回答

7
我正在尝试为OpenCV 1.0.0提供CMake支持,遇到了非常相似的情况。也就是说,在我自己的解决方案中,有一个共享库(.dll)和一个从我的源文件和头文件构建而来的可执行文件(.exe)。当执行那个.exe文件时,我们该如何确保.exe可以找到.dll文件?
正如@drescherjm所评论的那样,解决方法是:在根目录下的CMakeLists.txt文件中,在add_subdirectory()之前添加这两行代码:
set(LIBRARY_OUTPUT_PATH "${CMAKE_BINARY_DIR}")
set(EXECUTABLE_OUTPUT_PATH "${CMAKE_BINARY_DIR}")

3

我曾经在尝试使用cmocka库创建测试时遇到了类似的问题。

即使使用CMake通过find_library命令找到了您的库,例如

find_library(<SOME_VAR> NAMES lib_name PATHS "where/to/search")

您仍然会遇到这个问题。

Windows执行文件将无法找到.dll文件。您可以通过将此库添加到可执行文件旁边来解决此问题。

因此,如果您有类似以下结构的内容:

set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)

在你的CMakeLists.txt文件中,你只需要添加以下内容:
file(COPY ${SOME_VAR}
    DESTINATION ${EXECUTABLE_OUTPUT_PATH})

这就是它。


EXECUTABLE_OUTPUT_PATH已经被弃用;根据CMake 3.18的建议,应使用RUNTIME_OUTPUT_DIRECTORY - Joachim W
1
如果您的解决方案中有多个CMake项目,那么这是可以的,但是您能否自动复制外部库中的文件呢? - FalcoGer

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