CTest,CMake和MinGW:可执行文件构建,但无法运行,因为找不到新的DLL



顶级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 运行器中,我们执行:

cmake -G "Ninja" -DCMAKE_INSTALL_PREFIX=C:optx64 -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:optx64libPATH中,因此DLL是在cmake --install之后找到的。但是,这不是我们想要的:ctest应始终使用当前版本中的新DLL,而不是已安装的版本。

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

您的问题似乎是 Windows DLL 搜索过程无法找到mylib.dll当您的Demo可执行文件由ctest运行时。Windows DLL 搜索顺序在此处指定:

  1. 从中加载应用程序的目录。
  2. 系统目录。使用GetSystemDirectory函数获取此目录的路径。
  3. 16 位系统目录。没有函数可以获取此目录的路径,但会对其进行搜索。
  4. 窗口目录。使用GetWindowsDirectory函数获取此目录的路径。
  5. 当前目录。
  6. PATH环境变量中列出的目录。请注意,这不包括由App Paths注册表项。在以下情况下不使用App Paths键 计算 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)

或者,作为一种不太本地化的方法,您可以通过设置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)

一种使用生成器表达式并附加到测试环境 PATH 的更现代的方法:

add_test(NAME mytest ...)
set_tests_properties(mytest PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<$<BOOL:${WIN32}>:$<TARGET_FILE_DIR:my_library>>")

这会将包含"my_library"的目录附加到测试运行程序在 Windows 上构建时使用的 PATH 中,否则不会有任何更改。 无需复制库或弄乱构建产品的位置,也无需直接更改 PATH 或使用特定的工作目录。

相关内容

  • 没有找到相关文章

最新更新