If you want to create a redistributable installer for a Qt app with Cmake then youve come to the right place... I ve been struggling to make Qt work with cmake on windows, and finally figure out something that works:
-
Go ahead and download Qt: https://www.qt.io/download-qt-installer
-
Select a version of Qt with MingGW 64 (and any other lib you need like openssl for example...)
-
Setup windows environment vars (note that the order matters...) for the power shell to find the tools and libs that you need.
-
Ensure you have powershell installed or get the latest version here: https://github.com/PowerShell/PowerShell
-
You need
vcredist_x64_2010.exe
to be included with your package so get it here: https://www.microsoft.com/en-us/download/details.aspx?id=26999 -
Now that everyting is installed you can create the
CMakeLists.txt
code to generate an installer:
# Add your classic CMake stuffs...
cmake_minimum_required(VERSION 3.20)
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.20")
cmake_policy(SET CMP0115 NEW)
endif()
project(
"My Cool Project"
VERSION 1.0.1
DESCRIPTION "Some really awesome project that one day will change the world..."
LANGUAGES C CXX
)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
message(STATUS "${PROJECT_NAME} ${PROJECT_VERSION} for ${CMAKE_SYSTEM_NAME} ${CMAKE_SYSTEM_PROCESSOR}")
string(TIMESTAMP PROJECT_BUILD_DATE "%Y-%m-%d")
string(TIMESTAMP PROJECT_BUILD_YEAR "%Y")
configure_file(src/build.h)
# add warnings
add_compile_options(
-Wall
-Wpedantic
-Wextra
-Wshadow
-Wformat=2
-Wstrict-overflow
-fvisibility=hidden
-fno-strict-aliasing
-Werror
)
if(DEBUG)
message(STATUS "DEBUG MODE: DO NOT RELEASE ANYTHING FROM THIS BUILD!")
add_compile_options(
-g
-O0
)
else()
message(STATUS "RELEASE MODE")
add_compile_options(
-s
-Os
-DNDEBUG
)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -s")
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
# Now for the Qt specific stuffs...
# Tells CMake where to find Qt, it need to be set right!
set(QT_PATH "C:/QT")
message(STATUS "QT Path: ${QT_PATH}")
set(QT_ENV_PATH "C:/QT/6.2.4/mingw_64")
message(STATUS "QT Env: ${QT_ENV_PATH}")
# MS Redistributable path
set(MS_VCR100 "C:/Windows/System32")
# If you are using some libraries provided by Qt, here with OpenSSL:
target_include_directories(encryption PUBLIC "${QT_PATH}/Tools/OpenSSL/Win_x64/include")
target_link_directories(encryption PUBLIC "${QT_PATH}/Tools/OpenSSL/Win_x64/lib" "${QT_PATH}/Tools/OpenSSL/Win_x64/bin")
set(CMAKE_AUTOMOC ON)
find_package(Qt6 REQUIRED COMPONENTS Core Widgets)
# Add you beautifull executable
add_executable(
my_exe
WIN32
src/build.h
src/main.cxx
src/something.cxx
src/something.hxx
)
set_target_properties(my_exe PROPERTIES
WIN32_EXECUTABLE TRUE
)
target_link_libraries(
my_exe
PUBLIC
Qt6::Widgets
Qt6::Core
encryption
)
install(
TARGETS my_exe
RUNTIME DESTINATION .
COMPONENT my_exe_installer
BUNDLE DESTINATION .
COMPONENT my_exe_installer
)
function(CPACKIFW_COMMON)
set(CPACK_PACKAGE_NAME my_exe)
set(CPACK_PACKAGE_FILE_NAME "setup_${CPACK_PACKAGE_NAME}V${PROJECT_VERSION}")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "A beautifull program")
set(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "${CPACK_PACKAGE_NAME}")
set(CPACK_COMPONENTS_ALL my_exe_installer)
set(CPACK_IFW_PACKAGE_START_MENU_DIRECTORY "My Exe")
set(CPACK_IFW_PACKAGE_PUBLISHER "Fred")
set(CPACK_GENERATOR IFW)
set(CPACK_IFW_VERBOSE ON)
set(CPACK_IFW_PACKAGE_WIZARD_STYLE Classic)
set(CPACK_CREATE_DESKTOP_LINKS "My Exe")
include(CPack REQUIRED)
include(CPackIFW REQUIRED)
cpack_add_component(
my_exe_installer
DISPLAY_NAME "My Exe"
DESCRIPTION "My Exe description"
REQUIRED
)
cpack_ifw_configure_component(
my_exe_installer
FORCED_INSTALLATION
NAME qt.my_exe.installer
VERSION ${PROJECT_VERSION} # Version of component
DEFAULT TRUE
)
endfunction()
add_custom_command(
TARGET my_exe POST_BUILD
COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/windeployqt_stuff
COMMAND windeployqt.exe --compiler-runtime --dir ${CMAKE_BINARY_DIR}/windeployqt_stuff $<TARGET_FILE:my_exe>
)
# some required Qt components
install(
DIRECTORY ${CMAKE_BINARY_DIR}/windeployqt_stuff/
DESTINATION .
COMPONENT my_exe_installer
)
# optionally add some custom DLLs
install(
DIRECTORY "src/dll/"
DESTINATION .
COMPONENT my_exe_installer
FILES_MATCHING PATTERN "*"
)
# optionally adds some files, here a default config file that goes in the config directory
install(
FILES "src/pkg/config.ini"
DESTINATION config
COMPONENT my_exe_installer
)
# optionally add some of Qt DLLs
install(
DIRECTORY "${QT_PATH}/Tools/OpenSSL/Win_x64/bin/"
DESTINATION .
COMPONENT my_exe_installer
FILES_MATCHING PATTERN "*.dll"
)
# required platforms plugins
install(
DIRECTORY "${QT_ENV_PATH}/plugins/platforms/"
DESTINATION .
COMPONENT my_exe_installer
FILES_MATCHING PATTERN "*.dll"
)
# required redistributables
install(
FILES
"${MS_VCR100}/msvcr100.dll"
"${MS_VCR100}/msvcr100_clr0400.dll"
"${MS_VCR100}/msvcrt.dll"
DESTINATION .
COMPONENT my_exe_installer
)
CPACKIFW_COMMON()
- Now that you have a working CMake file you can go ahead and build your project:
# always use a new dir for the build
mkdir build
cd build
# gen the cmake environment
cmake ../ -G "MinGW Makefiles"
# compile
mingw32-make.exe -j 4
# generate the installer package
mingw32-make.exe package
Enjoy your new installer package!