Warning, /frameworks/extra-cmake-modules/modules/ECMAddAppIcon.cmake is written in an unsupported language. File is not indexed.
0001 # SPDX-FileCopyrightText: 2014 Alex Merry <alex.merry@kde.org> 0002 # SPDX-FileCopyrightText: 2014 Ralf Habacker <ralf.habacker@freenet.de> 0003 # SPDX-FileCopyrightText: 2006-2009 Alexander Neundorf <neundorf@kde.org> 0004 # SPDX-FileCopyrightText: 2006, 2007 Laurent Montel <montel@kde.org> 0005 # SPDX-FileCopyrightText: 2007 Matthias Kretz <kretz@kde.org> 0006 # 0007 # SPDX-License-Identifier: BSD-3-Clause 0008 0009 #[=======================================================================[.rst: 0010 ECMAddAppIcon 0011 ------------- 0012 0013 Add icons to executable files and packages. 0014 0015 :: 0016 0017 ecm_add_app_icon(<sources_var_name(|target (since 5.83))> 0018 ICONS <icon> [<icon> [...]] 0019 [SIDEBAR_ICONS <icon> [<icon> [...]] # Since 5.49 0020 [OUTFILE_BASENAME <name>]) # Since 5.49 0021 ) 0022 0023 The given icons, whose names must match the pattern:: 0024 0025 <size>-<other_text>.png 0026 0027 will be added as platform-specific application icons 0028 to the variable named ``<sources_var_name>`` or, if the first argument 0029 is a target (since 5.83), to the ``SOURCES`` property of ``<target>``. 0030 Any target must be created with add_executable() and not be an alias. 0031 0032 Other icon files are ignored but on Mac SVG files can be supported and 0033 it is thus possible to mix those with png files in a single macro call. 0034 0035 The platforms currently supported are Windows and Mac OS X, on all others 0036 the call has no effect and is ignored. 0037 0038 ``<size>`` is a numeric pixel size (typically 16, 32, 48, 64, 128 or 256). 0039 ``<other_text>`` can be any other text. See the platform notes below for any 0040 recommendations about icon sizes. 0041 0042 ``SIDEBAR_ICONS`` can be used to add Mac OS X sidebar 0043 icons to the generated iconset. They are used when a folder monitored by the 0044 application is dragged into Finder's sidebar. Since 5.49. 0045 0046 ``OUTFILE_BASENAME`` will be used as the basename for the icon file. If 0047 you specify it, the icon file will be called ``<OUTFILE_BASENAME>.icns`` on Mac OS X 0048 and ``<OUTFILE_BASENAME>.ico`` on Windows. If you don't specify it, it defaults 0049 to ``<sources_var_name>.<ext>``. Since 5.49. 0050 0051 0052 Windows notes 0053 * Icons are compiled into the executable using a resource file. 0054 * Icons may not show up in Windows Explorer if the executable 0055 target does not have the ``WIN32_EXECUTABLE`` property set. 0056 * Icotool (see :find-module:`FindIcoTool`) is required. 0057 * Supported sizes: 16, 24, 32, 48, 64, 128, 256, 512 and 1024. 0058 0059 Mac OS X notes 0060 * The executable target must have the ``MACOSX_BUNDLE`` property set. 0061 * Icons are added to the bundle. 0062 * If the ksvg2icns tool from KIconThemes is available, .svg and .svgz 0063 files are accepted; the first that is converted successfully to .icns 0064 will provide the application icon. SVG files are ignored otherwise. 0065 * The tool iconutil (provided by Apple) is required for bitmap icons. 0066 * Supported sizes: 16, 32, 64, 128, 256 (and 512, 1024 after OS X 10.9). 0067 * At least a 128x128px (or an SVG) icon is required. 0068 * Larger sizes are automatically used to substitute for smaller sizes on 0069 "Retina" (high-resolution) displays. For example, a 32px icon, if 0070 provided, will be used as a 32px icon on standard-resolution displays, 0071 and as a 16px-equivalent icon (with an "@2x" tag) on high-resolution 0072 displays. That is why you should provide 64px and 1024px icons although 0073 they are not supported anymore directly. Instead they will be used as 0074 32px@2x and 512px@2x. If an SVG icon is provided, ksvg2icns will be 0075 used internally to automatically generate all appropriate sizes, 0076 including the high-resolution ones. 0077 * This function sets the ``MACOSX_BUNDLE_ICON_FILE`` variable to the name 0078 of the generated icns file, so that it will be used as the 0079 ``MACOSX_BUNDLE_ICON_FILE`` target property when you call 0080 ``add_executable``. 0081 * Sidebar icons should typically provided in 16, 32, 64, 128 and 256px. 0082 0083 Since 1.7.0. 0084 #]=======================================================================] 0085 0086 function(ecm_add_app_icon appsources_or_target) 0087 set(options) 0088 set(oneValueArgs OUTFILE_BASENAME) 0089 set(multiValueArgs ICONS SIDEBAR_ICONS) 0090 cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) 0091 0092 if(NOT ARG_ICONS) 0093 message(FATAL_ERROR "No ICONS argument given to ecm_add_app_icon") 0094 endif() 0095 if (TARGET ${appsources_or_target}) 0096 get_target_property(target_type ${appsources_or_target} TYPE) 0097 if (NOT target_type STREQUAL "EXECUTABLE") 0098 message(FATAL_ERROR "Target argument passed to ecm_add_app_icon is not an executable: ${appsources_or_target}") 0099 endif() 0100 get_target_property(aliased_target ${appsources_or_target} ALIASED_TARGET) 0101 if(aliased_target) 0102 message(FATAL_ERROR "Target argument passed to ecm_add_app_icon must not be an alias: ${appsources_or_target}") 0103 endif() 0104 endif() 0105 if(ARG_UNPARSED_ARGUMENTS) 0106 message(FATAL_ERROR "Unexpected arguments to ecm_add_app_icon: ${ARG_UNPARSED_ARGUMENTS}") 0107 endif() 0108 0109 if(APPLE) 0110 find_program(KSVG2ICNS NAMES ksvg2icns) 0111 foreach(icon ${ARG_ICONS}) 0112 get_filename_component(icon_full ${icon} ABSOLUTE) 0113 get_filename_component(icon_type ${icon_full} EXT) 0114 # do we have ksvg2icns in the path and did we receive an svg (or compressed svg) icon? 0115 if(KSVG2ICNS AND (${icon_type} STREQUAL ".svg" OR ${icon_type} STREQUAL ".svgz")) 0116 # convert the svg icon to an icon resource 0117 execute_process(COMMAND ${KSVG2ICNS} "${icon_full}" 0118 WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} RESULT_VARIABLE KSVG2ICNS_ERROR) 0119 if(${KSVG2ICNS_ERROR}) 0120 message(AUTHOR_WARNING "ksvg2icns could not generate an OS X application icon from ${icon}") 0121 else() 0122 # install the icns file we just created 0123 get_filename_component(icon_name ${icon_full} NAME_WE) 0124 set(MACOSX_BUNDLE_ICON_FILE ${icon_name}.icns PARENT_SCOPE) 0125 if (TARGET ${appsources_or_target}) 0126 target_sources(${appsources_or_target} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/${icon_name}.icns") 0127 else() 0128 set(${appsources_or_target} "${${appsources_or_target}};${CMAKE_CURRENT_BINARY_DIR}/${icon_name}.icns" PARENT_SCOPE) 0129 endif() 0130 set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${icon_name}.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources) 0131 # we're done now 0132 return() 0133 endif() 0134 endif() 0135 endforeach() 0136 endif() 0137 0138 0139 _ecm_add_app_icon_categorize_icons("${ARG_ICONS}" "icons" "16;24;32;48;64;128;256;512;1024") 0140 if(ARG_SIDEBAR_ICONS) 0141 _ecm_add_app_icon_categorize_icons("${ARG_SIDEBAR_ICONS}" "sidebar_icons" "16;32;64;128;256") 0142 endif() 0143 0144 set(mac_icons 0145 # Icons: https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Optimizing/Optimizing.html#//apple_ref/doc/uid/TP40012302-CH7-SW4 0146 ${icons_at_16px} 0147 ${icons_at_32px} 0148 ${icons_at_64px} 0149 ${icons_at_128px} 0150 ${icons_at_256px} 0151 ${icons_at_512px} 0152 ${icons_at_1024px}) 0153 0154 set(mac_sidebar_icons 0155 # Sidebar Icons: https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/Finder.html#//apple_ref/doc/uid/TP40014214-CH15-SW15 0156 ${sidebar_icons_at_16px} 0157 ${sidebar_icons_at_32px} 0158 ${sidebar_icons_at_64px} 0159 ${sidebar_icons_at_128px} 0160 ${sidebar_icons_at_256px}) 0161 0162 if (NOT (mac_icons OR mac_sidebar_icons)) 0163 message(AUTHOR_WARNING "No icons suitable for use on macOS provided") 0164 endif() 0165 0166 0167 set(windows_icons_classic ${icons_at_16px} 0168 ${icons_at_24px} 0169 ${icons_at_32px} 0170 ${icons_at_48px} 0171 ${icons_at_64px} 0172 ${icons_at_128px}) 0173 set(windows_icons_modern ${windows_icons_classic} 0174 ${icons_at_256px} 0175 ${icons_at_512px} 0176 ${icons_at_1024px}) 0177 0178 if (NOT (windows_icons_modern OR windows_icons_classic)) 0179 message(AUTHOR_WARNING "No icons suitable for use on Windows provided") 0180 endif() 0181 0182 if (ARG_OUTFILE_BASENAME) 0183 set (_outfilebasename "${ARG_OUTFILE_BASENAME}") 0184 else() 0185 set (_outfilebasename "${appsources_or_target}") 0186 endif() 0187 set (_outfilename "${CMAKE_CURRENT_BINARY_DIR}/${_outfilebasename}") 0188 0189 if (WIN32 AND (windows_icons_modern OR windows_icons_classic)) 0190 set(saved_CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}") 0191 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_FIND_MODULE_DIR}) 0192 find_package(IcoTool) 0193 set(CMAKE_MODULE_PATH "${saved_CMAKE_MODULE_PATH}") 0194 0195 function(create_windows_icon_and_rc command args deps) 0196 add_custom_command( 0197 OUTPUT "${_outfilename}.ico" 0198 COMMAND ${command} 0199 ARGS ${args} 0200 DEPENDS ${deps} 0201 WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 0202 ) 0203 # this bit's a little hacky to make the dependency stuff work 0204 file(WRITE "${_outfilename}.rc.in" "IDI_ICON1 ICON DISCARDABLE \"${_outfilename}.ico\"\n") 0205 add_custom_command( 0206 OUTPUT "${_outfilename}.rc" 0207 COMMAND ${CMAKE_COMMAND} 0208 ARGS -E copy "${_outfilename}.rc.in" "${_outfilename}.rc" 0209 DEPENDS "${_outfilename}.ico" 0210 WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" 0211 ) 0212 endfunction() 0213 0214 if (IcoTool_FOUND) 0215 list(APPEND icotool_args "-c" "-o" "${_outfilename}.ico") 0216 0217 # According to https://stackoverflow.com/a/40851713/2886832 0218 # Windows always chooses the first icon above 255px, all other ones will be ignored 0219 set(maxSize 0) 0220 foreach(size 256 512 1024) 0221 if(icons_at_${size}px) 0222 set(maxSize "${size}") 0223 endif() 0224 endforeach() 0225 0226 foreach(size 16 24 32 48 64 128 ${maxSize}) 0227 if(NOT icons_at_${size}px) 0228 continue() 0229 endif() 0230 0231 set(icotool_icon_arg "") 0232 if(size STREQUAL "${maxSize}") 0233 # maxSize icon needs to be included as raw png 0234 list(APPEND icotool_args "-r") 0235 endif() 0236 0237 foreach(icon ${icons_at_${size}px}) 0238 list(APPEND icotool_args "${icons_at_${size}px}") 0239 endforeach() 0240 endforeach() 0241 0242 create_windows_icon_and_rc(IcoTool::IcoTool "${icotool_args}" "${windows_icons_modern}") 0243 if (TARGET ${appsources_or_target}) 0244 target_sources(${appsources_or_target} PRIVATE "${_outfilename}.rc") 0245 else() 0246 set(${appsources_or_target} "${${appsources_or_target}};${_outfilename}.rc" PARENT_SCOPE) 0247 endif() 0248 else() 0249 message(WARNING "Unable to find the icotool utilities or icons in matching sizes - application will not have an application icon!") 0250 endif() 0251 elseif (APPLE AND (mac_icons OR mac_sidebar_icons)) 0252 # first generate .iconset directory structure, then convert to .icns format using the Mac OS X "iconutil" utility, 0253 # to create retina compatible icon, you need png source files in pixel resolution 16x16, 32x32, 64x64, 128x128, 0254 # 256x256, 512x512, 1024x1024 0255 find_program(ICONUTIL_EXECUTABLE NAMES iconutil) 0256 if (ICONUTIL_EXECUTABLE) 0257 add_custom_command( 0258 OUTPUT "${_outfilename}.iconset" 0259 COMMAND ${CMAKE_COMMAND} 0260 ARGS -E make_directory "${_outfilename}.iconset" 0261 ) 0262 set(iconset_icons) 0263 macro(copy_icon filename sizename type) 0264 add_custom_command( 0265 OUTPUT "${_outfilename}.iconset/${type}_${sizename}.png" 0266 COMMAND ${CMAKE_COMMAND} 0267 ARGS -E copy 0268 "${filename}" 0269 "${_outfilename}.iconset/${type}_${sizename}.png" 0270 DEPENDS 0271 "${_outfilename}.iconset" 0272 "${filename}" 0273 WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 0274 ) 0275 list(APPEND iconset_icons 0276 "${_outfilename}.iconset/${type}_${sizename}.png") 0277 endmacro() 0278 0279 # List of supported sizes and filenames taken from: 0280 # https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Optimizing/Optimizing.html#//apple_ref/doc/uid/TP40012302-CH7-SW4 0281 foreach(size 16 32 128 256 512) 0282 math(EXPR double_size "2 * ${size}") 0283 foreach(file ${icons_at_${size}px}) 0284 copy_icon("${file}" "${size}x${size}" "icon") 0285 endforeach() 0286 foreach(file ${icons_at_${double_size}px}) 0287 copy_icon("${file}" "${size}x${size}@2x" "icon") 0288 endforeach() 0289 endforeach() 0290 0291 # List of supported sizes and filenames taken from: 0292 # https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/Finder.html#//apple_ref/doc/uid/TP40014214-CH15-SW15 0293 foreach(file ${sidebar_icons_at_16px}) 0294 copy_icon("${file}" "16x16" "sidebar") 0295 endforeach() 0296 foreach(file ${sidebar_icons_at_32px}) 0297 copy_icon("${file}" "16x16@2x" "sidebar") 0298 endforeach() 0299 foreach(file ${sidebar_icons_at_32px}) 0300 copy_icon("${file}" "18x18" "sidebar") 0301 endforeach() 0302 foreach(file ${sidebar_icons_at_64px}) 0303 copy_icon("${file}" "18x18@2x" "sidebar") 0304 endforeach() 0305 foreach(file ${sidebar_icons_at_128px}) 0306 copy_icon("${file}" "32x32" "sidebar") 0307 endforeach() 0308 foreach(file ${sidebar_icons_at_256px}) 0309 copy_icon("${file}" "32x32@2x" "sidebar") 0310 endforeach() 0311 0312 # generate .icns icon file 0313 add_custom_command( 0314 OUTPUT "${_outfilename}.icns" 0315 COMMAND ${ICONUTIL_EXECUTABLE} 0316 ARGS 0317 --convert icns 0318 --output "${_outfilename}.icns" 0319 "${_outfilename}.iconset" 0320 DEPENDS "${iconset_icons}" 0321 WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" 0322 ) 0323 # This will register the icon into the bundle 0324 set(MACOSX_BUNDLE_ICON_FILE "${_outfilebasename}.icns" PARENT_SCOPE) 0325 0326 # Append the icns file to the sources list so it will be a dependency to the 0327 # main target 0328 if (TARGET ${appsources_or_target}) 0329 target_sources(${appsources_or_target} PRIVATE "${_outfilename}.icns") 0330 else() 0331 set(${appsources_or_target} "${${appsources_or_target}};${_outfilename}.icns" PARENT_SCOPE) 0332 endif() 0333 0334 # Install the icon into the Resources dir in the bundle 0335 set_source_files_properties("${_outfilename}.icns" PROPERTIES MACOSX_PACKAGE_LOCATION Resources) 0336 else() 0337 message(STATUS "Unable to find the iconutil utility - application will not have an application icon!") 0338 endif() 0339 endif() 0340 endfunction() 0341 0342 macro(_ecm_add_app_icon_categorize_icons icons type known_sizes) 0343 set(_${type}_known_sizes) 0344 foreach(size ${known_sizes}) 0345 set(${type}_at_${size}px) 0346 list(APPEND _${type}_known_sizes ${size}) 0347 endforeach() 0348 0349 0350 foreach(icon ${icons}) 0351 get_filename_component(icon_full ${icon} ABSOLUTE) 0352 if (NOT EXISTS "${icon_full}") 0353 message(AUTHOR_WARNING "${icon_full} does not exist, ignoring") 0354 else() 0355 get_filename_component(icon_name ${icon} NAME) 0356 string(REGEX MATCH "([0-9]+|sc)\\-[^/]+\\.([a-z]+)$" 0357 _dummy "${icon_name}") 0358 set(size "${CMAKE_MATCH_1}") 0359 set(ext "${CMAKE_MATCH_2}") 0360 0361 if (NOT (ext STREQUAL "svg" OR ext STREQUAL "svgz")) 0362 if (NOT size) 0363 message(AUTHOR_WARNING "${icon_full} is not named correctly for ecm_add_app_icon - ignoring") 0364 elseif (NOT ext STREQUAL "png") 0365 message(AUTHOR_WARNING "${icon_full} is not a png file - ignoring") 0366 else() 0367 list(FIND _${type}_known_sizes ${size} offset) 0368 0369 if (offset GREATER -1) 0370 list(APPEND ${type}_at_${size}px "${icon_full}") 0371 elseif() 0372 message(STATUS "not found ${type}_at_${size}px ${icon_full}") 0373 endif() 0374 endif() 0375 endif() 0376 endif() 0377 endforeach() 0378 endmacro()