我有一个项目,该项目基本上是一个库DLL和该DLL的一些测试代码。它由一个顶层目录,一个用于库代码的子目录和一个用于测试代码的子目录组成。
当我在IDE中运行测试时,它们将失败,因为DLL与测试可执行文件不在同一子目录中。为了解决这个问题,我试图使用一些与文档相反的无效的CMake魔术。
我的魔术如下:
库子目录中的CMakelists.txt可将DLL复制到顶层,以便测试代码(以及将来使用DLL的应用程序)始终可以在一致的位置找到它:
add_custom_command(
OUTPUT "${CMAKE_BINARY_DIR}/my.dll"
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/my.dll" "${CMAKE_BINARY_DIR}/my.dll"
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/my.dll"
)
add_custom_target(export_my_dll
DEPENDS "${CMAKE_BINARY_DIR}/my.dll"
)
所有这些都有效,我在生成输出中看到已经构建了目标,并且输出文件是最新的。
tests子目录中的CMakelists.txt,从顶层向下复制DLL:
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/my.dll"
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_BINARY_DIR}/my.dll" "${CMAKE_CURRENT_BINARY_DIR}/my.dll"
DEPENDS export_my_dll
)
add_custom_target(dlls_for_tests
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/my.dll"
)
add_dependencies(tests dlls_for_tests)
“测试”是我的测试可执行文件的目标。生成的输出说它生成了“ dlls_for_tests”目标,但是DLL在测试可执行文件的二进制目录中不是最新的-测试可执行文件使用的是陈旧的DLL。
构建输出(QtCreator)如下:
...
[ 75%] Generating ../my.dll
[ 79%] Built target export_my_dll
[ 82%] Built target dlls_for_tests
Scanning dependencies of target SpectreCtrl_Tests
[ 89%] Building CXX object project/tests/CMakeFiles/tests.dir/test_func.cpp.obj
[ 94%] Linking CXX executable tests.exe
[ 100%] Built target tests
我有两个问题:
1)为什么不起作用?
2)有没有更好的方法来避免在未更改DL1或只是更易于阅读时复制DLl?
===============
我找到了两种可行的方法,但是我都不喜欢:
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/my.dll"
COMMAND ${CMAKE_COMMAND} -E copy "$<TARGET_FILE:my_dll>" "${CMAKE_CURRENT_BINARY_DIR}"
DEPENDS "$<TARGET_FILE:my_dll>"
)
add_custom_target(dlls_for_test
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/my.dll"
)
add_dependencies(tests dlls_for_test)
这将显式使用文件名-您需要正确设置文件名,如果更改库的目标名称(并因此更改了库名),则此名称将中断。希望如果DLL没有更改,它将跳过副本。
add_custom_target(dlls_for_tests
COMMAND ${CMAKE_COMMAND} -E copy "$<TARGET_FILE:my_dll>" "${CMAKE_CURRENT_BINARY_DIR}"
)
add_dependencies(tests dlls_for_tests)
这更短更甜,但是即使没有更改,它也将始终复制DLL。
答案 0 :(得分:1)
我将向您的目标添加一个POST_BUILD
步骤,如下所示:
add_library(my_dll SHARED ${DLL_SOURCES} ${DLL_HEADERS} ${DLL_RESOURCES} )
add_executable(tests ${SOURCES} ${HEADERS} ${RESOURCES} )
target_link_libraries(tests
my_dll
)
add_custom_command(TARGET tests
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:my_dll> "${CMAKE_CURRENT_BINARY_DIR}"
COMMENT "Copy dll file to ${CMAKE_CURRENT_BINARY_DIR} directory" VERBATIM
)
命令的顺序很重要。
另一种可能性是在顶级CMakeLists.txt文件中定义一个公共输出目录:
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
答案 1 :(得分:0)
但是测试可执行文件的二进制目录中的DLL不是最新的
这是因为您在tests/
子目录中的自定义命令与库文件中的没有依赖性。您只有自定义 target 的依赖项:
DEPENDS export_my_dll
只需从文件中添加依赖项,一切都会正常工作
DEPENDS "${CMAKE_BINARY_DIR}/my.dll"
# Dependency from the target is also needed
DEPENDS export_my_dll