Как вручную создавать файлы icns с помощью iconutil?

Когда я проверяю свое приложение, я получаю эту ошибку:

набор приложений не содержит значка в формате ICNS, содержащего как изображения 512x512, так и [email protected].

Я использую значки icns с Img2icns, и до сегодняшнего дня он всегда работал правильно. Но теперь я получаю эту ошибку, и нет способа заставить ее работать. Я попытался объединить два файла PNG (512x512 и 1024x1024) в Img2icns, но я всегда получаю эту ошибку. Я также попытался следовать инструкциям в Руководстве по человеческому интерфейсу Apple OS X, но когда я пытаюсь сделать наборы значков, я получаю эту ошибку терминала:

- bash: синтаксическая ошибка возле неожиданного токена 'newline'

Я не очень хорош с терминальными командами, поэтому, возможно, я делаю что-то неправильно. Я написал:

iconutil -c icns </Users/myname/SDK Mac Apps/MyApp/grafica/icon.iconset>

Если кто-то может помочь, это будет очень признательно. Спасибо, Масси.

Ответ 1

Оформить следующие инструкции (ссылка):

Использовать iconutil для создания файла icns вручную

Инструмент командной строки iconutil преобразует папки iconset в файлы icns с высокой разрешающей способностью. (Вы можете найти полную документацию для этого инструмента, введя man iconutil в Terminal.) Использование этого инструмента также сжимает результирующий файл icns, поэтому вам не нужно выполнять дополнительное сжатие.

Чтобы преобразовать набор значков в файл icns

Введите эту команду в окно терминала:

iconutil -c icns <iconset filename>

где <iconset filename> - путь к папке, содержащей набор значков, которые вы хотите преобразовать в icns. Вывод записывается в том же месте, что и iconset file, если вы не укажете выходной файл, как показано:

iconutil -c icns -o <icon filename> <iconset filename>

Другими словами, вам нужно заменить <iconset filename> на путь:

/Users/myname/SDK Mac Apps/MyApp/grafica/icon.iconset

Так как путь содержит пробелы, вам нужно использовать двойные кавычки, например:

iconutil -c icns "/Users/myname/SDK Mac Apps/MyApp/grafica/icon.iconset"

Эта команда должна работать правильно.

Ответ 2

Здесь script для преобразования 1024x1024 png (с именем "Icon1024.png" ) в требуемый файл icns. Сохраните его в файле с именем "CreateICNS.src" в папке, где ваш png файл затем находится в терминале "cd" в той же папке и введите "source CreateNNS.src", чтобы вызвать его:

mkdir MyIcon.iconset
sips -z 16 16     Icon1024.png --out MyIcon.iconset/icon_16x16.png
sips -z 32 32     Icon1024.png --out MyIcon.iconset/[email protected]
sips -z 32 32     Icon1024.png --out MyIcon.iconset/icon_32x32.png
sips -z 64 64     Icon1024.png --out MyIcon.iconset/[email protected]
sips -z 128 128   Icon1024.png --out MyIcon.iconset/icon_128x128.png
sips -z 256 256   Icon1024.png --out MyIcon.iconset/[email protected]
sips -z 256 256   Icon1024.png --out MyIcon.iconset/icon_256x256.png
sips -z 512 512   Icon1024.png --out MyIcon.iconset/[email protected]
sips -z 512 512   Icon1024.png --out MyIcon.iconset/icon_512x512.png
cp Icon1024.png MyIcon.iconset/[email protected]
iconutil -c icns MyIcon.iconset
rm -R MyIcon.iconset

Ответ 3

Там есть модуль командной строки node, который выполняет всю работу по преобразованию PNG файла в каталог iconset:

npm install -g node-icns
nicns --in adventure-cat.png --out adventure-cat.icns

Ответ 4

Эти команды (введенные в Terminal) работали для меня, чтобы преобразовать старый файл icns в новый формат:

