e0590a0b56
kf6-kcoreaddons 6.28.0 requires ECM >= 6.28.0 but the vendored ECM source/ was still 6.10.0: the sync engine skipped it because ECM's version marker is a bare set(VERSION "X.Y.Z") that the parser didn't recognize (only KF_VERSION / PROJECT_VERSION / RELEASE_SERVICE_VERSION). Re-lay ECM from its 6.28.0 source.tar (pure cmake modules, no Redox port) and teach both the sync engine and the validator to read set(VERSION) so this class is caught, not silently skipped.
381 lines
17 KiB
CMake
381 lines
17 KiB
CMake
# SPDX-FileCopyrightText: 2014 Alex Merry <alex.merry@kde.org>
|
|
# SPDX-FileCopyrightText: 2014 Ralf Habacker <ralf.habacker@freenet.de>
|
|
# SPDX-FileCopyrightText: 2006-2009 Alexander Neundorf <neundorf@kde.org>
|
|
# SPDX-FileCopyrightText: 2006, 2007 Laurent Montel <montel@kde.org>
|
|
# SPDX-FileCopyrightText: 2007 Matthias Kretz <kretz@kde.org>
|
|
#
|
|
# SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
#[=======================================================================[.rst:
|
|
ECMAddAppIcon
|
|
-------------
|
|
|
|
Add icons to executable files and packages.
|
|
|
|
::
|
|
|
|
ecm_add_app_icon(<sources_var_name(|target (since 5.83))>
|
|
ICONS <icon> [<icon> [...]]
|
|
[SIDEBAR_ICONS <icon> [<icon> [...]] # Since 5.49
|
|
[OUTFILE_BASENAME <name>]) # Since 5.49
|
|
)
|
|
|
|
The given icons, whose names must match the pattern::
|
|
|
|
<size>-<other_text>.png
|
|
|
|
will be added as platform-specific application icons
|
|
to the variable named ``<sources_var_name>`` or, if the first argument
|
|
is a target (since 5.83), to the ``SOURCES`` property of ``<target>``.
|
|
Any target must be created with add_executable() and not be an alias.
|
|
|
|
Other icon files are ignored but on macOS SVG files can be supported and
|
|
it is thus possible to mix those with png files in a single macro call.
|
|
|
|
The platforms currently supported are Windows and macOS, on all others
|
|
the call has no effect and is ignored.
|
|
|
|
``<size>`` is a numeric pixel size (typically 16, 32, 48, 64, 128 or 256).
|
|
``<other_text>`` can be any other text. See the platform notes below for any
|
|
recommendations about icon sizes.
|
|
|
|
``SIDEBAR_ICONS`` can be used to add macOS sidebar
|
|
icons to the generated iconset. They are used when a folder monitored by the
|
|
application is dragged into Finder's sidebar. Since 5.49.
|
|
|
|
``OUTFILE_BASENAME`` will be used as the basename for the icon file. If
|
|
you specify it, the icon file will be called ``<OUTFILE_BASENAME>.icns`` on macOS
|
|
and ``<OUTFILE_BASENAME>.ico`` on Windows. If you don't specify it, it defaults
|
|
to ``<sources_var_name>.<ext>``. Since 5.49.
|
|
|
|
|
|
Windows notes
|
|
* Icons are compiled into the executable using a resource file.
|
|
* Icons may not show up in Windows Explorer if the executable
|
|
target does not have the ``WIN32_EXECUTABLE`` property set.
|
|
* Icotool (see :find-module:`FindIcoTool`) is required.
|
|
* Supported sizes: 16, 24, 32, 48, 64, 128, 256, 512 and 1024.
|
|
|
|
macOS notes
|
|
* The executable target must have the ``MACOSX_BUNDLE`` property set.
|
|
* Icons are added to the bundle.
|
|
* If the ksvg2icns tool from KIconThemes is available, .svg and .svgz
|
|
files are accepted; the first that is converted successfully to .icns
|
|
will provide the application icon. SVG files are ignored otherwise.
|
|
* The tool iconutil (provided by Apple) is required for bitmap icons.
|
|
* Supported sizes: 16, 32, 64, 128, 256 (and 512, 1024 after OS X 10.9).
|
|
* At least a 128x128px (or an SVG) icon is required.
|
|
* Larger sizes are automatically used to substitute for smaller sizes on
|
|
"Retina" (high-resolution) displays. For example, a 32px icon, if
|
|
provided, will be used as a 32px icon on standard-resolution displays,
|
|
and as a 16px-equivalent icon (with an "@2x" tag) on high-resolution
|
|
displays. That is why you should provide 64px and 1024px icons although
|
|
they are not supported anymore directly. Instead they will be used as
|
|
32px@2x and 512px@2x. If an SVG icon is provided, ksvg2icns will be
|
|
used internally to automatically generate all appropriate sizes,
|
|
including the high-resolution ones.
|
|
* This function sets the ``MACOSX_BUNDLE_ICON_FILE`` variable to the name
|
|
of the generated icns file, so that it will be used as the
|
|
``MACOSX_BUNDLE_ICON_FILE`` target property when you call
|
|
``add_executable``.
|
|
* Sidebar icons should typically provided in 16, 32, 64, 128 and 256px.
|
|
|
|
Since 1.7.0.
|
|
#]=======================================================================]
|
|
|
|
cmake_policy(VERSION 3.16)
|
|
|
|
function(ecm_add_app_icon appsources_or_target)
|
|
set(options)
|
|
set(oneValueArgs OUTFILE_BASENAME)
|
|
set(multiValueArgs ICONS SIDEBAR_ICONS)
|
|
cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
|
|
|
if(NOT ARG_ICONS)
|
|
message(FATAL_ERROR "No ICONS argument given to ecm_add_app_icon")
|
|
endif()
|
|
if (TARGET ${appsources_or_target})
|
|
get_target_property(target_type ${appsources_or_target} TYPE)
|
|
if (NOT target_type STREQUAL "EXECUTABLE")
|
|
message(FATAL_ERROR "Target argument passed to ecm_add_app_icon is not an executable: ${appsources_or_target}")
|
|
endif()
|
|
get_target_property(aliased_target ${appsources_or_target} ALIASED_TARGET)
|
|
if(aliased_target)
|
|
message(FATAL_ERROR "Target argument passed to ecm_add_app_icon must not be an alias: ${appsources_or_target}")
|
|
endif()
|
|
endif()
|
|
if(ARG_UNPARSED_ARGUMENTS)
|
|
message(FATAL_ERROR "Unexpected arguments to ecm_add_app_icon: ${ARG_UNPARSED_ARGUMENTS}")
|
|
endif()
|
|
|
|
if(APPLE)
|
|
find_program(KSVG2ICNS NAMES ksvg2icns)
|
|
foreach(icon ${ARG_ICONS})
|
|
get_filename_component(icon_full ${icon} ABSOLUTE)
|
|
get_filename_component(icon_type ${icon_full} EXT)
|
|
# do we have ksvg2icns in the path and did we receive an svg (or compressed svg) icon?
|
|
if(KSVG2ICNS AND (${icon_type} STREQUAL ".svg" OR ${icon_type} STREQUAL ".svgz"))
|
|
# convert the svg icon to an icon resource
|
|
execute_process(COMMAND ${KSVG2ICNS} "${icon_full}"
|
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} RESULT_VARIABLE KSVG2ICNS_ERROR)
|
|
if(${KSVG2ICNS_ERROR})
|
|
message(AUTHOR_WARNING "ksvg2icns could not generate an OS X application icon from ${icon}")
|
|
else()
|
|
# install the icns file we just created
|
|
get_filename_component(icon_name ${icon_full} NAME_WE)
|
|
set(MACOSX_BUNDLE_ICON_FILE ${icon_name}.icns PARENT_SCOPE)
|
|
if (TARGET ${appsources_or_target})
|
|
target_sources(${appsources_or_target} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/${icon_name}.icns")
|
|
else()
|
|
set(${appsources_or_target} "${${appsources_or_target}};${CMAKE_CURRENT_BINARY_DIR}/${icon_name}.icns" PARENT_SCOPE)
|
|
endif()
|
|
set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${icon_name}.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
|
|
# we're done now
|
|
return()
|
|
endif()
|
|
endif()
|
|
endforeach()
|
|
endif()
|
|
|
|
|
|
_ecm_add_app_icon_categorize_icons("${ARG_ICONS}" "icons" "16;24;32;48;64;128;256;512;1024")
|
|
if(ARG_SIDEBAR_ICONS)
|
|
_ecm_add_app_icon_categorize_icons("${ARG_SIDEBAR_ICONS}" "sidebar_icons" "16;32;64;128;256")
|
|
endif()
|
|
|
|
set(mac_icons
|
|
# Icons: https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Optimizing/Optimizing.html#//apple_ref/doc/uid/TP40012302-CH7-SW4
|
|
${icons_at_16px}
|
|
${icons_at_32px}
|
|
${icons_at_64px}
|
|
${icons_at_128px}
|
|
${icons_at_256px}
|
|
${icons_at_512px}
|
|
${icons_at_1024px})
|
|
|
|
set(mac_sidebar_icons
|
|
# Sidebar Icons: https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/Finder.html#//apple_ref/doc/uid/TP40014214-CH15-SW15
|
|
${sidebar_icons_at_16px}
|
|
${sidebar_icons_at_32px}
|
|
${sidebar_icons_at_64px}
|
|
${sidebar_icons_at_128px}
|
|
${sidebar_icons_at_256px})
|
|
|
|
if (NOT (mac_icons OR mac_sidebar_icons))
|
|
message(AUTHOR_WARNING "No icons suitable for use on macOS provided")
|
|
endif()
|
|
|
|
|
|
set(windows_icons_classic ${icons_at_16px}
|
|
${icons_at_24px}
|
|
${icons_at_32px}
|
|
${icons_at_48px}
|
|
${icons_at_64px}
|
|
${icons_at_128px})
|
|
set(windows_icons_modern ${windows_icons_classic}
|
|
${icons_at_256px}
|
|
${icons_at_512px}
|
|
${icons_at_1024px})
|
|
|
|
if (NOT (windows_icons_modern OR windows_icons_classic))
|
|
message(AUTHOR_WARNING "No icons suitable for use on Windows provided")
|
|
endif()
|
|
|
|
if (ARG_OUTFILE_BASENAME)
|
|
set (_outfilebasename "${ARG_OUTFILE_BASENAME}")
|
|
else()
|
|
set (_outfilebasename "${appsources_or_target}")
|
|
endif()
|
|
set (_outfilename "${CMAKE_CURRENT_BINARY_DIR}/${_outfilebasename}")
|
|
|
|
if (WIN32 AND (windows_icons_modern OR windows_icons_classic))
|
|
set(saved_CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}")
|
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_FIND_MODULE_DIR})
|
|
find_package(IcoTool)
|
|
set(CMAKE_MODULE_PATH "${saved_CMAKE_MODULE_PATH}")
|
|
|
|
function(create_windows_icon_and_rc command args deps)
|
|
add_custom_command(
|
|
OUTPUT "${_outfilename}.ico"
|
|
COMMAND ${command}
|
|
ARGS ${args}
|
|
DEPENDS ${deps}
|
|
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
|
)
|
|
# this bit's a little hacky to make the dependency stuff work
|
|
file(WRITE "${_outfilename}.rc.in" "IDI_ICON1 ICON DISCARDABLE \"${_outfilename}.ico\"\n")
|
|
add_custom_command(
|
|
OUTPUT "${_outfilename}.rc"
|
|
COMMAND ${CMAKE_COMMAND}
|
|
ARGS -E copy "${_outfilename}.rc.in" "${_outfilename}.rc"
|
|
DEPENDS "${_outfilename}.ico"
|
|
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
|
|
)
|
|
endfunction()
|
|
|
|
if (IcoTool_FOUND)
|
|
list(APPEND icotool_args "-c" "-o" "${_outfilename}.ico")
|
|
|
|
# According to https://stackoverflow.com/a/40851713/2886832
|
|
# Windows always chooses the first icon above 255px, all other ones will be ignored
|
|
set(maxSize 0)
|
|
foreach(size 256 512 1024)
|
|
if(icons_at_${size}px)
|
|
set(maxSize "${size}")
|
|
endif()
|
|
endforeach()
|
|
|
|
foreach(size 16 24 32 48 64 128 ${maxSize})
|
|
if(NOT icons_at_${size}px)
|
|
continue()
|
|
endif()
|
|
|
|
set(icotool_icon_arg "")
|
|
if(size STREQUAL "${maxSize}")
|
|
# maxSize icon needs to be included as raw png
|
|
list(APPEND icotool_args "-r")
|
|
endif()
|
|
|
|
foreach(icon ${icons_at_${size}px})
|
|
list(APPEND icotool_args "${icons_at_${size}px}")
|
|
endforeach()
|
|
endforeach()
|
|
|
|
create_windows_icon_and_rc(IcoTool::IcoTool "${icotool_args}" "${windows_icons_modern}")
|
|
if (TARGET ${appsources_or_target})
|
|
target_sources(${appsources_or_target} PRIVATE "${_outfilename}.rc")
|
|
else()
|
|
set(${appsources_or_target} "${${appsources_or_target}};${_outfilename}.rc" PARENT_SCOPE)
|
|
endif()
|
|
else()
|
|
message(WARNING "Unable to find the icotool utilities or icons in matching sizes - application will not have an application icon!")
|
|
endif()
|
|
elseif (APPLE AND (mac_icons OR mac_sidebar_icons))
|
|
# first generate .iconset directory structure, then convert to .icns format using the macOS "iconutil" utility,
|
|
# to create retina compatible icon, you need png source files in pixel resolution 16x16, 32x32, 64x64, 128x128,
|
|
# 256x256, 512x512, 1024x1024
|
|
find_program(ICONUTIL_EXECUTABLE NAMES iconutil)
|
|
if (ICONUTIL_EXECUTABLE)
|
|
add_custom_command(
|
|
OUTPUT "${_outfilename}.iconset"
|
|
COMMAND ${CMAKE_COMMAND}
|
|
ARGS -E make_directory "${_outfilename}.iconset"
|
|
)
|
|
set(iconset_icons)
|
|
macro(copy_icon filename sizename type)
|
|
add_custom_command(
|
|
OUTPUT "${_outfilename}.iconset/${type}_${sizename}.png"
|
|
COMMAND ${CMAKE_COMMAND}
|
|
ARGS -E copy
|
|
"${filename}"
|
|
"${_outfilename}.iconset/${type}_${sizename}.png"
|
|
DEPENDS
|
|
"${_outfilename}.iconset"
|
|
"${filename}"
|
|
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
|
)
|
|
list(APPEND iconset_icons
|
|
"${_outfilename}.iconset/${type}_${sizename}.png")
|
|
endmacro()
|
|
|
|
# List of supported sizes and filenames taken from:
|
|
# https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Optimizing/Optimizing.html#//apple_ref/doc/uid/TP40012302-CH7-SW4
|
|
foreach(size 16 32 128 256 512)
|
|
math(EXPR double_size "2 * ${size}")
|
|
foreach(file ${icons_at_${size}px})
|
|
copy_icon("${file}" "${size}x${size}" "icon")
|
|
endforeach()
|
|
foreach(file ${icons_at_${double_size}px})
|
|
copy_icon("${file}" "${size}x${size}@2x" "icon")
|
|
endforeach()
|
|
endforeach()
|
|
|
|
# List of supported sizes and filenames taken from:
|
|
# https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/Finder.html#//apple_ref/doc/uid/TP40014214-CH15-SW15
|
|
foreach(file ${sidebar_icons_at_16px})
|
|
copy_icon("${file}" "16x16" "sidebar")
|
|
endforeach()
|
|
foreach(file ${sidebar_icons_at_32px})
|
|
copy_icon("${file}" "16x16@2x" "sidebar")
|
|
endforeach()
|
|
foreach(file ${sidebar_icons_at_32px})
|
|
copy_icon("${file}" "18x18" "sidebar")
|
|
endforeach()
|
|
foreach(file ${sidebar_icons_at_64px})
|
|
copy_icon("${file}" "18x18@2x" "sidebar")
|
|
endforeach()
|
|
foreach(file ${sidebar_icons_at_128px})
|
|
copy_icon("${file}" "32x32" "sidebar")
|
|
endforeach()
|
|
foreach(file ${sidebar_icons_at_256px})
|
|
copy_icon("${file}" "32x32@2x" "sidebar")
|
|
endforeach()
|
|
|
|
# generate .icns icon file
|
|
add_custom_command(
|
|
OUTPUT "${_outfilename}.icns"
|
|
COMMAND ${ICONUTIL_EXECUTABLE}
|
|
ARGS
|
|
--convert icns
|
|
--output "${_outfilename}.icns"
|
|
"${_outfilename}.iconset"
|
|
DEPENDS "${iconset_icons}"
|
|
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
|
|
)
|
|
# This will register the icon into the bundle
|
|
set(MACOSX_BUNDLE_ICON_FILE "${_outfilebasename}.icns" PARENT_SCOPE)
|
|
|
|
# Append the icns file to the sources list so it will be a dependency to the
|
|
# main target
|
|
if (TARGET ${appsources_or_target})
|
|
target_sources(${appsources_or_target} PRIVATE "${_outfilename}.icns")
|
|
else()
|
|
set(${appsources_or_target} "${${appsources_or_target}};${_outfilename}.icns" PARENT_SCOPE)
|
|
endif()
|
|
|
|
# Install the icon into the Resources dir in the bundle
|
|
set_source_files_properties("${_outfilename}.icns" PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
|
|
else()
|
|
message(STATUS "Unable to find the iconutil utility - application will not have an application icon!")
|
|
endif()
|
|
endif()
|
|
endfunction()
|
|
|
|
macro(_ecm_add_app_icon_categorize_icons icons type known_sizes)
|
|
set(_${type}_known_sizes)
|
|
foreach(size ${known_sizes})
|
|
set(${type}_at_${size}px)
|
|
list(APPEND _${type}_known_sizes ${size})
|
|
endforeach()
|
|
|
|
|
|
foreach(icon ${icons})
|
|
get_filename_component(icon_full ${icon} ABSOLUTE)
|
|
if (NOT EXISTS "${icon_full}")
|
|
message(AUTHOR_WARNING "${icon_full} does not exist, ignoring")
|
|
else()
|
|
get_filename_component(icon_name ${icon} NAME)
|
|
string(REGEX MATCH "([0-9]+|sc)\\-[^/]+\\.([a-z]+)$"
|
|
_dummy "${icon_name}")
|
|
set(size "${CMAKE_MATCH_1}")
|
|
set(ext "${CMAKE_MATCH_2}")
|
|
|
|
if (NOT (ext STREQUAL "svg" OR ext STREQUAL "svgz"))
|
|
if (NOT size)
|
|
message(AUTHOR_WARNING "${icon_full} is not named correctly for ecm_add_app_icon - ignoring")
|
|
elseif (NOT ext STREQUAL "png")
|
|
message(AUTHOR_WARNING "${icon_full} is not a png file - ignoring")
|
|
else()
|
|
list(FIND _${type}_known_sizes ${size} offset)
|
|
|
|
if (offset GREATER -1)
|
|
list(APPEND ${type}_at_${size}px "${icon_full}")
|
|
else()
|
|
message(STATUS "not found ${type}_at_${size}px ${icon_full}")
|
|
endif()
|
|
endif()
|
|
endif()
|
|
endif()
|
|
endforeach()
|
|
endmacro()
|