Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to idiomatically package dependencies for a QT application using CPack?

I have a simple QT project. I'm developing on Linux. But it's meant to be deployed to Linux, Mac and Windows ultimately.

I'm attempting to package it for distribution. I'm running into problems locating the dependencies and packaging them up and doing this in an idiomatic way (IOW: No hardcoded paths to DLLs or including the DLLs in my source repo)

For the Windows port, I'm using MinGW and compiling like this:

mingw64-cmake -G "Unix Makefiles" .. -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=/usr/share/mingw/toolchain-mingw64.cmake
make && ctest && make install && cpack -G "TGZ" && cpack -G "NSIS64"

I've set it to product a tar.gz file and an NSIS installer. There's no particular reason for NSIS and not Wix at the moment. This is just to figure things out.

It compiles a Windows executable, but it does not include the DLLs necessary to run the program. It's these:

Libgcc_s_seh-1.dll
Qt5Core.dll
Qt5Gui.dll

A quick find on my computer shows me that those DLLs are present here:

/usr/x86_64-w64-mingw32/sys-root/mingw/bin/Qt5Widgets.dll
/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libgcc_s_seh-1.dll
...

Is there a way to automatically get CPack to dig up the DLLs and include them in the installer?

Here is my CMakeLists.txt file:

cmake_minimum_required(VERSION 2.8.11)

project(myapp)

enable_testing()

set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

find_package(Qt5Core REQUIRED)
find_package(Qt5Gui REQUIRED)
find_package(Qt5Widgets REQUIRED)

add_executable(myapp WIN32 main.cpp mainwindow.cpp resources.qrc)

target_link_libraries(myapp Qt5::Widgets)
target_link_libraries(myapp Qt5::Core)
target_link_libraries(myapp Qt5::Gui)

INSTALL(TARGETS myapp
        BUNDLE DESTINATION .
        RUNTIME DESTINATION bin
        LIBRARY DESTINATION lib
        ARCHIVE DESTINATION lib
        )

INSTALL(FILES ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS} DESTINATION bin COMPONENT Libraries)     

IF(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS)
    INSTALL(PROGRAMS ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS} DESTINATION bin COMPONENT System)
ENDIF(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS)

INCLUDE(CPack)

I've looked around for some help on this. The best thing I came across was this link

But it's not looking so idiomatic. If we look closer at the CMakeLists.txt file, it's got machine-specific hard coded paths that are certain to change in the future:

IF(    WIN32 AND ${ARCH_32BIT})

    SET(QT_INSTALLED_PATH "C:/QtMSVCX86/Qt5.5.0/5.5/msvc2013" )

ELSEIF(WIN32 AND ${ARCH_64BIT})

    SET(QT_INSTALLED_PATH "C:/QtMSVCX64/Qt5.5.0/5.5/msvc2013_64" )

ELSEIF(UNIX  AND NOT MINGW AND ${ARCH_32BIT})

    SET(QT_INSTALLED_PATH "/opt/Qt5.5.0/5.5/gcc/" )

ELSEIF(UNIX  AND NOT MINGW AND ${ARCH_64BIT})

    SET(QT_INSTALLED_PATH "/opt/Qt5.5.0/5.5/gcc_64/" )

ENDIF()

SET(CMAKE_AUTOMOC ON)
SET(CMAKE_AUTOUIC ON)
SET(CMAKE_AUTORCC ON)

FIND_PACKAGE(Qt5Widgets PATHS  ${QT_INSTALLED_PATH} NO_DEFAULT_PATH)
FIND_PACKAGE(Qt5Qml     PATHS  ${QT_INSTALLED_PATH} NO_DEFAULT_PATH)
FIND_PACKAGE(Qt5Quick   PATHS  ${QT_INSTALLED_PATH} NO_DEFAULT_PATH)
like image 946
101010 Avatar asked Aug 31 '16 22:08

101010


1 Answers

Have a look at CMake's Bundle Utilities It contains a FIXUP_BUNDLE macro which collects all the necessary dependencies of an executable, including Qt. It works basically the same way on Windows, Linux and Mac. You could start by adding FIXUP_BUNDLE(myapp) to your CMake file. the actual dependency resolving and copying happens during the CPack run. Depending on project size and complexity, some tweaks are necessary, but in general I have seen it used successfully in larger cross-platform Qt projects with a CMake based build system

like image 185
manol Avatar answered Sep 28 '22 13:09

manol