cd Folder_With_Icns_File
iconutil -c iconset Your_Icon_Name.icns 
rm Your_Icon_Name.icns 
iconutil -c icns Your_Icon_Name.iconset
rm -R Your_Icon_Name.iconset

Update

Параметр -c для iconutil больше не поддерживается. Вместо этого используйте --convert:

cd Folder_With_Icns_File
iconutil --convert iconset Your_Icon_Name.icns 
rm Your_Icon_Name.icns 
iconutil --convert icns Your_Icon_Name.iconset
rm -R Your_Icon_Name.iconset

Ответ 5

Хотя использование всевозможных сценариев для преобразования изображения в PNG высокого разрешения в набор различных копий с низким разрешением может показаться удобным (и это действительно так), не следует забывать, что этот вид автоматического изменения размера приведет к ощутимо несовершенным изображениям.

Чем меньше разрешение, тем ярче значок!

Вместо этого вы всегда должны запрашивать логотип в каком-то векторном формате у вашего дизайнера, например, в SVG. Имея это под рукой, вы можете вручную подготовить идеальные файлы PNG во всех необходимых разрешениях, а затем создать один файл .icns, который сделает ваш значок приложения красивым на каждом экране, от мобильного телефона до какого-нибудь высококачественного дисплея Retina. последний iMac.

Согласно последним рекомендациям Apple от 2016 года, вы должны подготовить следующие файлы PNG:

+---------------------+--------------------+--------------+
|      filename       | resolution, pixels | density, PPI |
+---------------------+--------------------+--------------+
| icon_16x16.png      | 16x16              |           72 |
| [email protected]   | 32x32              |          144 |
| icon_32x32.png      | 32x32              |           72 |
| [email protected]   | 64x64              |          144 |
| icon_128x128.png    | 128x128            |           72 |
| [email protected] | 256x256            |          144 |
| icon_256x256.png    | 256x256            |           72 |
| [email protected] | 512x512            |          144 |
| icon_512x512.png    | 512x512            |           72 |
| [email protected] | 1024x1024          |          144 |
+---------------------+--------------------+--------------+

После того, как все файлы PNG подготовлены, поместить их в какой - нибудь каталог с .iconset расширением (Logos.iconset, например) и выполнить следующие из терминала:

iconutil --convert icns Logos.iconset

Если после выполнения этой команды не было ошибок, то все файлы были обработаны правильно, и вы получили файл Logos.icns в том же каталоге, содержащий все красивые четкие логотипы для вашего приложения, которые подойдут для любого современного экрана по состоянию на 2017 год.

Ответ 6

Дополнительный комментарий, когда вы создаете файл .icns, вам нужно переименовать все файлы pic с префиксом "icon_", в противном случае iconutil завершится с сообщением об ошибке: ".iconset: error: Не удалось создать ICNS". который не является информативным вообще.

Ответ 7

Я рефакторировал @Henry script, чтобы он выглядел лучше:

#!/bin/zsh
NAME=$(basename $1 .png); DIR="$NAME.iconset"
mkdir -pv $DIR
for m r in 'n' '' '((n+1))' '@2x'; do
    for n in $(seq 4 9 | grep -v 6); do
        p=$((2**$m)); q=$((2**$n))
        OUT="$DIR/icon_${q}x${q}${r}.png"
        sips -z $p $p $1 --out $OUT
    done
done
iconutil -c icns $DIR
rm -frv $DIR

Обновление

Параметр -c для iconutil больше не поддерживается. Вместо этого используйте -—convert:

#!/bin/zsh
NAME=$(basename $1 .png); DIR="$NAME.iconset"
mkdir -pv $DIR
for m r in 'n' '' '((n+1))' '@2x'; do
    for n in $(seq 4 9 | grep -v 6); do
        p=$((2**$m)); q=$((2**$n))
        OUT="$DIR/icon_${q}x${q}${r}.png"
        sips -z $p $p $1 --out $OUT
    done
