需要从库子目录复制DLL以使用CMake测试子目录

时间:2019-01-11 09:01:12

标签: cmake

我有一个项目,该项目基本上是一个库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。

2 个答案:

答案 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