#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:
Предполагая, что вы запускаете свои тесты, создавая цель RUN_TESTS в Visual Studio:
-
Я всегда добавляю …/boost/boost_1_47/lib в переменную окружения командного пути, поэтому библиотеки boost unit_test_framework dll можно найти во время выполнения. Это то, что я рекомендую.
-
Если по какой-либо причине изменение вашего пути невозможно, вы можете скопировать файлы с помощью 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()
При этом модульные тесты улавливают ошибки как можно скорее, без необходимости сначала компилировать всю партию.