done
iconutil -—convert icns $DIR
rm -frv $DIR

Ответ 8

Я написал bash-скрипт для создания icns из SVG файла:

#!/usr/bin/env bash 
sizes=(16 32 64 128 256 512)
largfile='[email protected]'
if [ ! -f "$largfile" ]; then
  convert -background none -resize 1024x1024 "$1" "$largfile"
fi
for s in "${sizes[@]}"; do
  echo $s
  convert -background none -resize ${s}x${s} "$largfile" "icon_${s}x$s.png"
done

cp 'icon_32x32.png'     '[email protected]'
mv 'icon_64x64.png'     '[email protected]'
cp 'icon_256x256.png'   '[email protected]'
cp 'icon_512x512.png'   '[email protected]'

mkdir icon.iconset
mv icon_*x*.png icon.iconset
iconutil -c icns icon.iconset

Убедитесь, что на Mac установлена программа imagemagick с поддержкой librsvg:

brew install imagemagick --with-librsvg

Этот сценарий послужил мне довольно хорошо.


Обновить

Для более тщательной обработки я создал инструмент командной строки (написанный на Swift) для генерации AppIcon.appiconset с правильной компоновкой и форматом:

https://github.com/kindlychung/genicon

Ответ 9

Dead simple.png 👉.icns

  1. Скачайте IconMaker.app - просто .applescript не будет кусаться
  2. Перетащите ваш .png в IconMaker.app, который вы только что создали.

Больше информации: http://eon.codes/blog/2016/12/06/Creating-an-app-icon/

High sierra update iconutil теперь более строго относится к размеру исходного .png. Подробнее об этом в блоге после прыжка. ✌️

Ответ 10

Когда я проверяю свое приложение, я получаю эту ошибку:

набор приложений не содержит значок в формате ICNS, содержащий как изображение 512x512, так и 512x512 @2x.

Я не очень хорошо разбираюсь в команде терминала, и поэтому, возможно, я делаю что-то неправильно. Я написал:

iconutil -c icns </Users/myname/SDK Mac Apps/MyApp/grafica/icon.iconset>

Во-первых, как я уже говорил в комментарии к Анне, вам, вероятно, не нужно использовать iconutil. Вы должны просто добавить набор иконок в свой проект и позволить Xcode преобразовать его для вас как часть сборки.

В любом случае это может быть вашей проблемой:

Я попытался поместить два файла PNG togheter (512x512 и 1024x1024)... но я всегда получаю ошибку.

Нет размера 1024 на 1024 точки. Элемент 1024 на 1024 пикселя (который был 1024 балла перед Mountain Lion) теперь используется для 512 на 512 точек @2x.

Ваш PNG файл должен быть назван соответствующим образом: [email protected]

Ответ 11

Apple старше Icon Composer версии 2.2 работает просто отлично, вы просто открываете .ICNS в нем, нажимаете кнопку 1024x1024 и добавляете свое изображение.

Ответ 12

То же, что @Henry (комментарий выше), но принимает в качестве аргумента имя файла PNG и выводит ICNS с тем же именем.

ПРИМЕЧАНИЕ. Предполагается, что имя файла PNG будет иметь только 1 точку для отдельного расширения, т.е. xpto.png.

Итак, сохраните приведенный ниже код в поле с именем "CreateICNS.src" в папке, где находится ваш файл png.

КОД:

IFS='.' read -ra ADDR <<< "$1"
ICONSET=${ADDR[0]}.iconset
mkdir $ICONSET
sips -z 16 16     $1 --out $ICONSET/icon_16x16.png
sips -z 32 32     $1 --out $ICONSET/[email protected]
sips -z 32 32     $1 --out $ICONSET/icon_32x32.png
sips -z 64 64     $1 --out $ICONSET/[email protected]
sips -z 128 128   $1 --out $ICONSET/icon_128x128.png
sips -z 256 256   $1 --out $ICONSET/[email protected]
sips -z 256 256   $1 --out $ICONSET/icon_256x256.png
sips -z 512 512   $1 --out $ICONSET/[email protected]
sips -z 512 512   $1 --out $ICONSET/icon_512x512.png
cp $1 $ICONSET/[email protected]
iconutil -c icns $ICONSET
rm -R $ICONSET

