4

I'm trying to build a with Qt 5.14 an application on release mode and everything is working fine inside of Qt Creator, but when I'm trying to run the executable by itself I'm getting an error like this:


OS: Windows 10

Qt: 5.14

Cmake: 3.5


enter image description here


What I've tried:

  1. set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++ -static")
  2. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -fPIC")
  3. ${ADDITIONAL_LIBRARIES} -static inside of target_link_libraries

None of the above worked for me and I'm getting the same error whenever I'm trying to run the executable by its self without using Qt Creator.


My CMake file:

cmake_minimum_required(VERSION 3.5)

project(Scrollable LANGUAGES CXX)

set(CMAKE_INCLUDE_CURRENT_DIR ON)

set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)

set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++ -static")
set(CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} -std=c++0x -fPIC")
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(Qt5 REQUIRED Core Widgets Gui Qml Quick Qml)

qt5_add_resources(resource.qrc)

include_directories(${CMAKE_CURRENT_SOURCE_DIR})
include_directories("MoviesInterface")

set(SOURCES
        main.cpp
        MovieInterface/movieinterfaceomdb.cpp
        MovieInterface/moviesinterface.cpp
        )

set(HEADERS
        MovieInterface/movieinterfaceomdb.h
        MovieInterface/moviesinterface.h
        )


add_executable(Scrollable ${SOURCES} ${HEADERS} qml.qrc)
qt5_use_modules(Scrollable Core Network)
target_link_libraries(Scrollable
        Qt5::Core
        Qt5::Gui
        Qt5::Widgets
        Qt5::Qml
        ${ADDITIONAL_LIBRARIES} -static
        )
Mircea
  • 1,671
  • 7
  • 25
  • 41
  • Others have already asked similar questions, such as [this](https://stackoverflow.com/questions/18161546/cant-start-a-program-because-qt5cored-dll-is-missing), on this site. Have you tried those suggestions? It is likely your issue can be resolved by updating your `Path` or copying the missing DLLs to your executable location. – Kevin Mar 25 '20 at 17:57
  • Sure... except that there no connection between my static linking libraries in CMake and that missing DLL, because I cant just copy-paste that DLL into my build folder. That a sign that I didn't link correctly the libraries. – Mircea Mar 25 '20 at 18:01
  • Did you reinstall Qt5core? ;) I did some tests with executing "make all" successful in the build folder that was build by qmake from the qt creator. Than I changed the path to all the source files and put em in the buid folder - worked perfectly fine since all the linking was already done by qmake and changes in the source code took affect by issuing make all. Can you execute make all in the build folder - does it compile? – Ingo Mi Mar 25 '20 at 18:20

3 Answers3

11

A You want to statically compile. This won't work for Qt libs and Mingw libs itself, because these would need to be compiled statically, too. But they are only distributed as dynamic linked libraries.

If you really want to have statically linkable Qt libs, you would need to compile Qt statically, before you can link them. There are some descriptions for compiling Qt statically out there. But it's a lot of work.

B Why Qt5Core.dll is not found:

Inside Qt Creator the path to the Qt libraries for your application is automatically set, because of Compiler/Toolchain auto-detection.

But, when you run your application executable standalone, the path to the Qt libs is not set and they do not reside in the application folder next to the executable.


To solve this i would suggest using windeployqt. windeployqt analyzes the library or executable you build and copies the needed Qt dependencies into the build folder.

I tend to use a cmake helper function for this.

  1. Create windeployqt.cmake with the following content and place it into /cmake modules folder of your project:
find_package(Qt5Core REQUIRED)

# get absolute path to qmake, then use it to find windeployqt executable

get_target_property(_qmake_executable Qt5::qmake IMPORTED_LOCATION)
get_filename_component(_qt_bin_dir "${_qmake_executable}" DIRECTORY)

function(windeployqt target)

    # POST_BUILD step
    # - after build, we have a bin/lib for analyzing qt dependencies
    # - we run windeployqt on target and deploy Qt libs

    add_custom_command(TARGET ${target} POST_BUILD
        COMMAND "${_qt_bin_dir}/windeployqt.exe"         
                --verbose 1
                --release
                --no-svg
                --no-angle
                --no-opengl
                --no-opengl-sw
                --no-compiler-runtime
                --no-system-d3d-compiler
                \"$<TARGET_FILE:${target}>\"
        COMMENT "Deploying Qt libraries using windeployqt for compilation target '${target}' ..."
    )

