【问题标题】:CTest, CMake & MinGW: Executables build, but fail to run, because fresh DLL is not foundCTest、CMake 和 MinGW:可执行文件构建,但无法运行,因为找不到新的 DLL
【发布时间】:2019-12-17 15:01:16
【问题描述】:

顶级CMakeLists.txt 包含:

include(CTest)
add_subdirectory(lib)
add_subdirectory(demo)
add_subdirectory(test)

lib/CMakeLists.txt 本质上是:

add_library(MyLib <sources>)

demo/CMakeLists.txt 本质上是:

add_executable(Demo demo.c)
target_link_libraries(Demo MyLib)

test/CMakeLists.txt 只是:

add_test(NAME Demo COMMAND Demo)

从一个 gitlab-runner,我们执行:

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\libPATH 中,因此DLL 在cmake --install 之后找到。然而,这不是我们想要的:ctest 应始终使用当前构建的新 DLL,而不是安装的版本。

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

【问题讨论】:

  • 我编辑了我的问题,以表明它不仅是一种解决方法,而且是关于理解为什么干净的标准 CMake 代码不起作用。
  • 它工作正常。您的运行时环境错误,您需要修复它。如果您构建了一个已经安装的共享库并且需要使用正确的共享库,那么这与在 Linux 上设置 RPATH 没有什么不同。

标签: dll cmake environment-variables mingw ctest


【解决方案1】:

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

  1. 加载应用程序的目录。
  2. 系统目录。使用GetSystemDirectory函数获取该目录的路径。
  3. 16 位系统目录。没有函数获取这个目录的路径,但是搜索到了。
  4. Windows 目录。使用GetWindowsDirectory函数获取该目录的路径。
  5. 当前目录。
  6. PATH 环境变量中列出的目录。请注意,这不包括由指定的每个应用程序路径 App Paths 注册表项。 App Paths 键在以下情况下不使用 计算 DLL 搜索路径。

因此,您可以将PATH 环境变量修改为包含来自当前构建的新DLL 的位置。

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

include(CTest)
add_subdirectory(lib ${CMAKE_BINARY_DIR}/demo)
add_subdirectory(demo ${CMAKE_BINARY_DIR}/demo)
add_subdirectory(test)

或者,作为一种本地化程度较低的方法,您可以通过设置 CMAKE_RUNTIME_OUTPUT_DIRECTORY 将 DLL 与可执行文件放在同一目录中:

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

另一种选择:

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

【讨论】:

  • 我更喜欢使用CMAKE_RUNTIME_OUTPUT_DIRECTORY DLLexe 放入同一个文件夹,而不是通过add_subdirectory() 强制二进制文件夹位置。
  • @fdk1342 是的,这也是一种有效的方法,虽然似乎不太本地化,因为我相信它适用于所有目标。但是,您可以使用 RUNTIME_OUTPUT_DIRECTORY 设置特定于目标的属性。
  • 图书馆是我们的产品;演示程序和测试是辅助性的。因此,我不喜欢将库从 lib 移动到 demo。在 CMake 中是否有一种惯用的方式来告诉演示程序在哪里可以找到 DLL?
  • 如果您不介意,我将编辑您的答案以添加第三种方法:调用 add_test 并使用指向 lib 的 WORKING_DIRECTORY
  • @JoachimW 然后,您可以通过将${CMAKE_BINARY_DIR}/demo 更改为${CMAKE_BINARY_DIR}/lib 来将demo 构建工件放在lib 文件夹中。一般来说,您可以修改您的运行时环境,通过更新您的PATH 环境变量,通过ctest 更新它,使用我的回答中建议的解决方法之一,或那些已经记录在案的@ 987654325@.
猜你喜欢
  • 1970-01-01
  • 2014-06-12
  • 1970-01-01
  • 1970-01-01
  • 2011-04-22
  • 1970-01-01
  • 1970-01-01
  • 2021-07-17
  • 1970-01-01
相关资源
最近更新 更多