КАК ПОЛЬЗОВАТЬСЯ :

Затем в терминале "cd" в ту же папку и введите:

source CreateICNS.src {PNG filename}

где {PNG filename} - это имя вашего PNG файла, то есть xpto.png.

Если ваш файл будет называться abc.png, вы будете использовать:

source CreateICNS.src abc.png

Ответ 13

@dardo82 код оболочки хорош и работает. Вот более простой в sh (для всех * nix) и быстрее (как это действительно имеет значение):

#!/bin/sh
#   This runs silent, be as verbose as you wish
NAME=$(basename ${1} .png)
DIR="${NAME}.iconset"
mkdir -p ${DIR}
for i in 16 32 128 256 512 ; do
    x=""
    for p in $i $(($i+$i)) ; do
        sips -z $p $p ${1} --out "${NAME}.iconset/icon_${i}x${i}${x}.png"
        x="@2x"
    done
done >/dev/null  # /dev/null in lieu of a "-s" silent option
iconutil -—convert icns $DIR
rm -r $DIR

Ответ 14

Выполнить iconutil -c icns Icon.iconset

Примечание

  • Icon.iconset - это папка
  • Начало имени с нижним регистром icon_
  • Когда вы видите Icon.icns с правильным изображением, вы знаете, что оно работает

введите описание изображения здесь

Ответ 15

Есть 2 задачи:
- создать 10 правильных файлов icns
- получите ваш проект XCode, чтобы использовать их правильно

Поскольку у меня были часовые проблемы с обеими этими задачами, а также мне не нравится, когда я не "вижу", что происходит, вот путь для осторожных:

Создайте 10 правильных файлов icns:
Я использовал приведенный выше сценарий от Генри: он все еще работает для HighSierra и Xcode 9.2, включая команду "c".
Файл icns, который я получил, в Finder/Quicklook отображался только как один значок размера, а в режиме предварительного просмотра - только 8 из 10 размеров.
Поэтому я использовал терминал, пошел с cd в свою папку и использовал команду: iconutil -c iconset (имя файла icns) в только что созданном файле icns, чтобы вернуть файл icns обратно в папку iconset, и - вот, я мог посмотрите мои недавно созданные 10 файлов значков. Используя Быстрый просмотр папки с иконками (и используя полноэкранный режим, чтобы иметь возможность масштабировать их с помощью ползунка), я мог проверить, что все размеры на самом деле выглядят очень хорошо.

В качестве отступления: они выглядели лучше, чем мои попытки изменить размер в PSE, скорее всего потому, что я не нашел времени, чтобы поиграть со всеми вариантами изменения размера в PSE. Если вы используете PSE, убедитесь, что ваши файлы png сохранены без цветового профиля. Кроме того, по признанию моего невежества, для меня файл 256x256 @2 такой же, как файл 512x512 - оба в 72dpi. Попытка следовать комментариям с разрешением 144 т/д у меня не сработала.

Получите ваш проект XCode, чтобы использовать их правильно:
Сначала я удалил все свои бесплодные попытки в XCode и отправил чистую версию в репозиторий git (что было бы разумно, было бы сначала зафиксировать чистую версию - прежде чем я неистово начал одиссею добавления значков).
Я также убедился, что в файле info.plist нет указателя, связанного с записью "файл значков", и что в общих настройках проекта я выбрал AppIcon для значков приложений.
Затем я добавил каталог assets.asset и в каталог ресурсов новую папку AppIcon AppIcons and Launch Images для ОС.
Затем я скопировал (перетаскивал с нажатой опцией) из папки наборов иконок каждый файл изображения png в соответствующий AppIcon Spaceholder. Итак, еще раз, я мог видеть, что происходит. Xcode действительно преобразовал это в файлы icns, или, может быть, - поскольку моя папка с набором иконок, полученная из папки icns, - форматы файлов были приняты.

