顶级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:optx64lib
在PATH
中,因此DLL是在cmake --install
之后找到的。但是,这不是我们想要的:ctest
应始终使用当前版本中的新DLL,而不是已安装的版本。
在Linux下,一切正常。为什么不适用于Windows和MinGW?这是 CMake 中的错误吗?我们如何解决此问题,以便ctest
在所有平台上正确执行?
您的问题似乎是 Windows DLL 搜索过程无法找到mylib.dll
当您的Demo
可执行文件由ctest
运行时。Windows DLL 搜索顺序在此处指定:
- 从中加载应用程序的目录。
- 系统目录。使用
GetSystemDirectory
函数获取此目录的路径。- 16 位系统目录。没有函数可以获取此目录的路径,但会对其进行搜索。
- 窗口目录。使用
GetWindowsDirectory
函数获取此目录的路径。- 当前目录。
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 或使用特定的工作目录。