Add credits for Marek
[trojita.git] / cmake / TrojitaNSIS.cmake
blob5a0eba29eba52f23bfd31f752cf1a226ae2c340c
1 # Create NSIS Installer, check for all dependent DLL libraries and include them into Installer
3 ### Generate list of files for inclusion into installer ###
5 if(POLICY CMP0026)
6     # reading the LOCATION property
7     cmake_policy(SET CMP0026 OLD)
8 endif()
10 # Include trojita executable
11 get_target_property(TROJITA_EXE_PATH trojita LOCATION)
12 get_filename_component(TROJITA_EXE ${TROJITA_EXE_PATH} NAME)
13 file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/trojita-files.nsi.in "!define TROJITA_EXE_PATH \"${TROJITA_EXE_PATH}\"\n!define TROJITA_EXE \"${TROJITA_EXE}\"\n")
15 # Include trojita icon
16 get_filename_component(TROJITA_ICON_PATH ${CMAKE_CURRENT_SOURCE_DIR}/src/icons/trojita.ico REALPATH)
17 file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/trojita-files.nsi.in "!define TROJITA_ICON_PATH \"${TROJITA_ICON_PATH}\"\n")
19 set(TROJITA_INSTALL_FILES "")
21 set(TROJITA_LIBRARIES "")
22 set(TROJITA_LIBRARIES_PATHS "")
24 # Prepare a list of all Qt plugins which are needed.
25 # We need a hardcoded list of plugin types because I'm too lazy to find out how to work with associative arrays/hashmaps in cmake.
26 set(TROJITA_QT_PLUGIN_TYPES bearer generic iconengines imageformats sqldrivers platforms)
28 foreach(plugintype ${TROJITA_QT_PLUGIN_TYPES})
29     set(TROJITA_QT_${plugintype}_PLUGINS "")
30 endforeach()
32 foreach(plugin ${Qt5Gui_PLUGINS} ${Qt5Network_PLUGINS} Qt5::QSQLiteDriverPlugin Qt5::QSvgIconPlugin)
33   get_target_property(_loc ${plugin} LOCATION)
35   set(plugin_recognized FALSE)
37   foreach(plugintype ${TROJITA_QT_PLUGIN_TYPES})
38       if(${_loc} MATCHES "/plugins/${plugintype}/.*\\.dll$")
39           list(APPEND TROJITA_QT_${plugintype}_PLUGINS ${_loc})
40           set(plugin_recognized TRUE)
41       endif()
42   endforeach()
44   if(NOT ${plugin_recognized})
45       message(FATAL_ERROR "Unrecognized Qt plugin -- don't know where to put it: ${_loc}")
46   endif()
48 endforeach()
50 # Qt doesn't really link with OpenSSL, but loads it during runtime, which means that our objdump won't find the DLL names.
51 # Of course, the library names are provided through the .dll.a convention, and I'm too lazy to write code which converts
52 # them to just DLLs, so we support either passing them explicitly, or we require CMake 4.4 and its OpenSSL imported targets.
53 # The reason for this is that we only have cmake-3.3 in the CI so far.
54 if(NOT (EXISTS "${OpenSSL_Crypto_LOC}" AND EXISTS "${OpenSSL_SSL_LOC}"))
55     find_package(OpenSSL REQUIRED)
56     cmake_minimum_required(VERSION 3.4.0)
57     get_target_property(OpenSSL_SSL_LOC OpenSSL::SSL LOCATION)
58     get_target_property(OpenSSL_Crypto_LOC OpenSSL::Crypto LOCATION)
59 endif()
61 # We don't have trojita.exe at CMake time yet, so we have to take a look at all the stuff which we know is going to be needed.
62 # I could probably write some CMake code to handle this, but sorry, that's ETOOCOMPLEX for me. Instead, I chose to write this
63 # ugly beast and to swear each time in future when the list of libraries which Trojita links against gets extended, and someone
64 # forgets to update *this* hardcoded list. Patches which improve this are very welcome.
66 get_target_property(QtCore_LOC Qt5::Core LOCATION)
67 get_target_property(QtGui_LOC Qt5::Gui LOCATION)
68 get_target_property(QtNetwork_LOC Qt5::Network LOCATION)
69 get_target_property(QtSql_LOC Qt5::Sql LOCATION)
70 get_target_property(QtWebKitWidgets_LOC Qt5::WebKitWidgets LOCATION)
71 get_target_property(QtWidgets_LOC Qt5::Widgets LOCATION)
72 set(required_dll_names ${QtCore_LOC} ${QtGui_LOC} ${QtNetwork_LOC} ${QtSql_LOC} ${QtWebKitWidgets_LOC} ${QtWidgets_LOC} ${OpenSSL_SSL_LOC} ${OpenSSL_Crypto_LOC})
73 if(WITH_DBUS)
74     get_target_property(QtDBus_LOC Qt5::DBus LOCATION)
75     list(APPEND required_dll_names ${QtDBus_LOC})
76 endif()
78 find_package(PythonInterp REQUIRED interpreter)
80 message(STATUS "Determining the list of required DLL files...")
81 set(all_plugin_dlls "")
82 foreach(plugintype ${TROJITA_QT_PLUGIN_TYPES})
83     list(APPEND all_plugin_dlls ${TROJITA_QT_${plugintype}_PLUGINS})
84 endforeach()
85 execute_process(COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/packaging/mingw-bundledlls
86     ${required_dll_names} ${all_plugin_dlls}
87     WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
88     OUTPUT_VARIABLE library_dependencies_STR)
89 # convert from one-file-per-line into a cmake list
90 string(REPLACE "\n" ";" library_dependencies "${library_dependencies_STR}")
92 # because mingw-bundledlls filters out the name of the libraries which were passed on the command line
93 list(APPEND library_dependencies ${required_dll_names})
95 # ...and here we go!
96 foreach(dll_lib ${library_dependencies})
97     message(STATUS "Including DLL: ${dll_lib}")
98 endforeach()
99 set(TROJITA_INSTALL_FILES "${TROJITA_INSTALL_FILES};${library_dependencies}")
102 # Include be.contacts executable
103 get_target_property(FILE_PATH be.contacts LOCATION)
104 list(APPEND TROJITA_INSTALL_FILES "${FILE_PATH}")
106 # Include common library for plugins
107 if(WITH_SHARED_PLUGINS)
108     get_target_property(FILE_PATH Plugins LOCATION)
109     list(APPEND TROJITA_INSTALL_FILES "${FILE_PATH}")
110 endif()
112 # Include all shared plugins
113 get_property(SHARED_PLUGINS GLOBAL PROPERTY TROJITA_SHARED_PLUGINS)
114 foreach(PLUGIN ${SHARED_PLUGINS})
115     get_target_property(FILE_PATH ${PLUGIN} LOCATION)
116     list(APPEND TROJITA_INSTALL_FILES "${FILE_PATH}")
117 endforeach()
119 # Include additional files
120 list(APPEND TROJITA_INSTALL_FILES "${CMAKE_CURRENT_SOURCE_DIR}/README")
121 list(APPEND TROJITA_INSTALL_FILES "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
123 # Generate list of install files
124 file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/trojita-files.nsi.in "!macro TROJITA_INSTALL_FILES\n")
125 foreach(FILE_PATH ${TROJITA_INSTALL_FILES})
126     file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/trojita-files.nsi.in "File \"${FILE_PATH}\"\n")
127 endforeach()
128 if(Qt5LinguistForTrojita_FOUND)
129     if(num_languages)
130         file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/trojita-files.nsi.in "File /r /x *.ts /x x_test locale\n")
131     endif()
132 endif()
133 foreach(plugintype ${TROJITA_QT_PLUGIN_TYPES})
134     file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/trojita-files.nsi.in "SetOutPath \"\$INSTDIR\\${plugintype}\"\n")
135     foreach(plugin ${TROJITA_QT_${plugintype}_PLUGINS})
136         file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/trojita-files.nsi.in "File \"${plugin}\"\n")
137         message(STATUS "Including ${plugintype} plugin: ${plugin}")
138     endforeach()
139 endforeach()
141 file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/trojita-files.nsi.in "!macroend\n")
143 # Generate list of uninstall files
144 file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/trojita-files.nsi.in "!macro TROJITA_UNINSTALL_FILES\n")
145 if(Qt5LinguistForTrojita_FOUND)
146     if(num_languages)
147         file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/trojita-files.nsi.in "RMDir /r \"\$INSTDIR\\locale\"\n")
148     endif()
149 endif()
151 foreach(plugintype ${TROJITA_QT_PLUGIN_TYPES})
152     foreach(plugin ${TROJITA_QT_${plugintype}_PLUGINS})
153         get_filename_component(plugin_basename ${plugin} NAME)
154         file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/trojita-files.nsi.in "Delete \"\$INSTDIR\\${plugintype}\\${plugin_basename}\"\n")
155     endforeach()
156     file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/trojita-files.nsi.in "RMDir \"\$INSTDIR\\${plugintype}\"\n")
157 endforeach()
159 foreach(FILE_PATH ${TROJITA_INSTALL_FILES})
160     get_filename_component(FILE_NAME ${FILE_PATH} NAME)
161     file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/trojita-files.nsi.in "Delete \"\$INSTDIR\\${FILE_NAME}\"\n")
162 endforeach()
163 file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/trojita-files.nsi.in "!macroend\n")
165 execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/trojita-files.nsi.in ${CMAKE_CURRENT_BINARY_DIR}/trojita-files.nsi)
167 ### Generate installer ###
169 if(CMAKE_SIZEOF_VOID_P STREQUAL 4)
170     set(MAKENSIS_OUTPUT Trojita-Setup.exe)
171 else()
172     set(MAKENSIS_FLAGS -DX86_64 ${MAKENSIS_FLAGS})
173     set(MAKENSIS_OUTPUT Trojita-Setup-x86_64.exe)
174 endif()
176 if(NOT CMAKE_VERBOSE_MAKEFILE)
177     set(MAKENSIS_FLAGS -V2 -DQUIET ${MAKENSIS_FLAGS})
178 endif()
180 set(MAKENSIS_FLAGS ${MAKENSIS_FLAGS} -NOCD)
182 add_custom_command(OUTPUT ${MAKENSIS_OUTPUT}
183     COMMAND ${MAKENSIS}
184     ARGS ${MAKENSIS_FLAGS} ${CMAKE_CURRENT_SOURCE_DIR}/packaging/trojita.nsi
185     DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/packaging/trojita.nsi ${CMAKE_CURRENT_BINARY_DIR}/trojita-files.nsi ${TROJITA_EXE_PATH} ${TROJITA_ICON_PATH} ${TROJITA_INSTALL_FILES} version)
186 add_custom_target(installer ALL DEPENDS ${MAKENSIS_OUTPUT})