Затем заархивируйте и подтвердите, и при загрузке или проверке ошибок не будет.

Ответ 16

Здравствуйте, для моих нужд я сделал капельку, которая работает с перетаскиванием значков в одиночку или значками для поиска в папке (я ограничился папками, поскольку поиск по томам всех значков может занять много времени). Поэтому при перетаскивании вы можете отбрасывать папки или приложения, все, что может содержать значок. Созданный набор значков несет имя исходного значка, он помещается в каталог "/aaaicones" и путь к значку. Пример в папке "/aaaicones, если вы отправляете xcode.app, вы найдете" /aaaicones/Applications/xcode.app/access.iconset "и/aaaicones/Applications/xcode.app/access.icns(воссозданный значок) будет текстовый файл, в котором будет прослеживаться полный путь к значкам, и путь к соответствующему примеру набора значков" /Applications/xcode.app/Contents/Applications/Instruments.app/Contents/Frameworks/InstrumentsPlugIn.framework/Versions/A/Resources/access.icns ""/aaaicones/Applications/xcode.app/access.iconset" в примере, взятом (xcode), это может создать папку в конце (со всеми значками и значками) размером 214 МБ. Если вы будете обрабатывать только один значок, он будет помещен в каталог "/aaaicones/aIconeseule/" и его исходный путь, пример /aaaicones/aIconeseule/Mac Elcapitan/.VolumeIcon.icns и /aaaicones/aIconeseule/Mac Elcapitan/.VolumeIcon.iconset с /aaaicones/aIconeseule/Mac Elcapitan/aalisticones.txt Капля ниже