endfunction()

Note 1: --verbose 1 is set, so that you see what's going on. You might disable it later.

Note 2: Please handle the excludes yourself. I don't know the specific requirements of your app, e.g. if you need OpenGL or SVG support.

  1. Then add to your CMakeLists.txt:
# Set path to our custom CMAKE scripts
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake")

# Include Qt deployment helper function
include(windeployqt)

Finally, add to the end of CMakeLists.txt:

windeployqt(Scrollable)

Now, windeployqt is run as a POST_BUILD step on your executable, copying the qt libraries to the build folder. The executable will now pick up the Qt dependencies from this folder and should be able to run standalone (without path to Qt libs set).

Keep in mind to also copy other dependencies, e.g. third-party libs or runtime-dependencies.


Follow-up for your mingw dependencies:

set(QT_MINGW "/path/to/your/qt/mingw/compiler")

add_custom_command(TARGET Scrollable POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_if_different ${QT_MINGW}/bin/libgcc_s_dw2-1.dll $<TARGET_FILE_DIR:${TARGET}>
    COMMAND ${CMAKE_COMMAND} -E copy_if_different ${QT_MINGW}/bin/libstdc++-6.dll $<TARGET_FILE_DIR:${TARGET}>
    COMMAND ${CMAKE_COMMAND} -E copy_if_different ${QT_MINGW}/bin/libwinpthread-1.dll $<TARGET_FILE_DIR:${TARGET}>
    COMMENT "Deploy mingw runtime libraries from ${QT_MINGW}/bin"
)
Jens A. Koch
  • 39,862
  • 13
  • 113
  • 141
  • I did try this and it's almost working, except that now when I'm building the project it failed and I'm receiving this error message. – Mircea Mar 25 '20 at 20:28
  • `Unable to find the platform plugin. mingw32-make.exe[2]: *** [CMakeFiles\Scrollable.dir\build.make:172: Scrollable.exe] Error 1 mingw32-make.exe[2]: *** Deleting file 'Scrollable.exe' mingw32-make.exe[1]: *** [CMakeFiles\Makefile2:76: CMakeFiles/Scrollable.dir/all] Error 2 mingw32-make.exe: *** [Makefile:83: all] Error 2 22:26:33: The process "C:\Qt\Tools\CMake_64\bin\cmake.exe" exited with code 2. Error while building/deploying project Scrollable (kit: Desktop Qt 5.14.1 MinGW 64-bit) When executing step "CMake Build"` – Mircea Mar 25 '20 at 20:29
  • Ok, seems the platform plugin isn't copied. It should be in `platforms\qwindows.dll`. Also i'm not sure, if your application needs additional compiler specific (mingw) runtime libs in the exe folder. -- You can use http://www.dependencywalker.com/ to find out what your exe depends on. Then copy those libs to the folder. – Jens A. Koch Mar 25 '20 at 20:49
  • I've add thos updates between `target_link_libraries` and `windeployqt(Scrollable)` in **CMakeList.txt** and is not working, I'm receiving this error message: `CMake Error at CMakeLists.txt:53 (add_custom_command): Error evaluating generator expression: $ Expression syntax not recognized` – Mircea Mar 26 '20 at 09:01
  • sry, my fault: all occurances of `$` – Jens A. Koch Mar 26 '20 at 12:10
  • If I'm changing that the CMakeList.txt is going to work as expected but I will receive this error message again – Mircea Mar 26 '20 at 12:35
  • `Unable to find the platform plugin. mingw32-make.exe[2]: *** [CMakeFiles\Scrollable.dir\build.make:172: Scrollable.exe] Error 1 mingw32-make.exe[2]: *** Deleting file 'Scrollable.exe' mingw32-make.exe[1]: *** [CMakeFiles\Makefile2:76: CMakeFiles/Scrollable.dir/all] Error 2 mingw32-make.exe: *** [Makefile:83: all] Error 2 14:32:54: The process "C:\Qt\Tools\CMake_64\bin\cmake.exe" exited with code 2. Error while building/deploying project Scrollable (kit: Desktop Qt 5.14.1 MinGW 64-bit) When executing step "CMake Build"` – Mircea Mar 26 '20 at 12:36
  • Simply drop the idea of statically compiling Qt libs and Mingw into your exe. It won't work unless you compile everything statically, which is an insane amout of work. By now you should have Qt + Mingw compiler libs as DLLs next to your executable. To find out what's missing use dependencywalke. Copy the missing DLLs next to your exe. – Jens A. Koch Mar 26 '20 at 12:51
  • It's working what you give it to me over there with just 2 exceptions. 1. I needed to add this command into **windeployqt** `--qmldir ${_qt_bin_dir}"/../qml"` 2. I need to add those libraries instead of `libgcc_s_seh-1.dll, libstdc++-6.dll, libwinpthread-1.dll` And all the build and CMake is working but I do have just one problem more. When I'm running the executable I'm receiving this error message. `qrc:/main.qml:3:1: module "QtQuick.Shapes" is not installed` Could you help me with this last problem? – Mircea Mar 26 '20 at 13:52
  • Seems you are pulling in Qt's QML stuff instead of the ones needed for your application. Maybe change the inclusion path to the .qml files in your project sources, .e.g `--qmldir ${PROJECT_SOURCE_DIR}/qml` I don't know if the top level project folder is enough, maybe windeployqt recurses the folder structure and picks up every qml file.. – Jens A. Koch Mar 26 '20 at 14:55
  • Is there an automatic feature detection so I don't have to exclude the features manually? – Amin Ya Nov 12 '21 at 12:12
  • the approach with post-build custom command works quite good, but how do you copy Qt modules during the install step? They aren't picked up automagically from the build dir – AntonK Aug 13 '22 at 17:30
