3 # Wireshark - Network traffic analyzer
4 # By Gerald Combs <gerald@wireshark.org>
5 # Copyright 1998 Gerald Combs
7 # SPDX-License-Identifier: GPL-2.0-or-later
10 # We should use CPack to generate the NSIS package. Even better,
11 # we should use CPack to create a .msi using WiX.
13 set(WIRESHARK_NSIS_GENERATED_FILES
14 ${CMAKE_CURRENT_BINARY_DIR}/wireshark-manifest.nsh
15 ${CMAKE_CURRENT_BINARY_DIR}/wireshark-config.nsh
17 if(NOT SKIP_NSIS_QT_DLLS)
18 list(APPEND WIRESHARK_NSIS_GENERATED_FILES ${CMAKE_CURRENT_BINARY_DIR}/wireshark-qt-manifest.nsh)
20 set(WIRESHARK_NSIS_GENERATED_FILES ${WIRESHARK_NSIS_GENERATED_FILES} PARENT_SCOPE)
22 set(WIRESHARK_NSIS_FILES
23 ${CMAKE_CURRENT_SOURCE_DIR}/wireshark.nsi
24 ${CMAKE_CURRENT_SOURCE_DIR}/wireshark-common.nsh
25 ${CMAKE_CURRENT_SOURCE_DIR}/servicelib.nsh
26 ${CMAKE_CURRENT_SOURCE_DIR}/NpcapPage.ini
27 ${CMAKE_CURRENT_SOURCE_DIR}/USBPcapPage.ini
28 ${WIRESHARK_NSIS_GENERATED_FILES}
32 set(STRATOSHARK_NSIS_GENERATED_FILES
33 ${CMAKE_CURRENT_BINARY_DIR}/stratoshark-manifest.nsh
34 ${CMAKE_CURRENT_BINARY_DIR}/stratoshark-config.nsh
35 ${CMAKE_CURRENT_BINARY_DIR}/stratoshark-qt-manifest.nsh
37 set(STRATOSHARK_NSIS_GENERATED_FILES ${STRATOSHARK_NSIS_GENERATED_FILES} PARENT_SCOPE)
39 set(STRATOSHARK_NSIS_FILES
41 stratoshark-common.nsh
45 ${STRATOSHARK_NSIS_GENERATED_FILES}
49 # Variables required for config.nsh
50 set(PROGRAM_NAME ${CMAKE_PROJECT_NAME})
51 set(LOG_PROGRAM_NAME ${LOG_PROJECT_NAME})
52 file(TO_NATIVE_PATH "${CMAKE_SOURCE_DIR}" TOP_SRC_DIR)
53 # STAGING_DIR depends on the build configuration so we pass it
54 # on the command line below.
55 file(TO_NATIVE_PATH "${CMAKE_BINARY_DIR}/doc" DOC_DIR)
56 set (MMDBRESOLVE_EXE ${MAXMINDDB_FOUND})
59 # - Sync the various version names between CMake and NSIS.
60 # - Set CMakeLists.txt version strings in tools/make-version.py
61 # - Add a VERSION_EXTRA cmake option
62 set (PRODUCT_VERSION ${PROJECT_MAJOR_VERSION}.${PROJECT_MINOR_VERSION}.${PROJECT_PATCH_VERSION}.${PROJECT_BUILD_VERSION})
63 set (LOG_PRODUCT_VERSION ${LOG_PROJECT_MAJOR_VERSION}.${LOG_PROJECT_MINOR_VERSION}.${PROJECT_PATCH_VERSION}.${PROJECT_BUILD_VERSION})
65 if((BUILD_wireshark OR BUILD_stratoshark) AND QT_FOUND)
66 set (QT_DIR "\${STAGING_DIR}")
69 # Look for the Visual C++ Redistributable packages in the following locations:
71 # - _PROJECT_LIB_DIR/vcredist_MSVCxx
73 # - %VCINSTALLDIR%/redist/1033 (<= Visual Studio 2015)
74 # - %VCINSTALLDIR%/Redist/MSVC/* (>= Visual Studio 2017)
75 # MSVC_VERSION (_MSC_VER) = Visual Studio Version / MSVC Toolset Version
76 # 1900 = VS2015 14.0 / 14.00
77 # 1910 = VS2017 15.1, 15.2 / 14.10
78 # 1911 = VS2017 15.3, 15.4 / 14.11
79 # 1912 = VS2017 15.5 / 14.12
80 # 1913 = VS2017 15.6 / 14.13
81 # 1914 = VS2017 15.7 / 14.14
82 if(MSVC_VERSION GREATER_EQUAL 1930)
83 set(_ws_vcredist_subdir "vcredist_MSVC2022")
84 elseif(MSVC_VERSION GREATER_EQUAL 1920)
85 set(_ws_vcredist_subdir "vcredist_MSVC2019")
86 set(_msvs_version 15.0) # Doesn't appear to be set
87 elseif(MSVC_VERSION GREATER_EQUAL 1910)
88 set(_ws_vcredist_subdir "vcredist_MSVC2017")
89 set(_msvs_version 15.0)
90 elseif(MSVC_VERSION GREATER_EQUAL 1900)
91 set(_ws_vcredist_subdir "vcredist_MSVC2015")
92 set(_ms_vcredist_subdir "redist/1033")
93 set(_msvs_version 14.0)
96 # Try to find the Redist folder in VCINSTALLDIR which is set by vcvarsall.bat.
97 # If it is not set, query it within the registry. VS2015 looks for the "VC7" key
98 # in two locations (four if you count HKCU instead of HKLM). However, VS2017
99 # does not use "VC7" (it sets a directory relative to vsdevcmd_start.bat). As
100 # both versions do set "VS7", use that instead.
101 find_path(VCINSTALLDIR Redist PATHS
103 "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VS7;${_msvs_version}]\\VC"
104 "[HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Microsoft\\VisualStudio\\SxS\\VS7;${_msvs_version}]\\VC"
107 file(TO_NATIVE_PATH "${VCINSTALLDIR}" VCINSTALLDIR_NATIVE)
108 message(STATUS "Using VCINSTALLDIR: ${VCINSTALLDIR_NATIVE}")
110 # Visual Studio Community 2017 version 15.7.5 uses VCRT 14.14.26405, but an
111 # earlier version used 14.10.25008. Let's just glob for the right value.
112 if(MSVC_VERSION GREATER_EQUAL 1910 AND VCINSTALLDIR)
113 file(GLOB _ms_vcredist_subdir RELATIVE "${VCINSTALLDIR}"
114 "${VCINSTALLDIR}/Redist/MSVC/14.*.*")
117 find_program(_vcredist
119 "vc_redist.${WIRESHARK_TARGET_PLATFORM}.exe" # Visual Studio 2022 and later
120 "vcredist_${WIRESHARK_TARGET_PLATFORM}.exe" # Visual Studio 2019 and earlier
121 PATHS "${_PROJECT_LIB_DIR}" $ENV{VCToolsRedistDir} "${VCINSTALLDIR}"
122 PATH_SUFFIXES ${_ws_vcredist_subdir} ${_ms_vcredist_subdir}
126 file(TO_NATIVE_PATH "${_vcredist}" _vcredist)
127 message(STATUS "Using ${_vcredist} for the NSIS installer.")
128 get_filename_component(VCREDIST_DIR ${_vcredist} DIRECTORY)
129 get_filename_component(VCREDIST_EXE ${_vcredist} NAME)
133 # Ideally we would generate this at compile time using a separate cmake
134 # module, e.g. cmake/modules/configure_nsis_file.cmake. However we would
135 # have to figure out a clean way to pass in the variables above.
136 file(READ "${CMAKE_CURRENT_SOURCE_DIR}/wireshark-config.nsh.in" _config_nsh_contents)
137 string(CONFIGURE "${_config_nsh_contents}" _config_nsh_contents)
138 string(REPLACE "#define" "!define" _config_nsh_contents "${_config_nsh_contents}")
139 string(REPLACE "#undef" "!undef" _config_nsh_contents "${_config_nsh_contents}")
140 file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/wireshark-config.nsh" "${_config_nsh_contents}")
142 # wireshark-manifest.nsh. Can be created at configure time.
143 set(_all_manifest "${CMAKE_CURRENT_BINARY_DIR}/wireshark-manifest.nsh")
144 set(_all_manifest_contents "# Files required for all sections. Generated by CMake.\n")
146 set(_all_manifest_contents "${_all_manifest_contents}!ifdef BUNDLE_DEBUG_DLLS\n")
147 foreach(_dll ${GLIB2_DLLS_DEBUG})
148 set(_all_manifest_contents "${_all_manifest_contents}File \"\${STAGING_DIR}\\${_dll}\"\n")
150 set(_all_manifest_contents "${_all_manifest_contents}!else\n")
151 foreach(_dll ${GLIB2_DLLS_RELEASE})
152 set(_all_manifest_contents "${_all_manifest_contents}File \"\${STAGING_DIR}\\${_dll}\"\n")
154 set(_all_manifest_contents "${_all_manifest_contents}!endif\n")
155 foreach(_dll ${AMRNB_DLL} ${CARES_DLL} ${PCRE2_RELEASE_DLL} ${GCRYPT_DLLS}
156 ${GNUTLS_DLLS} ${KERBEROS_DLLS} ${LIBSSH_DLLS} ${LUA_DLL}
157 ${LZ4_DLL} ${MINIZIP_DLL} ${MINIZIPNG_DLLS} ${NGHTTP2_DLL} ${NGHTTP3_DLL} ${SBC_DLL} ${SMI_DLL}
158 ${SNAPPY_DLL} ${SPANDSP_DLL} ${BCG729_DLL} ${LIBXML2_DLLS} ${WINSPARKLE_DLL}
159 ${ZLIB_DLL} ${ZLIBNG_DLL} ${BROTLI_DLLS} ${ZSTD_DLL} ${ILBC_DLL} ${OPUS_DLL}
161 # Needed for mmdbresolve
164 set(_all_manifest_contents "${_all_manifest_contents}File \"\${STAGING_DIR}\\${_dll}\"\n")
167 include(${CMAKE_CURRENT_SOURCE_DIR}/InstallMSYS2.cmake)
168 foreach(_dll ${MINGW_DLLS})
169 file(TO_NATIVE_PATH ${_dll} _path)
170 set(_all_manifest_contents "${_all_manifest_contents}File \"${_path}\"\n")
173 include(${CMAKE_CURRENT_SOURCE_DIR}/InstallMinGW.cmake)
174 foreach(_dll ${MINGW_DLLS})
175 file(TO_NATIVE_PATH ${_dll} _path)
176 set(_all_manifest_contents "${_all_manifest_contents}File \"${_path}\"\n")
179 file(WRITE "${_all_manifest}" "${_all_manifest_contents}")
182 if (BUILD_stratoshark)
183 # Ideally we would generate this at compile time using a separate cmake
184 # module, e.g. cmake/modules/configure_nsis_file.cmake. However we would
185 # have to figure out a clean way to pass in the variables above.
186 file(READ "${CMAKE_CURRENT_SOURCE_DIR}/stratoshark-config.nsh.in" _config_nsh_contents)
187 string(CONFIGURE "${_config_nsh_contents}" _config_nsh_contents)
188 string(REPLACE "#define" "!define" _config_nsh_contents "${_config_nsh_contents}")
189 string(REPLACE "#undef" "!undef" _config_nsh_contents "${_config_nsh_contents}")
190 file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/stratoshark-config.nsh" "${_config_nsh_contents}")
192 # stratoshark-manifest.nsh. Can be created at configure time.
193 set(_all_manifest "${CMAKE_CURRENT_BINARY_DIR}/stratoshark-manifest.nsh")
194 set(_all_manifest_contents "# Files required for all sections. Generated by CMake.\n")
195 set(_all_manifest_contents "${_all_manifest_contents}!ifdef BUNDLE_DEBUG_DLLS\n")
196 foreach(_dll ${GLIB2_DLLS_DEBUG})
197 set(_all_manifest_contents "${_all_manifest_contents}File \"\${STAGING_DIR}\\${_dll}\"\n")
199 set(_all_manifest_contents "${_all_manifest_contents}!else\n")
200 foreach(_dll ${GLIB2_DLLS_RELEASE})
201 set(_all_manifest_contents "${_all_manifest_contents}File \"\${STAGING_DIR}\\${_dll}\"\n")
203 set(_all_manifest_contents "${_all_manifest_contents}!endif\n")
204 foreach(_dll ${AMRNB_DLL} ${CARES_DLL} ${PCRE2_RELEASE_DLL} ${GCRYPT_DLLS}
205 ${GNUTLS_DLLS} ${KERBEROS_DLLS} ${LIBSSH_DLLS} ${LUA_DLL}
206 ${LZ4_DLL} ${MINIZIP_DLL} ${MINIZIPNG_DLLS} ${NGHTTP2_DLL} ${NGHTTP3_DLL} ${SBC_DLL} ${SMI_DLL}
207 ${SNAPPY_DLL} ${SPANDSP_DLL} ${BCG729_DLL} ${LIBXML2_DLLS} ${WINSPARKLE_DLL}
208 ${ZLIB_DLL} ${ZLIBNG_DLL} ${BROTLI_DLLS} ${ZSTD_DLL} ${ILBC_DLL} ${OPUS_DLL}
210 # Needed for mmdbresolve
213 set(_all_manifest_contents "${_all_manifest_contents}File \"\${STAGING_DIR}\\${_dll}\"\n")
215 file(WRITE "${_all_manifest}" "${_all_manifest_contents}")
218 file(TO_NATIVE_PATH "${DATAFILE_DIR}" _staging_dir)
219 file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}" _outfile_dir)
220 file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}" _nsis_include_dir)
222 # Variables we can't set via config.nsh.
224 -DSTAGING_DIR=${_staging_dir}
225 -DOUTFILE_DIR=${_outfile_dir}
226 -DNSIS_INCLUDE_DIR=${_nsis_include_dir}
231 macro( ADD_NSIS_PACKAGE_TARGETS )
232 set (_nsis_source_dir ${CMAKE_SOURCE_DIR}/packaging/nsis )
233 set (_nsis_binary_dir ${CMAKE_BINARY_DIR}/packaging/nsis )
235 # XXX - if we're not building Wireshark, we can't build the
236 # manifest below. On the other hand, if we're not building
237 # Wireshark, we have no need to include Qt in the installer,
238 # so it's not clear we need this manifest.
240 # This should probably be fixed, so that people can produce
241 # command-line-only installer packages.
243 # wireshark-qt-manifest.nsh. Created using Wireshark.exe.
244 if(NOT SKIP_NSIS_QT_DLLS)
246 add_custom_command(OUTPUT ${_nsis_binary_dir}/wireshark-qt-manifest.nsh
247 COMMAND set "PATH=${QT_BIN_PATH};%PATH%"
248 COMMAND ${POWERSHELL_COMMAND} "${_nsis_source_dir}/windeployqt-to-nsis.ps1"
249 -Executable $<TARGET_FILE:wireshark>
250 -FilePath ${_nsis_binary_dir}/wireshark-qt-manifest.nsh
251 $<$<CONFIG:Debug>:-DebugConfig>
253 "${_nsis_source_dir}/windeployqt-to-nsis.ps1"
254 $<TARGET_FILE:wireshark>
257 add_custom_command(OUTPUT ${_nsis_binary_dir}/wireshark-qt-manifest.nsh
258 COMMAND ${Python3_EXECUTABLE} "${_nsis_source_dir}/windeployqt-to-nsis.py"
259 --executable $<TARGET_FILE:wireshark>
260 ${_nsis_binary_dir}/wireshark-qt-manifest.nsh
261 #$<$<CONFIG:Debug>:-DebugConfig>
263 "${_nsis_source_dir}/windeployqt-to-nsis.py"
264 $<TARGET_FILE:wireshark>
266 elseif(MINGW AND CMAKE_CROSSCOMPILING)
267 add_custom_command(OUTPUT ${_nsis_binary_dir}/wireshark-qt-manifest.nsh
268 COMMAND ${Python3_EXECUTABLE} "${_nsis_source_dir}/windeployqt-to-nsis.py"
269 --sysroot "${MINGW_SYSROOT}"
270 --mapping "${_nsis_source_dir}/mingw64-qt-mapping.txt"
271 ${_nsis_binary_dir}/wireshark-qt-manifest.nsh
272 #$<$<CONFIG:Debug>:-DebugConfig>
274 "${_nsis_source_dir}/windeployqt-to-nsis.py"
275 "${_nsis_source_dir}/mingw64-qt-mapping.txt"
278 message(FATAL_ERROR "Unknown Qt deployment method")
282 # Build NSIS package dependencies. We build the package in
283 # two stages so that wireshark_nsis below doesn't trigger
284 # any dependencies that might clobber any signed executables.
285 add_custom_target(wireshark_nsis_prep
287 ${WIRESHARK_NSIS_FILES}
293 set_target_properties(wireshark_nsis_prep PROPERTIES
295 EXCLUDE_FROM_DEFAULT_BUILD True
298 # Make sure required blobs are available
299 FetchContent_MakeAvailable(Npcap USBPcap)
301 # Dump the installer into
302 # ${CMAKE_CURRENT_SOURCE_DIR}/packaging/nsis
303 # Note that executables and DLLs *must* be built separately
304 add_custom_target(wireshark_nsis
305 COMMAND ${MAKENSIS_EXECUTABLE} ${NSIS_OPTIONS}
306 $<$<CONFIG:Debug>:-DBUNDLE_DEBUG_DLLS>
307 $<$<BOOL:${MSVC}>:-DUSE_VCREDIST>
309 WORKING_DIRECTORY ${_nsis_source_dir}
311 set_target_properties(wireshark_nsis PROPERTIES
313 EXCLUDE_FROM_DEFAULT_BUILD True
317 if(BUILD_stratoshark)
318 # stratoshark-qt-manifest.nsh. Created using Wireshark.exe.
319 add_custom_command(OUTPUT ${_nsis_binary_dir}/stratoshark-qt-manifest.nsh
320 COMMAND set "PATH=${QT_BIN_PATH};%PATH%"
321 COMMAND ${POWERSHELL_COMMAND} "${_nsis_source_dir}/windeployqt-to-nsis.ps1"
322 -Executable $<TARGET_FILE:stratoshark>
323 -FilePath ${_nsis_binary_dir}/stratoshark-qt-manifest.nsh
324 $<$<CONFIG:Debug>:-DebugConfig>
325 DEPENDS "${_nsis_source_dir}/windeployqt-to-nsis.ps1"
328 # Build NSIS package dependencies. We build the package in
329 # two stages so that stratoshark_nsis below doesn't trigger
330 # any dependencies that might clobber any signed executables.
331 add_custom_target(stratoshark_nsis_prep
333 ${STRATOSHARK_NSIS_FILES}
337 ${DATAFILE_DIR}/uninstall-stratoshark.exe
339 set_target_properties(stratoshark_nsis_prep PROPERTIES
341 EXCLUDE_FROM_DEFAULT_BUILD True
344 # Dump the installer into
345 # ${CMAKE_CURRENT_SOURCE_DIR}/packaging/nsis
346 # Note that executables and DLLs *must* be built separately
347 add_custom_target(stratoshark_nsis
348 COMMAND ${MAKENSIS_EXECUTABLE} ${NSIS_OPTIONS}
349 $<$<CONFIG:Debug>:-DBUNDLE_DEBUG_DLLS>
351 WORKING_DIRECTORY ${_nsis_source_dir}
353 set_target_properties(stratoshark_nsis PROPERTIES
355 EXCLUDE_FROM_DEFAULT_BUILD True
358 endmacro( ADD_NSIS_PACKAGE_TARGETS )
361 ${DATAFILE_DIR}/uninstall-wireshark.exe
362 wireshark-${VERSION}-${WIRESHARK_TARGET_PLATFORM}.exe
364 wireshark-manifest.nsh
365 wireshark-qt-manifest.nsh
366 ${DATAFILE_DIR}/uninstall-stratoshark.exe
367 stratoshark-${VERSION}-${WIRESHARK_TARGET_PLATFORM}.exe
368 stratoshark-config.nsh
369 stratoshark-manifest.nsh
370 stratoshark-qt-manifest.nsh