on open draggedItems
    set input to draggedItems
    set fich to draggedItems


    set media to {}

    set theInfo to {}

    set n to "0"
    repeat with currentItem in draggedItems
        set dirchoisi to POSIX path of fich
        if ".icns" is not in dirchoisi then
            if "Volumes" is not in dirchoisi then

                set origi to do shell script "echo   /aaaicones" & dirchoisi
                set fich to do shell script "echo " & fich & " | xxd -p -c 100000 | sed 's#3a#2f#g' | xxd -r -p | sed 's#" & dirchoisi & "#" & "/aaaicones" & dirchoisi & "#g' | xxd -p -c 100000 | sed 's#2f#3a#g' | xxd -r -p"
                tell application "Finder"
                    if exists (folder fich) then
                        set nn to "0"
                        repeat with nn from 1 to 5
                            set origi to do shell script "echo  " & origi & "/" & " | sed 's#//#" & nn & "/" & "#'"
                            set fich to do shell script "echo " & fich & " | sed 's#:aaaicones*.*#" & origi & "#'" & " | xxd -p -c 100000 | sed 's#2f#3a#g' | xxd -r -p"

                            if not (exists folder (fich as Unicode text)) then
                                try
                                    set origi to do shell script "echo  " & origi
                                    exit repeat
                                end try
                            end if
                        end repeat
                    end if
                end tell
                tell application "Finder"
                    if not (exists folder (fich as Unicode text)) then
                        do shell script "mkdir -p -m 0777 " & quoted form of origi
                    end if
                end tell
                try
                    set theInfo to do shell script "find " & (quoted form of dirchoisi) & " -name *.icns "
                end try




                set AppleScript text item delimiters to return

                set theList to text items of theInfo

                set AppleScript text item delimiters to ""

                set n to count theList
                repeat with i from 1 to n
                    if "Volumes" is not in item i of theList then
                        set end of media to item i of theList
                    end if
                end repeat
                set n to count media
                set cheminicns to do shell script " > " & quoted form of (origi & "aalisticones.txt") & " |  chmod 777 " & quoted form of (origi & "aalisticones.txt")
                set cheminicns to do shell script "ls " & quoted form of (origi & "aalisticones.txt")

                tell application "Finder"
                    set letext to (POSIX file cheminicns as alias)
                    set label index of letext to 2
                end tell



                repeat with i from 1 to n

                    set hdd to item i of media
                    try

                        set input to do shell script "echo   " & hdd & " | sed 's#//#/#g; s#(#\\(#g;s#)#\\)#g' "
                        do shell script "echo   " & quoted form of input & " >>" & quoted form of cheminicns
                        set png to do shell script "echo " & quoted form of input & " | sed 's#.*/##' "

                        do shell script "cp -f " & quoted form of input & " " & quoted form of origi
                        set input to do shell script "iconutil -c iconset  " & quoted form of (origi & png)
                        do shell script "echo   " & quoted form of (origi & png) & " | sed 's#.icns#.iconset#' >>" & quoted form of cheminicns
                    end try
                end repeat
                tell application "Finder"
                    if exists (folder fich) then
                        open fich
                    end if
                end tell

            end if
        else

            set input to do shell script "echo   " & dirchoisi & " | sed 's#//#/#g; s#(#\\(#g;s#)#\\)#g' "
            set png to do shell script "echo " & quoted form of input & " | sed 's#.*/##' "
            set origi to do shell script "echo " & quoted form of ("/aaaicones/aIconeseule/" & input) & " | sed 's#/Volumes/##; s#" & quoted form of png & "##'"
            do shell script "mkdir -p -m 0777 " & quoted form of origi
            do shell script "echo   " & quoted form of input & " >>" & quoted form of origi & "aalisticones.txt"

            do shell script "cp -f " & quoted form of input & " " & quoted form of origi
            set input to do shell script "iconutil -c iconset  " & quoted form of (origi & png)
            do shell script "echo   " & quoted form of (origi & png) & " >>" & quoted form of origi & "aalisticones.txt"
        end if
    end repeat
end open

Ответ 17

Здесь функция, в основном основанная на примере Генри (может быть полезна в ~/.bash_profile):

mkicns() {
    if [[ -z "$*" ]] || [[ "${*##*.}" != "png" ]]; then
        echo "Input file invalid"
    else
        filename="${1%.*}"
        mkdir "$filename".iconset
        for i in 16 32 128 256 ; do
            n=$(( i * 2 ))
            sips -z $i $i "$1" --out "$filename".iconset/icon_${i}x${i}.png
            sips -z $n $n "$1" --out "$filename".iconset/icon_${i}x${i}@2x.png
            [[ $n -eq 512 ]] && \
            sips -z $n $n "$1" --out "$filename".iconset/icon_${n}x${n}.png
            (( i++ ))
        done
        cp "$1" "$filename".iconset/[email protected]
        iconutil -c icns "$filename".iconset
        rm -r "$filename".iconset
    fi
}

Использование

$ mkicns "filename.png"  # double-quote if spaces exist in filename

Создает 10 размеров от 16x16 до [email protected]; принимает входные изображения в .png.

Ответ 18

Мне это нужно, но для CMake. Я также хотел вариант дать ему SVG.

Вот суть: https://gist.github.com/Qix-/f4090181e55ea365633da8c3d0ab5249

И код CMake:

# LICENSE: CC0 - go nuts.

# Hi :) This is what I used to generate the ICNS for my game, Tide.
# Both input formats (SVG vs PNG) work just fine, but in my experience
# the SVG came out with noticeably better results (although PNG wasn't
# a catastrophe either). The logo for the game was simple enough that
# SVG was indeed an option.