0

Follow-up for your mingw dependencies: ...

If Qt is installed with MinGW as well, you can avoid additional copy operattions for runtime libraries within add_custom_command just using windeployqt.exe with --compiler-runtime command line option.

algo99
  • 69
  • 3
0

Building off of @Jens A. Koch's solution, I made two CMake macros. In my case, QT_DIR is set to C:\Qt\5.15.2\msvc2019_64. I know that there are more elegant solutions, but I'm not a pro at CMake. Feel free to offer suggestions.

# Set a variable called DEBUG_OR_RELEASE_LOWER_CASE to either debug or release
# USAGE: set_debug_or_release_variable()
macro (set_debug_or_release_variable)
    if(DEFINED CMAKE_CONFIGURATION_TYPES)
        # defined for Ninja, but not msbuild
        if ("Debug" STREQUAL ${CMAKE_CONFIGURATION_TYPES})
            set(DEBUG_OR_RELEASE_LOWER_CASE debug)
        else()
            set(DEBUG_OR_RELEASE_LOWER_CASE release)
        endif()
    else()
        #defined for msbuild, but not Ninja
        if ("Debug" STREQUAL ${CMAKE_BUILD_TYPE})
            set(DEBUG_OR_RELEASE_LOWER_CASE debug)
        else()
            set(DEBUG_OR_RELEASE_LOWER_CASE release)
        endif()
    endif()
endmacro (set_debug_or_release_variable)

# Based on Jens A. Koch's solution at https://stackoverflow.com/questions/60854495/qt5-cmake-include-all-libraries-into-executable#:~:text=To%20solve%20this%20i%20would%20suggest%20using%20windeployqt.,it%20into%20%2Fcmake%20modules%20folder%20of%20your%20project%3A
# USAGE: set_target_deplay_qt ${PROJECT_NAME} {debug|release}
macro (set_target_deploy_qt arg1 arg2)
    if(NOT EXISTS "${QT_DIR}/bin/windeployqt.exe")
        message(FATAL_ERROR "windeployqt.exe not found in '${QT_DIR}/bin'. Please check that your Qt installation includes the deployment tool.")
    endif()

    # NOTE: arg2 is lower case 'debug' or 'release'.
    add_custom_command(TARGET ${arg1} POST_BUILD COMMAND "${QT_DIR}/bin/windeployqt.exe"
                --${arg2}
                \"$<TARGET_FILE:${arg1}>\"
        COMMENT "Deploying Qt libraries using windeployqt.exe for compilation target '${arg1}' ..."
    )
endmacro (set_target_deploy_qt)

Then in root CMakeLists.txt:

set_debug_or_release_variable()
message(STATUS ----DEBUG_OR_RELEASE_LOWER_CASE " " ${DEBUG_OR_RELEASE_LOWER_CASE}-----)

And in executable project's CMakeLists.txt:

# Copy Qt dependencies to output folder
set_target_deploy_qt(${PROJECT_NAME} ${DEBUG_OR_RELEASE_LOWER_CASE})
Dale Barnard
  • 779
  • 1
  • 7
  • 16