diff options
Diffstat (limited to 'modules')
| -rw-r--r-- | modules/ECMAddAppIcon.cmake | 227 | 
1 files changed, 227 insertions, 0 deletions
| diff --git a/modules/ECMAddAppIcon.cmake b/modules/ECMAddAppIcon.cmake new file mode 100644 index 00000000..4efdd392 --- /dev/null +++ b/modules/ECMAddAppIcon.cmake @@ -0,0 +1,227 @@ +#.rst: +# ECMAddAppIcon +# ------------- +# +# Add icons to executable files and packages. +# +# :: +# +#  ecm_add_app_icon(<sources_var> +#                   ICONS <icon> [<icon> [...]]) +# +# The given icons, whose names must match the pattern:: +# +#   <size>-<other_text>.png +# +# will be added to the executable target whose sources are specified by +# ``<sources_var>`` on platforms that support it (Windows and Mac OS X). +# +# ``<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. +# +# 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. +#    * The tool png2ico is required. See :find-module:`FindPng2Ico`. +#    * Supported sizes: 16, 32, 48, 64, 128. +# +# Mac OS X notes +#    * The executable target must have the ``MACOSX_BUNDLE`` property set. +#    * Icons are added to the bundle. +#    * The tool iconutil (provided by Apple) is required. +#    * Supported sizes: 16, 32, 64, 128, 256, 512, 1024. +#    * At least a 128x128px 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. +#    * 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``. + +#============================================================================= +# Copyright 2014 Alex Merry <alex.merry@kde.org> +# Copyright 2014 Ralf Habacker <ralf.habacker@freenet.de> +# Copyright 2006-2009 Alexander Neundorf, <neundorf@kde.org> +# Copyright 2006, 2007, Laurent Montel, <montel@kde.org> +# Copyright 2007 Matthias Kretz <kretz@kde.org> +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file COPYING-CMAKE-SCRIPTS for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of extra-cmake-modules, substitute the full +#  License text for the above reference.) + +include(CMakeParseArguments) + +function(ecm_add_app_icon appsources) +    set(options) +    set(oneValueArgs) +    set(multiValueArgs 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(ARG_UNPARSED_ARGUMENTS) +        message(FATAL_ERROR "Unexpected arguments to ecm_add_app_icon: ${ARG_UNPARSED_ARGUMENTS}") +    endif() + +    set(known_sizes 16 32 48 64 128 256 512 1024) +    foreach(size ${known_sizes}) +        set(icons_at_${size}px) +    endforeach() + +    foreach(icon ${ARG_ICONS}) +        if (NOT EXISTS "${icon}") +            message(AUTHOR_WARNING "${icon} does not exist, ignoring") +        else() +            string(REGEX MATCH "([0-9]+)\\-[^/]+\\.([a-z]+)$" +                               _dummy "${icon}") +            set(size  "${CMAKE_MATCH_1}") +            set(ext   "${CMAKE_MATCH_2}") +            if (NOT size) +                message(AUTHOR_WARNING "${icon} is not named correctly for ecm_add_app_icon - ignoring") +            elseif (NOT ext STREQUAL "png") +                message(AUTHOR_WARNING "${icon} is not a png file - ignoring") +            else() +                list(FIND known_sizes "${size}" offset) +                if (offset GREATER -1) +                    list(APPEND icons_at_${size}px "${icon}") +                endif() +            endif() +        endif() +    endforeach() + +    set(mac_icons ${icons_at_16px} +                  ${icons_at_32px} +                  ${icons_at_64px} +                  ${icons_at_128px} +                  ${icons_at_256px} +                  ${icons_at_512px} +                  ${icons_at_1024px}) +    if (NOT icons_at_128px) +        message(AUTHOR_WARNING "No 128px icon provided; this will not work on Mac OS X") +    endif() + +    set(windows_icons ${icons_at_16px} +                      ${icons_at_32px} +                      ${icons_at_48px} +                      ${icons_at_64px} +                      ${icons_at_128px}) +    if (NOT windows_icons) +        message(AUTHOR_WARNING "No icons suitable for use on Windows provided") +    endif() + +    set (_outfilename "${CMAKE_CURRENT_BINARY_DIR}/${appsources}") + +    if (WIN32 AND windows_icons) +        set(saved_CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}") +        set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_FIND_MODULE_DIR}) +        find_package(Png2Ico) +        set(CMAKE_MODULE_PATH "${saved_CMAKE_MODULE_PATH}") + +        if (Png2Ico_FOUND) +            if (Png2Ico_HAS_RCFILE_ARGUMENT) +                add_custom_command( +                    OUTPUT "${_outfilename}.rc" "${_outfilename}.ico" +                    COMMAND Png2Ico::Png2Ico +                    ARGS +                        --rcfile "${_outfilename}.rc" +                        "${_outfilename}.ico" +                        ${windows_icons} +                    DEPENDS ${windows_icons} +                    WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" +                ) +            else() +                add_custom_command( +                    OUTPUT "${_outfilename}.ico" +                    COMMAND Png2Ico::Png2Ico +                    ARGS "${_outfilename}.ico" ${windows_icons} +                    DEPENDS ${windows_icons} +                    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}" +                ) +            endif() +            set(${appsources} "${${appsources}};${_outfilename}.rc" PARENT_SCOPE) +        else() +            message(WARNING "Unable to find the png2ico utility - application will not have an application icon!") +        endif() +    elseif (APPLE AND mac_icons) +        # first generate .iconset directory structure, then convert to .icns format using the Mac OS X "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) +                add_custom_command( +                    OUTPUT "${_outfilename}.iconset/icon_${sizename}.png" +                    COMMAND ${CMAKE_COMMAND} +                    ARGS -E copy +                         "${filename}" +                         "${_outfilename}.iconset/icon_${sizename}.png" +                    DEPENDS +                        "${_outfilename}.iconset" +                        "${filename}" +                    WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" +                ) +                list(APPEND iconset_icons +                            "${_outfilename}.iconset/icon_${sizename}.png") +            endmacro() +            foreach(size 16 32 64 128 256 512) +                math(EXPR double_size "2 * ${size}") +                foreach(file ${icons_at_${size}px}) +                    copy_icon("${file}" "${size}x${size}") +                endforeach() +                foreach(file ${icons_at_${double_size}px}) +                    copy_icon("${file}" "${size}x${size}@2x") +                endforeach() +            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 ${appsources}.icns PARENT_SCOPE) + +            # Append the icns file to the sources list so it will be a dependency to the +            # main target +            set(${appsources} "${${appsources}};${_outfilename}.icns" PARENT_SCOPE) + +            # Install the icon into the Resources dir in the bundle +            set_source_files_properties(${_outfilename}.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources) +        else(ICONUTIL_EXECUTABLE) +            message(STATUS "Unable to find the iconutil utility - application will not have an application icon!") +        endif(ICONUTIL_EXECUTABLE) +    endif() +endfunction() | 