# To use:
#
#    make_icns( INPUT "path/to/img.{svg,png}"
#               OUTPUT ICNS_PATH )
#
# Then add it as a custom target or use it as a
# dependency somewhere - I give you that option.
#
# For example:
#
#    add_custom_target( my-icns ALL DEPENDS "${ICNS_PATH}" )
#
# For the associated utilities:
#
# - PNG: brew install imagemagick
# - SVG: brew cask install inkscape
#
# Enjoy!

function (make_icns_from_png)
    cmake_parse_arguments (
        ARG
        ""             # Boolean args
        "INPUT;OUTPUT" # List of single-value args
        ""             # Multi-valued args
        ${ARGN})

    find_program (
        convert_exe
        NAMES "convert" "convert.exe"
        DOC "Path to ImageMagick convert")
    if (NOT convert_exe)
        message (FATAL_ERROR "Could not find ImageMagick 'convert' - is ImageMagick installed?")
    endif ()

    get_filename_component (ARG_INPUT_ABS "${ARG_INPUT}" ABSOLUTE BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
    get_filename_component (ARG_INPUT_ABS_BIN "${ARG_INPUT}" ABSOLUTE BASE_DIR "${CMAKE_CURRENT_BINARY_DIR}")
    get_filename_component (ARG_INPUT_FN "${ARG_INPUT_ABS_BIN}" NAME_WE)
    get_filename_component (ARG_INPUT_DIR "${ARG_INPUT_ABS_BIN}" DIRECTORY)

    set (sourceimg "${ARG_INPUT_ABS}")

    set (basepath "${ARG_INPUT_DIR}/${ARG_INPUT_FN}")
    set (output_icns "${basepath}.icns")
    set (iconset "${basepath}.iconset")

    set (deplist "")

    foreach (size IN ITEMS 16 32 128 256 512)
        math (EXPR size2x "2 * ${size}")

        set (ipath "${iconset}/icon_${size}x${size}.png")
        set (ipath2x "${iconset}/icon_${size}x${size}@2x.png")

        list (APPEND deplist "${ipath}" "${ipath2x}")

        add_custom_command (
            OUTPUT "${ipath}"
            COMMAND "${convert_exe}" ARGS "${sourceimg}" -resize "${size}x${size}" "${ipath}"
            MAIN_DEPENDENCY "${sourceimg}"
            COMMENT "ICNS resize: ${ipath}"
            VERBATIM)

        add_custom_command (
            OUTPUT "${ipath2x}"
            COMMAND "${convert_exe}" ARGS "${sourceimg}" -resize "${size2x}x${size2x}" "${ipath2x}"
            MAIN_DEPENDENCY "${sourceimg}"
            COMMENT "ICNS resize: ${ipath2x}"
            VERBATIM)
    endforeach ()

    add_custom_command (
        OUTPUT "${output_icns}"
        COMMAND iconutil ARGS --convert icns --output "${output_icns}" "${iconset}"
        MAIN_DEPENDENCY "${sourceimg}"
        DEPENDS ${deplist}
        COMMENT "ICNS: ${output_icns}"
        VERBATIM)

    if (ARG_OUTPUT)
        set ("${ARG_OUTPUT}" "${output_icns}" PARENT_SCOPE)
    endif ()
endfunction ()

function (make_icns_from_svg)
    cmake_parse_arguments (
        ARG
        ""             # Boolean args
        "INPUT;OUTPUT" # List of single-value args
        ""             # Multi-valued args
        ${ARGN})

    set (CMAKE_FIND_APPBUNDLE NEVER) # otherwise, it'll pick up the app bundle and open a shit ton of windows
    find_program (
        inkscape_exe
        NAMES "inkscape" "inkscape.exe"
        DOC "Path to Inkscape"
        PATHS "/usr/local/bin" "/usr/bin")

    message (STATUS "Inkscape path: ${inkscape_exe}")

    if (NOT inkscape_exe)
        message (FATAL_ERROR "Could not find Inkscape - is it installed?")
    endif ()

    get_filename_component (ARG_INPUT_ABS "${ARG_INPUT}" ABSOLUTE BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
    get_filename_component (ARG_INPUT_ABS_BIN "${ARG_INPUT}" ABSOLUTE BASE_DIR "${CMAKE_CURRENT_BINARY_DIR}")
    get_filename_component (ARG_INPUT_FN "${ARG_INPUT_ABS_BIN}" NAME_WE)
    get_filename_component (ARG_INPUT_DIR "${ARG_INPUT_ABS_BIN}" DIRECTORY)

    set (sourceimg "${ARG_INPUT_ABS}")

    set (basepath "${ARG_INPUT_DIR}/${ARG_INPUT_FN}")
    set (output_icns "${basepath}.icns")
    set (iconset "${basepath}.iconset")

    set (deplist "")

    foreach (size IN ITEMS 16 32 128 256 512)
        math (EXPR size2x "2 * ${size}")

        set (ipath "${iconset}/icon_${size}x${size}.png")
        set (ipath2x "${iconset}/icon_${size}x${size}@2x.png")

        list (APPEND deplist "${ipath}" "${ipath2x}")

        add_custom_command (
            OUTPUT "${ipath}"
            COMMAND "${inkscape_exe}" ARGS -z -e "${ipath}" -w ${size} -h ${size} "${sourceimg}"
            MAIN_DEPENDENCY "${sourceimg}"
            COMMENT "ICNS resize: ${ipath}"
            VERBATIM)

        add_custom_command (
            OUTPUT "${ipath2x}"
            COMMAND "${inkscape_exe}" ARGS -z -e "${ipath2x}" -w ${size2x} -h ${size2x} "${sourceimg}"
            MAIN_DEPENDENCY "${sourceimg}"
            COMMENT "ICNS resize: ${ipath2x}"
            VERBATIM)
    endforeach ()

    add_custom_command (
        OUTPUT "${output_icns}"
        COMMAND iconutil ARGS --convert icns --output "${output_icns}" "${iconset}"
        MAIN_DEPENDENCY "${sourceimg}"
        DEPENDS ${deplist}
        COMMENT "ICNS: ${output_icns}"
        VERBATIM)

    if (ARG_OUTPUT)
        set ("${ARG_OUTPUT}" "${output_icns}" PARENT_SCOPE)
    endif ()
endfunction ()

function (make_icns)
    cmake_parse_arguments (
        ARG
        ""             # Boolean args
        "INPUT;OUTPUT" # List of single-value args
        ""             # Multi-valued args
        ${ARGN})

    if (NOT ARG_INPUT)
        message (FATAL_ERROR "INPUT is required")
    endif ()

    if (NOT IS_ABSOLUTE "${ARG_INPUT}")
        get_filename_component (ARG_INPUT "${ARG_INPUT}" ABSOLUTE BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
    endif ()

    if (NOT EXISTS "${ARG_INPUT}")
        message (FATAL_ERROR "INPUT does not exist: ${ARG_INPUT}")
    endif ()

    file (RELATIVE_PATH ARG_INPUT "${CMAKE_CURRENT_SOURCE_DIR}" "${ARG_INPUT}")

    get_filename_component (ARG_INPUT_EXT "${ARG_INPUT}" EXT)
    if ("${ARG_INPUT_EXT}" STREQUAL ".png")
        make_icns_from_png (INPUT "${ARG_INPUT}" OUTPUT child_output)
    elseif ("${ARG_INPUT_EXT}" STREQUAL ".svg")
        make_icns_from_svg (INPUT "${ARG_INPUT}" OUTPUT child_output)
    else ()
        message (FATAL_ERROR "INPUT must refer to a .png or .svg, but a ${ARG_INPUT_EXT} was provided")
    endif ()

    if (ARG_OUTPUT)
        set ("${ARG_OUTPUT}" "${child_output}" PARENT_SCOPE)
    endif ()
endfunction ()