如何使Boost DLL对使用CMake构建的可执行文件可访问?

10
我在Windows上使用CMake构建基于Boost.Test的测试套件。由于我正在动态链接到Boost.Test,所以我的可执行文件需要能够找到DLL(相对于可执行文件,它在../../../boost/boost_1_47/lib或类似位置下)。
因此,我需要将DLL复制到可执行文件所在的文件夹中,或以其他方式使其可寻找。如何使用CMake最好地实现这一点?
-- 附加信息 --
目前,我的CMakeLists.txt具有以下与Boost相关的配置:
set(Boost_ADDITIONAL_VERSIONS "1.47" "1.47.0")
set(BOOST_ROOT "../boost")

find_package(Boost 1.47 COMPONENTS unit_test_framework REQUIRED)
include_directories(${Boost_INCLUDE_DIR})
link_directories(${Boost_LIBRARY_DIR})

add_executable(test-suite test-suite.cpp)
target_link_libraries(test-suite ${Boost_LIBRARIES})

2
http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:install - Hans Passant
3个回答

6
假设您是通过在Visual Studio中构建RUN_TESTS目标来运行测试:
  1. 我总是将 .../boost/boost_1_47/lib 添加到我的命令路径环境变量中,这样在运行时就可以找到boost unit_test_framework dlls。 这是我推荐的做法。

  2. 如果由于某些原因无法更改您的路径,则可以使用cmake复制文件。

(未经测试)

get_filename_component(LIBNAME "${Boost_UNIT_TEST_FRAMEWORK_LIBRARY_RELEASE}" NAME)
add_custom_command(TARGET test-suite POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy "${Boost_UNIT_TEST_FRAMEWORK_LIBRARY_RELEASE}" "${CMAKE_CURRENT_BINARY_DIR}/${LIBNAME}"
)

3. 如果你不仅在构建时运行测试(正如我上面所假设的那样),则需要一系列类似于 Hans Passant 建议的 INSTALL 命令。在你的片段中,你没有一个 INSTALL 命令用于你的可执行文件;因此,即使是你的可执行文件也不会最终出现在“可执行文件夹”中。首先添加一个 cmake 的 INSTALL 命令,将你的可执行文件放置到响应 cmake INSTALL 目标的某个地方。一旦你成功实现了这一点,我们就可以着手解决如何添加另一个 INSTALL 命令,将 boost unit_test_framework 库放置在同一位置的问题。之后,如果你想使用 CPACK 制作安装程序,该库将自动与可执行文件一起被安装。


4

最终我使用install命令将Boost DLL复制到可执行文件的文件夹中:

get_filename_component(UTF_BASE_NAME ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY_RELEASE} NAME_WE)
get_filename_component(UTF_PATH ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY_RELEASE} PATH)
install(FILES ${UTF_PATH}/${UTF_BASE_NAME}.dll
  DESTINATION ../bin
  CONFIGURATIONS Release RelWithDebInfo
)

get_filename_component(UTF_BASE_NAME_DEBUG ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY_DEBUG} NAME_WE)
install(FILES ${UTF_PATH}/${UTF_BASE_NAME_DEBUG}.dll
  DESTINATION ../bin
  CONFIGURATIONS Debug
)

2
我有一个非常类似的问题,但这里提供的解决方案并不是很令人满意。 像原帖作者一样,我想基于boost::test运行单元测试。
我有多个测试项目,每个项目对应我们产品的一个主要组件。 在每次运行测试之前都必须运行install目标,这意味着需要重新编译整个东西才能运行属于核心组件的测试。这就是我想避免的。
如果我更改了核心组件中的某些内容,我希望编译该核心组件和相关的测试。然后运行测试。当测试成功时,我才想编译并最终安装其余部分。
为了在调试器中运行测试,我在以下链接中找到了一些非常有用的cmake脚本: https://github.com/rpavlik/cmake-modules 通过这种方式,我可以指定所有所需dll的目录,并为新进程设置PATH环境变量:
# for debugging
INCLUDE(CreateLaunchers)

create_target_launcher(PLCoreTests 
    ARGS  "--run-test=Core1"
    RUNTIME_LIBRARY_DIRS ${PL_RUNTIME_DIRS_DEBUG} ${PROJECT_BINARY_DIR}/bin/Debug 
    WORKING_DIRECTORY ${PL_MAIN_DIR}/App/PL/bin
)

${PL_RUNTIME_DIRS_DEBUG}包含了boost和其他库的dll文件所在的目录。

现在我正在寻找如何使用ADD_CUSTOM_COMMAND()实现类似的功能。

更新:

ADD_CUSTOM_COMMAND()可以有多个命令,CMake会将它们写入一个批处理文件中。因此,您可以首先设置包含所有运行时目录的路径,然后执行测试可执行文件。为了能够轻松地手动执行测试,我让CMake在构建目录中创建了一个额外的批处理文件:

MACRO(RunUnitTest TestTargetName)
    IF(RUN_UNIT_TESTS)
        SET(TEMP_RUNTIME_DIR ${PROJECT_BINARY_DIR}/bin/Debug)
        FOREACH(TmpRuntimeDir ${PL_RUNTIME_DIRS_DEBUG})
            SET(TEMP_RUNTIME_DIR  ${TEMP_RUNTIME_DIR}  ${TmpRuntimeDir})
        ENDFOREACH(TmpRuntimeDir)

        ADD_CUSTOM_COMMAND(TARGET ${TestTargetName} POST_BUILD 
            COMMAND echo "PATH=${TEMP_RUNTIME_DIR};%PATH%" > ${TestTargetName}_script.bat
            COMMAND echo ${TestTargetName}.exe --result_code=no --report_level=no >> ${TestTargetName}_script.bat
            COMMAND ${TestTargetName}_script.bat
            WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug
        )
    ENDIF(RUN_UNIT_TESTS)
ENDMACRO()

通过这种方式,单元测试可以尽快地捕捉到错误,而无需先编译整个程序。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接