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

时间:2011-11-02 09:46:32

标签: windows dll boost cmake

我在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})

3 个答案:

答案 0 :(得分:6)

假设您通过在Visual Studio中构建RUN_TESTS目标来运行测试:

  1. 我总是将... / boost / boost_1_47 / lib添加到我的命令PATH环境变量中,因此可以在运行时找到boost unit_test_framework dll。这就是我的建议。

  2. 如果由于某种原因无法更改PATH,您可以使用cmake复制文件。

  3. (未测试的)

    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。如果你 NOT 只在构建时运行测试(正如我上面假设的那样),那么你需要一系列INSTALL命令,比如Hans Passant建议的那样。在您的代码段中,您的可执行文件没有INSTALL命令;所以即使你的可执行文件也不会“在可执行文件夹中”。首先添加一个cmake INSTALL命令,将您的可执行文件置于某个位置以响应cmake INSTALL目标。一旦你有了这个工作,我们就可以着手搞清楚如何添加另一个INSTALL命令,将boost unit_test_framework库放到同一个位置。之后,如果要使用CPACK创建安装程序,则库将自动与可执行文件一起安装。

答案 1 :(得分: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 :(得分:2)

我有一个非常类似的问题,但这里提出的解决方案并不令人满意。 像原始海报一样,我想基于boost :: test运行单元测试。

我有多个测试项目,每个测试项目对应我们产品的每个市长组件。 必须在每次测试之前运行安装目标意味着重新编译整个事情只是为了运行属于核心组件的测试。这就是我想要避免的。

如果我在核心组件中更改某些内容,我想编译该核心组件和相关的测试。然后运行测试。当测试成功时,我才想编译并最终安装其余部分。

为了在调试器中运行测试,我发现了一些非常有用的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()

有了这个,单元测试会尽快捕获错误,而不必先编译整个批次。