aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Merry <alex.merry@kde.org>2015-01-18 22:25:26 +0000
committerAlex Merry <alex.merry@kde.org>2015-01-24 11:01:09 +0000
commitcf5ccc7d9eba368846fae043855d9b064dac786d (patch)
tree0d958c3148592f0510153499a5d8fcc2e6b943c4
parent1dd2029e5585385ea42d3092b010a8879ff00201 (diff)
downloadextra-cmake-modules-cf5ccc7d9eba368846fae043855d9b064dac786d.tar.gz
extra-cmake-modules-cf5ccc7d9eba368846fae043855d9b064dac786d.tar.bz2
Add ecm_add_app_icon function.
This adds an application icon to an executable from PNG files for Windows and Mac OS X. Unlike the similar kde4_add_app_icon macro from kdelibs, this requires icons to be explicitly listed as arguments (meaning CMake can tell when ones are added or deleted and reconfigure as appropriate), and it works with Matthias Benkmann's png2ico tool, as well as the KDE-Win tool of the same name. Currently missing unit tests. Also completely untested (except that `make test` runs on Linux, so there are no obvious syntax errors). With thanks to Ralf Habacker for the inital work on porting kde4_add_app_icon. CHANGELOG: Add ECMAddAppIcon module to add icons to executable targets on Windows and Mac OS X.
-rw-r--r--docs/find-module/FindPng2Ico.rst1
-rw-r--r--docs/module/ECMAddAppIcon.rst1
-rw-r--r--find-modules/FindPng2Ico.cmake115
-rw-r--r--modules/ECMAddAppIcon.cmake227
4 files changed, 344 insertions, 0 deletions
diff --git a/docs/find-module/FindPng2Ico.rst b/docs/find-module/FindPng2Ico.rst
new file mode 100644
index 00000000..db8aa775
--- /dev/null
+++ b/docs/find-module/FindPng2Ico.rst
@@ -0,0 +1 @@
+.. ecm-module:: ../../find-modules/FindPng2Ico.cmake
diff --git a/docs/module/ECMAddAppIcon.rst b/docs/module/ECMAddAppIcon.rst
new file mode 100644
index 00000000..31c09a88
--- /dev/null
+++ b/docs/module/ECMAddAppIcon.rst
@@ -0,0 +1 @@
+.. ecm-module:: ../../modules/ECMAddAppIcon.cmake
diff --git a/find-modules/FindPng2Ico.cmake b/find-modules/FindPng2Ico.cmake
new file mode 100644
index 00000000..71e2487c
--- /dev/null
+++ b/find-modules/FindPng2Ico.cmake
@@ -0,0 +1,115 @@
+#.rst:
+# FindPng2Ico
+# -----------
+#
+# Try to find png2ico.
+#
+# If the png2ico executable is not in your PATH, you can provide
+# an alternative name or full path location with the ``Png2Ico_EXECUTABLE``
+# variable.
+#
+# This will define the following variables:
+#
+# ``Png2Ico_FOUND``
+# True if png2ico is available.
+#
+# ``Png2Ico_EXECUTABLE``
+# The png2ico executable.
+#
+# If ``Png2Ico_FOUND`` is TRUE, it will also define the following imported
+# target:
+#
+# ``Png2Ico::Png2Ico``
+# The png2ico executable.
+#
+# and the following variables:
+#
+# ``Png2Ico_HAS_COLORS_ARGUMENT``
+# Whether png2ico accepts a ``--colors`` argument. `Matthias Benkmann's
+# tool <http://www.winterdrache.de/freeware/png2ico/>`_ does, while the
+# version of png2ico from the `"KDE On Windows" (kdewin)
+# <https://projects.kde.org/projects/kdesupport/kdewin>`_ project does not.
+#
+# ``Png2Ico_HAS_RCFILE_ARGUMENT``
+# Whether png2ico accepts an ``--rcfile`` argument. The version of png2ico
+# from the `"KDE On Windows" (kdewin)
+# <https://projects.kde.org/projects/kdesupport/kdewin>`_ project does,
+# while `Matthias Benkmann's tool
+# <http://www.winterdrache.de/freeware/png2ico/>`_ does not.
+#
+
+#=============================================================================
+# Copyright 2014 Alex Merry <alex.merry@kde.org>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#=============================================================================
+
+include(${CMAKE_CURRENT_LIST_DIR}/ECMFindModuleHelpersStub.cmake)
+
+ecm_find_package_version_check(Png2Ico)
+
+# Find png2ico
+find_program(Png2Ico_EXECUTABLE NAMES png2ico)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(Png2Ico
+ FOUND_VAR
+ Png2Ico_FOUND
+ REQUIRED_VARS
+ Png2Ico_EXECUTABLE
+)
+
+mark_as_advanced(Png2Ico_EXECUTABLE)
+
+if (Png2Ico_FOUND)
+ execute_process(
+ COMMAND "${Png2Ico_EXECUTABLE}" --help
+ OUTPUT_VARIABLE _png2ico_help_text
+ )
+ if (_png2ico_help_text MATCHES ".*--rcfile .*")
+ set(Png2Ico_HAS_RCFILE_ARGUMENT TRUE)
+ else()
+ set(Png2Ico_HAS_RCFILE_ARGUMENT FALSE)
+ endif()
+ if (_png2ico_help_text MATCHES ".*--colors .*")
+ set(Png2Ico_HAS_COLORS_ARGUMENT TRUE)
+ else()
+ set(Png2Ico_HAS_COLORS_ARGUMENT FALSE)
+ endif()
+ unset(_png2ico_help_text)
+
+ if (NOT TARGET Png2Ico::Png2Ico)
+ add_executable(Png2Ico::Png2Ico IMPORTED)
+ set_target_properties(Png2Ico::Png2Ico PROPERTIES
+ IMPORTED_LOCATION "${Png2Ico_EXECUTABLE}"
+ )
+ endif()
+endif()
+
+include(FeatureSummary)
+set_package_properties(Png2Ico PROPERTIES
+ URL "http://www.winterdrache.de/freeware/png2ico/ or https://projects.kde.org/projects/kdesupport/kdewin"
+ DESCRIPTION "Executable that converts a collection of PNG files into a Windows icon file"
+)
+
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()