Нужно скопировать DLL из подкаталога библиотеки, чтобы протестировать подкаталог с помощью CMake - PullRequest
0 голосов
/ 11 января 2019

У меня есть проект, который в основном представляет собой библиотеку 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"
)

Это все работает, и в выводе сборки я вижу, что цели построены, а выходной файл обновлен.

CMakelists.txt в подкаталоге tests для копирования 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)

"tests" - это цель для моего исполняемого файла test. Выходные данные сборки говорят, что он создает цель «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) Есть ли лучший способ сделать это, чтобы избежать копирования 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 голосов
/ 11 января 2019

но DLL не обновлена ​​в двоичном каталоге для исполняемого файла тестов

Это потому, что ваша пользовательская команда в подкаталоге tests/ не имеет никакой зависимости из библиотеки file . У вас есть зависимость только от вашей пользовательской target :

DEPENDS export_my_dll

Просто добавьте зависимость из файла, и все будет работать:

DEPENDS "${CMAKE_BINARY_DIR}/my.dll"
# Dependency from the target is also needed
DEPENDS export_my_dll
0 голосов
/ 11 января 2019

Я бы добавил 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")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...