CMake с MinGW-w64 не устанавливает встроенную DLL, но собирается нормально - PullRequest
0 голосов
/ 29 мая 2019

NB: Все файлы, на которые здесь ссылаются, немного ниже горизонтальной линейки.

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

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

Если не используется явный файл toolchain (то есть без -DCMAKE_TOOLCHAIN_FILE=...), все работает как положено, и lib${PRJNAME}.so устанавливается по желанию.Однако, как только я воспользуюсь файлом инструментария, приведенным ниже, я получу только полученный lib ${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

Как вы можете видеть, собственная сборка устанавливает разделяемую библиотеку actual , но та, которая предназначена для Windows, устанавливает только импорт lib, не 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 вступает в силу, поскольку именно там заканчивается импорт lib.Но почему встроенный .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)

1 Ответ

1 голос
/ 29 мая 2019
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.

...