How to add icon to a Qt application on Windows using a .rc file on a CMake project?

Viewed 1175

I'm trying to add an application icon to an application I'm writing, following what is described in https://doc.qt.io/qt-5/appicon.html

I'm using Qt Desktop 5.15.2 (64) and 6.1.2 (64) for both MinGW and MSVC, on Windows 10 64 bits. They all compile without error or warnings, but the icon doesn't show up.

My CMakeFile.txt:

cmake_minimum_required(VERSION 3.14)

project(MyApp VERSION 0.1 LANGUAGES CXX)

set(CMAKE_INCLUDE_CURRENT_DIR ON)

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

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# QtCreator supports the following variables for Android, which are identical to qmake Android variables.
# Check https://doc.qt.io/qt/deployment-android.html for more information.
# They need to be set before the find_package(...) calls below.

if(ANDROID)
    set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
#    if (ANDROID_ABI STREQUAL "armeabi-v7a")
#        set(ANDROID_EXTRA_LIBS
#            ${CMAKE_CURRENT_SOURCE_DIR}/path/to/libcrypto.so
#            ${CMAKE_CURRENT_SOURCE_DIR}/path/to/libssl.so)
#    endif()
endif()

find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Quick LinguistTools REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Quick LinguistTools REQUIRED)

set(TS_FILES _pt_BR.ts)

set(PROJECT_SOURCES
        main.cpp
        qml.qrc
        ${TS_FILES}
)

if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
    set(APP_ICON_RESOURCE_WINDOWS "${CMAKE_CURRENT_SOURCE_DIR}/MyApp.rc")
    qt_add_executable(MyApp
        MANUAL_FINALIZATION
        ${PROJECT_SOURCES}
        ${APP_ICON_RESOURCE_WINDOWS}
    )

    qt_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES})
else()
    if(ANDROID)
        add_library(MyApp SHARED
            ${PROJECT_SOURCES}
        )
    elseif(WIN32)
        set(APP_ICON_RESOURCE_WINDOWS "${CMAKE_CURRENT_SOURCE_DIR}/windows/MyApp.rc")
        add_executable(MyApp
            ${PROJECT_SOURCES}
            ${APP_ICON_RESOURCE_WINDOWS}
        )

    else()
        add_executable(MyApp
          ${PROJECT_SOURCES}
        )
    endif()

    qt5_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES})
endif()

target_compile_definitions(MyApp
  PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
target_link_libraries(MyApp
  PRIVATE Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Quick)

set_target_properties(MyApp PROPERTIES
    MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
    MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
    MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
)

if(QT_VERSION_MAJOR EQUAL 6)
    qt_import_qml_plugins(MyApp)
    qt_finalize_executable(MyApp)
endif()

MyApp.rc:

MyAppIcon ICON "MyApp.ico"

The .ico contains a single 256x256 32-bit RGBA image.

For what matters, after so many failures I tried creating a test project using qmake, and added the icon using RC_ICONS = QtTest.ico the .pro file, which worked (got the correct icon). When I tried using the RC_FILE = QtTest.rc instead it used the default icon, but without any warnings or errors.

Just in case I generated the .res file using windres, but to no avail. Changed QtTestIco ICON "QtTest.ico" and regenerated the .res, the same result.

Substituting the CMakeList.txt for a .pro file and using the RC_ICONS is not an option, sadly.

Somebody could help me, please?

Thanks in advance.

2 Answers

In order to add a Microsoft resources (RC) file, you need to tell CMake to support the "RC" language by enabling Microsoft's RC language. This will kick in the resource compiler when it detects a file with the *.rc extension in your project.

Here is a sample code snippet:

if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
    enable_language("RC")
    set (WIN32_RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/windows/MyApp.rc)
endif()

add_executable(MyApp WIN32
    ${PROJECT_SOURCES}
    ${WIN32_RESOURCES}
)

Build your project and Microsoft Explorer will then see your icon.

Suppose you have (core and myapp just as an example):

core/
   CMakeLists.txt
   myapp.ico
   myapp.rc
   ...other dirs with your sources...

Your myapp.rc contains:

IDI_ICON1               ICON    DISCARDABLE     "myapp.ico"

Suppose you have MS VC Build Tools installed and you have x64 Native Tools Command Prompt open. And you build your project using cmake, etc. It means that there you also have rc cmd program there. So in your prompt do:

C:\Users\MyName\myapprepo\core>    rc  myapp.rc

Then you get a binary file myapp.res:

core/
   CMakeLists.txt
   myapp.ico
   myapp.rc
   myapp.res

So now, you need to link this binary file to our lib/app. In my case it was a lib I called core and I would link it to my executable myapp. It does not matter. The point is that you should link the file:

# core/CMakeLists.txt

target_link_libraries(${CORE_LIBRARY_NAME} 
                      ${CMAKE_CURRENT_SOURCE_DIR}/myapp.res 
                      Qt5::Widgets)

The MS VC compiler knows what to do when linking the res file to your lib/exe. So don't worry about the strange entity. In general, the whole procedure is exactly as it is described in the docs https://doc.qt.io/archives/qt-4.8/appicon.html:

If you do not use qmake, the necessary steps are: first, run the rc program on the .rc file, then link your application with the resulting .res file.

If any question, ask in comments. Good luck!

Related