CMake GET_RUNTIME_DEPENDENCIES не может найти библиотеку dll, когда она связана через lib (библиотека импорта)?

Сборка ОС: Windows 10, Cmake 3.16.3.

Я использую target_link_libraries, чтобы связать сторонний .lib файл с моей .dll библиотекой.

Но когда я использую GET_RUNTIME_DEPENDENCIES для установки dll, зависимости не обнаружено.

Это происходит только в Windows, установка в Linux в порядке.

Есть ли какие-нибудь подсказки, как решить эту проблему или хотя бы как ее отладить?

Какая именно команда использует CMake в Windows для определения зависимостей?

Я вызываю GET_RUNTIME_DEPENDENCIES так:

file(GET_RUNTIME_DEPENDENCIES
    RESOLVED_DEPENDENCIES_VAR RES
    UNRESOLVED_DEPENDENCIES_VAR UNRES
    CONFLICTING_DEPENDENCIES_PREFIX CONFLICTING_DEPENDENCIES
    EXECUTABLES ${EXECS}
    LIBRARIES ${LIBS} ${MODULES} ${QTPLUGINS_LIBS}
    DIRECTORIES ${RUNTIME_DEPENDENCIES_DIRECTORIES}
    POST_EXCLUDE_REGEXES ${PLATFORM_POST_EXCLUDE_REGEXES}
)

Где LIBS содержит мой dll, но нет RES нет UNRES содержит путь к 3-му патчу dll.


person ephemerr    schedule 03.02.2020    source источник
comment
Пожалуйста, предоставьте некоторый код (желательно, минимально воспроизводимый пример). При наличии текущей информации решение проблемы представляет собой сложную игру в догадки.   -  person Tsyvarev    schedule 03.02.2020


Ответы (1)


GET_RUNTIME_DEPENDENCIES не знает о ваших переменных времени настройки, поэтому вам нужно указать их вручную. В этом ответе говорится, что вы могу передать переменные на шаг установки, но я пока не смог заставить это работать. К счастью, он поддерживает выражения генератора.

Другая проблема в вашем фрагменте кода заключается в том, что он должен вызываться во время установки. Например, в блоке install(CODE ...).

Итак, имея все это в виду, это должно помочь вам начать.

install(CODE [[
    file(GET_RUNTIME_DEPENDENCIES
        RESOLVED_DEPENDENCIES_VAR RES
        UNRESOLVED_DEPENDENCIES_VAR UNRES
        CONFLICTING_DEPENDENCIES_PREFIX CONFLICTING_DEPENDENCIES
        EXECUTABLES $<TARGET_FILE:your_executable_target_name>
        LIBRARIES $<TARGET_FILE:a_lib_target_name>
    )

    message("\n\nFound dependencies :")
    foreach(DEP ${RES})
        message("${DEP}")
    endforeach()
    message("\n\nNot found dependencies :")
    foreach(DEP ${UNRES})
        message("${DEP}")
    endforeach()
]])

Создайте цель установки, чтобы увидеть результаты.

cmake ..
cmake --build . --target install
person scx    schedule 28.10.2020
comment
Одно небольшое замечание: аргумент $<TARGET_FILE:> может быть только целевым именем. (Например, если у вас есть целевое определение add_library(foo SHARED ...), то $<TARGET_FILE:foo> вставит libfoo.so в Linux, foo.dll в Windows и т. д. Но $<TARGET_FILE:foo.dll> или $<TARGET_FILE:libfoo> не сработает.) Что касается передачи переменных, это может быть сложно, потому что вы должны убедиться, что переменная НЕ экранирована в коде передачи — вы хотите, чтобы она была расширена. Мне пришлось перепроверить синтаксис моего ответа, чтобы убедиться, что я не напутал (снова), но он должен работать. - person FeRD; 29.10.2020
comment
Так, например, в приведенном выше коде вы можете добавить install(CODE "set(my_compiler \"${CMAKE_CXX_COMPILER_ID}\")") перед блоком install(CODE..., который у вас есть сейчас. Затем вы можете написать message(STATUS "Built with ${my_compiler}") во втором блоке, чтобы получить вывод процесса установки -- Создан с помощью GNU, -- Создан с помощью Clang и т. д. - person FeRD; 29.10.2020
comment
@FeRD Хорошее примечание, я обновил ответ, чтобы уточнить, что вы должны указать целевые имена (а не фактические имена файлов). Проблема с передачей переменных конфигурации заключается в том, что вы не можете использовать их в своих выражениях генератора, что делает их несколько бесполезными. Например, $<TARGET_FILE:${SOME_VAR}> ошибки с Expression syntax not recognized. - person scx; 29.10.2020
comment
Это было бы бесполезно, даже если бы вы могли это сделать, потому что эти переменные оцениваются сразу во время настройки. К тому времени, когда блок install(CODE...) достигает блока cmake_install.txt для этого каталога (что происходит до завершения начального запуска cmake), все эти выражения генератора исчезают, заменяясь результатами их оценки. Передача обычных переменных может быть удобной. Frex, если вам нужно передать динамически сгенерированный список путей поиска или PRE_EXCLUDE_REGEXES в file(GET_RUNTIME_DEPENDENCIES..). - person FeRD; 29.10.2020
comment
(Я имею в виду, что на самом деле вы можете сделать $<TARGET_FILE:${myvar}> нормально — вы просто не можете сделать это внутри [[ ]]-защищенного блока, потому что он блокирует раскрытие всех переменных. знак доллара и фигурная скобка, когда вы пишете блок CODE, но все это компромисс.) - person FeRD; 29.10.2020
comment
Можем ли мы согласиться с тем, что было бы полезно передать ваши целевые имена в TARGET_FILE? Хотя я не уверен, что полностью понимаю. Вы говорите, что скопированные переменные можно было бы расширить, если бы блок был заключен в двойные кавычки? ты! - person scx; 29.10.2020
comment
О, я говорю, что если бы вы использовали блок в двойных кавычках, вам даже не нужно было бы копировать переменные — точно так же, как и сами выражения генератора, они были бы развернуты сразу же, как и install(CODE...) команда обрабатывается. Недостатком является то, что вам придется избегать всего, что вы НЕ хотите, немедленно заменить. (Как и ссылки на ${UNRES}, ${DEP} и т. д. в вашем коде. Блок [[ ]] значительно упрощает написание этой части кода за счет возможности ссылаться на переменные контекста родительского файла.) - person FeRD; 29.10.2020
comment
Итак, похоже, проблемы, с которыми я сталкиваюсь, связаны с целевыми переменными. Следующее ничего не выводит, хотя и компилируется. install(CODE "set(TARGET_NAME \"${MY_TARGET}\")") install(CODE "message(\"Target Name : ${TARGET_NAME}\")") ` Я не уверен, что cmake voodoo предотвращает это, но спасибо за помощь. - person scx; 29.10.2020