CTest、CMake&;MinGW:可执行文件已生成,但无法运行,因为找不到新的DLL

CTest、CMake&;MinGW:可执行文件已生成,但无法运行,因为找不到新的DLL,dll,cmake,environment-variables,mingw,ctest,Dll,Cmake,Environment Variables,Mingw,Ctest,顶级CMakeLists.txt包含: include(CTest) add_subdirectory(lib) add_subdirectory(demo) add_subdirectory(test) lib/CMakeLists.txt基本上是: add_library(MyLib <sources>) add_executable(Demo demo.c) target_link_libraries(Demo MyLib) test/CMakeLists.txt只是:

顶级
CMakeLists.txt
包含:

include(CTest)
add_subdirectory(lib)
add_subdirectory(demo)
add_subdirectory(test)
lib/CMakeLists.txt
基本上是:

add_library(MyLib <sources>)
add_executable(Demo demo.c)
target_link_libraries(Demo MyLib)
test/CMakeLists.txt
只是:

add_test(NAME Demo COMMAND Demo)
从gitlab运行程序,我们执行:

cmake -G "Ninja" -DCMAKE_INSTALL_PREFIX=C:\opt\x64 -B. ..
cmake --build
ctest --output-on-failure
前两步成功;第三个失败的原因是:

Start 1: Demo
1/1 Test #1: Demo .......................Exit code 0xc0000135
***Exception:   0.03 sec
如果我重试:

cmake --install
ctest
然后测试成功。所以唯一的问题是运行
ctest
时找不到
build/lib/mylib.dll
。而
C:\opt\x64\lib
位于
路径中,因此在
cmake--install
之后可以找到DLL。然而,这并不是我们想要的:
ctest
将始终使用当前版本的新DLL,而不是安装的版本


在Linux下,一切都正常工作。为什么它不适合Windows和MinGW?这是CMake中的错误吗?我们如何解决这个问题,使
ctest
在所有平台上都能正确执行?

您的问题似乎是当
ctest
运行您的
Demo
可执行文件时,Windows DLL搜索过程未能找到
mylib.DLL
。指定了Windows DLL搜索顺序:

  • 从中加载应用程序的目录
  • 系统目录。使用
    GetSystemDirectory
    函数获取此目录的路径
  • 16位系统目录。没有获取此目录路径的函数,但会对其进行搜索
  • Windows目录。使用
    GetWindowsDirectory
    函数获取此目录的路径
  • 当前目录
  • PATH
    环境变量中列出的目录。请注意,这不包括指定的每个应用程序路径
    应用程序路径
    注册表项。在以下情况下不使用
    应用程序路径
    键: 计算DLL搜索路径
  • 因此,您可以修改
    PATH
    环境变量,使其也包含当前生成的新DLL的位置

    更好的、不易出错的解决方案可能是将DLL与
    Demo
    可执行文件放在同一目录中。通过修改顶级CMake文件,可以强制CMake为DLL和可执行文件使用相同的二进制目录:

    include(CTest)
    add_subdirectory(lib ${CMAKE_BINARY_DIR}/demo)
    add_subdirectory(demo ${CMAKE_BINARY_DIR}/demo)
    add_subdirectory(test)
    
    或者,作为一种本地化程度较低的方法,您可以通过以下设置将DLL放置在与可执行文件相同的目录中:

    还有另一种选择:

    add_test(NAME Demo COMMAND Demo WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
    

    我更喜欢使用
    CMAKE_RUNTIME_OUTPUT_目录
    DLL
    exe
    放在同一个文件夹中,而不是通过
    add_subdirectory()
    @fdk1342强制二进制文件夹位置。是的,这也是一种有效的方法,尽管似乎本地化程度较低,因为我相信它适用于所有目标。但是,您可以使用设置特定于目标的属性;演示程序和测试是辅助的。因此,我不喜欢将库从lib移动到demo。在CMake中有没有一种惯用的方法告诉演示程序在哪里可以找到DLL?如果你不介意,我将编辑你的答案,添加第三种方法:调用
    add\u test
    ,使
    WORKING\u目录指向lib。@JoachimW,您可以通过将
    ${CMAKE\u BINARY\u DIR}/demo
    更改为
    ${CMAKE\u BINARY\u DIR}/lib,将
    demo
    构建工件放在
    lib
    文件夹中。通常,您可以通过更新
    PATH
    环境变量来修改运行时环境,也可以通过使用我的答案中建议的解决方法之一来更新它,或者使用已经记录的方法。这是否回答了您的问题?我对我的问题进行了编辑,以明确这不仅是一个解决方案,而且是关于理解为什么清洁的标准CMake代码不起作用。它确实起作用了。您的运行时环境错误,您需要修复它。如果您构建了一个已安装的共享库,并且需要使用正确的库,那么这与在Linux上设置RPATH没有什么区别。
    add_test(NAME Demo COMMAND Demo WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/lib)