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