Как сделать Boost DLL доступными для исполняемого файла, созданного с помощью CMake?

#windows #dll #boost #cmake

#Windows #dll #boost #cmake

Вопрос:

Я использую CMake в Windows для создания набора тестов на основе Boost.Test. Поскольку я ссылаюсь на Boost.При динамическом тестировании мой исполняемый файл должен иметь возможность находить DLL (которая находится в ../ .. / ../boost/boost_1_47/lib или что-то в этом роде относительно исполняемого файла).

Поэтому мне нужно либо скопировать DLL в папку, в которой находится исполняемый файл, либо сделать его доступным для поиска каким-либо другим способом. Каков наилучший способ добиться этого с помощью CMake?

— Дополнительная информация —

Мой CMakeLists.txt имеет ли эта конфигурация, связанная с повышением, на данный момент:

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

Комментарии:

1. cmake.org/cmake/help/cmake-2-8-docs.html#command:install

Ответ №1:

Предполагая, что вы запускаете свои тесты, создавая цель RUN_TESTS в Visual Studio:

  1. Я всегда добавляю …/boost/boost_1_47/lib в переменную окружения командного пути, поэтому библиотеки boost unit_test_framework dll можно найти во время выполнения. Это то, что я рекомендую.

  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. Если вы НЕ только запускаете тесты во время сборки (как я предполагал выше), вам понадобится ряд INSTALL команд, как предложил Ханс Пассант. В вашем фрагменте у вас нет INSTALL команды для вашего исполняемого файла; так что даже ваш исполняемый файл не окажется «в папке исполняемого файла». Сначала добавьте INSTALL команду cmake, чтобы поместить ваш исполняемый файл куда-нибудь в ответ на цель установки cmake. Как только это заработает, мы сможем выяснить, как добавить другую команду УСТАНОВКИ, чтобы поместить библиотеку boost unit_test_framework в то же место. После этого, если вы хотите создать установщик с использованием CPACK, библиотека будет автоматически установлена вместе с исполняемым файлом.

Ответ №2:

В итоге я использовал 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
)
  

Ответ №3:

У меня очень похожая проблема, но представленное здесь решение не совсем удовлетворительное. Как и в оригинальном постере, я хочу запускать модульные тесты на основе boost::test.

У меня есть несколько тестовых проектов, по одному для каждого компонента mayor нашего продукта. Необходимость запускать цель установки перед каждым тестом означает перекомпиляцию всего этого только для запуска тестов, принадлежащих основному компоненту. Этого я хочу избежать.

Если я что-то изменю в основном компоненте, я хочу скомпилировать этот основной компонент и связанные с ним тесты. А затем запустите тесты. Только после успешного завершения тестов я хочу скомпилировать и в конечном итоге установить оставшуюся часть.

Для запуска тестов в отладчике я нашел несколько очень полезных сценариев 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} содержит каталоги, в которых можно найти библиотеки DLL из boost и всех других библиотек.

Теперь я ищу, как я могу добиться чего-то подобного с помощью 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()
  

При этом модульные тесты улавливают ошибки как можно скорее, без необходимости сначала компилировать всю партию.