CMake с MinGW-w64 не устанавливает встроенную DLL, но строится нормально

Примечание: Файлы, на которые имеются ссылки здесь, приведены ниже горизонтальной линейки немного вниз.

Это MWE, полученный из проекта, в котором я столкнулся с этим. Используемая версия CMake — 3.12.2 в Ubuntu 16.04 (точнее, 16.04.6).

Цель состоит в том, чтобы создать CMakeLists.txt, который можно перенаправить на сборку Windows DLL с помощью цепочки инструментов MinGW-w64 (apt-get install mingw-w64 в Ubuntu/Debian).

При использовании без явного файла цепочки инструментов (т. е. без -DCMAKE_TOOLCHAIN_FILE=...) все работает, как и ожидалось, и lib${PRJNAME}.so устанавливается по желанию. Однако, как только я использую файл цепочки инструментов, приведенный ниже, я получаю только результирующую библиотеку импорта ${PRJNAME}Lib.dll.a, но не соответствующий установленный файл .dll.

Если я вызову сценарий Bash следующим образом:

./build.sh 2>&1 |grep '^-- Install'

вывод:

-- Install configuration: ""
-- Installing: /home/user/cmake-test/build-native/install-target/lib/libtest.so
-- Install configuration: ""
-- Installing: /home/user/cmake-test/build-windows/install-target/lib/test.dll.a

Как вы можете видеть, собственная сборка устанавливает общую библиотеку действительный, но сборка, ориентированная на Windows, устанавливает только библиотеку импорта, нет — DLL. Я ожидал увидеть что-то вроде этого:

-- Install configuration: ""
-- Installing: /home/user/cmake-test/build-native/install-target/lib/libtest.so
-- Install configuration: ""
-- Installing: /home/user/cmake-test/build-windows/install-target/lib/test.dll
-- Installing: /home/user/cmake-test/build-windows/install-target/lib/test.dll.a

Что я здесь делаю неправильно? Казалось бы, функция install() вызывается правильно:

install(
    TARGETS ${PRJNAME}
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    COMPONENT library
)

Очевидно, что ARCHIVE DESTINATION вступает в силу, так как именно здесь заканчивается импортная библиотека. Но почему встроенный .dll здесь полностью игнорируется?

Примечание: я знаю о GNUInstallDirs, но он полностью развалился, как только я начал кросс-компиляцию для Windows. Поэтому я устанавливаю нужные пути «вручную» перед вызовом install().


build.sh (должен быть исполняемым)

Скрипт сначала сотрет папки build-native и build-windows, если они есть, а затем создаст их снова. Затем он будет вызывать cmake из этих папок соответственно, ориентируясь на системный (собственный) набор инструментов и набор инструментов MinGW-w64 соответственно. И последнее, но не менее важное: он вызовет установку из этих папок соответственно.

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

#/usr/bin/env bash
for i in native windows; do
        D=build-$i
        test -d $D && rm -rf $D
        mkdir $D
        [[ "$i" == "windows" ]] && TCFILE=mingw64-64bit.cmake
        ( set -x; cd $D && cmake .. -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=. ${TCFILE+-DCMAKE_TOOLCHAIN_FILE=$TCFILE} -DCMAKE_VERBOSE_MAKEFILE=ON )
        ( set -x; cd $D && cmake --build . --target install )
done

test.cpp

#ifdef _WIN32
#   if defined(test_EXPORTS)
#       define TEST_API  __declspec(dllexport)
#   else
#       define TEST_API __declspec(dllimport)
#   endif
#else
#   define TEST_API
#endif

TEST_API void SomeFunction()
{
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.12)
set(PRJNAME test)
set(TARGET_DIR "${CMAKE_CURRENT_BINARY_DIR}/install-target")
project(${PRJNAME})

add_library(${PRJNAME} SHARED test.cpp)

if (CMAKE_SYSTEM_NAME MATCHES "Windows")
    set(DLL_PREFIX)
    set(DLL_POSTFIX Lib)
else()
    set(DLL_PREFIX lib)
    set(DLL_POSTFIX)
endif ()

set_target_properties(
    ${PRJNAME}
    PROPERTIES
    PREFIX "${DLL_PREFIX}"
    IMPORT_PREFIX "${DLL_PREFIX}"
    DEBUG_POSTFIX "${DLL_POSTFIX}"
    RELEASE_POSTFIX "${DLL_POSTFIX}"
    CXX_STANDARD 11
    CXX_EXTENSIONS OFF
    CXX_STANDARD_REQUIRED ON
    POSITION_INDEPENDENT_CODE 1
)

set(CMAKE_INSTALL_PREFIX ${TARGET_DIR})
set(CMAKE_INSTALL_LIBDIR lib)
set(CMAKE_INSTALL_INCLUDEDIR include)

install(
    TARGETS ${PRJNAME}
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    COMPONENT library
)

mingw64-64bit.cmake

set(CMAKE_SYSTEM_NAME Windows)
set(TOOLCHAIN_PREFIX x86_64-w64-mingw32)

set(CMAKE_C_COMPILER   ${TOOLCHAIN_PREFIX}-gcc-posix)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++-posix)
set(CMAKE_RC_COMPILER  ${TOOLCHAIN_PREFIX}-windres)

set(CMAKE_FIND_ROOT_PATH  /usr/${TOOLCHAIN_PREFIX})

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
723
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
install(
    TARGETS ${PRJNAME}
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}
    COMPONENT library
)

В соответствии с документацией по команде install файл DLL считается объектом времени выполнения. Я тестировал пример на Ubuntu 14.04.

Спасибо, это действительно было проблемой. Совсем не очевидно, почему один будет считаться RUNTIME, а другой LIBRARY... да ладно.

0xC0000022L 29.05.2019 18:33

@ 0xC0000022L Мое единственное предположение заключается в том, что в Windows легко разместить DLL в том же месте, что и исполняемый файл, чтобы при запуске исполняемого файла он легко находил DLL.

fdk1342 29.05.2019 18:41

Другие вопросы по теме