Публикация MacOS
macOS приложения обычно распространяются в формате .app application bundle. Для работы .NET Core и Avalonia проектов в .app пакете необходимо выполнить несколько дополнительных шагов после публикации приложения.
С Avalonia у вас будет структура папок .app, которая выглядит следующим образом:
Для получения дополнительной информации о Info.plist, смотрите документацию Apple.
Создание пакета приложения
Существует несколько вариантов создания структуры папок .app. Вы можете сделать это на любой операционной системе, так как .app файл - это просто набор папок, организованных в определенном формате, и инструменты не зависят от операционной системы. Однако, если вы создаете на Windows за пределами WSL, исполняемый файл может не иметь правильных атрибутов для выполнения на macOS -- возможно, вам придется выполнить chmod +x для выходного бинарного файла (выходные данные, сгенерированные dotnet publish) с Unix машины. Это бинарный выход, который попадает в папку MyApp.app/Contents/MacOS/, и его имя должно соответствовать CFBundleExecutable.
Структура .app зависит от правильного форматирования и содержания файла Info.plist. Используйте Xcode для редактирования Info.plist, так как он имеет автозаполнение для всех свойств. Убедитесь, что:
Значение
CFBundleExecutableсоответствует имени бинарного файла, сгенерированногоdotnet publish-- обычно это то же имя, что и у вашего .dll файла, без.dll.CFBundleNameустановлено на отображаемое имя вашего приложения. Если это имя длиннее 15 символов, также установитеCFBundleDisplayName.CFBundleIconFileустановлено на имя вашегоicnsфайла значка (включая расширение).CFBundleIdentifierустановлено на уникальный идентификатор, обычно в формате обратного DNS -- например,com.myapp.macos.NSHighResolutionCapableустановлено на true (<true/>вInfo.plist).CFBundleVersionустановлено на версию вашего пакета, например, 1.4.2.CFBundleShortVersionStringустановлено на строку версии вашего приложения, видимую пользователю, например,Major.Minor.Patch.
Если вам нужно зарегистрировать протокол или ассоциации файлов - откройте plist файлы других приложений в папке Applications и изучите их поля.
Пример протокола:
Пример ассоциации файлов
Дополнительная документация по возможным ключам Info.plist доступна здесь.
Если в какой-то момент инструменты выдают ошибку о том, что ваш файл с активами не имеет цели для osx-64, добавьте следующие идентификаторы среды выполнения в верхнюю <PropertyGroup> в вашем .csproj:
Добавьте другие идентификаторы среды выполнения по мере необходимости. Каждый идентификатор должен быть разделен точкой с запятой (;).
Примечания по созданию файлов значков
Этот тип значков можно создать не только на устройствах Apple, но также возможно на устройствах под управлением Linux.
Вы можете найти больше информации о том, как это сделать, в этом посте в блоге:
Creating Mac OS X Icons (icns) on Linux
Примечания по исполняемому файлу .app
Файл, который фактически исполняется macOS при запуске вашего .app пакета, не будет иметь стандартное расширение .dll. Если содержимое вашей папки публикации, которое попадает внутрь .app пакета, не имеет как MyApp (исполняемый файл), так и MyApp.dll, вероятно, что-то не генерируется правильно, и macOS, вероятно, не сможет запустить ваш .app правильно.
Недавние изменения в способе распространения и нотаризации .NET Core на macOS привели к тому, что исполняемый файл MyApp (также называемый "app host" в связанной документации) не генерируется. Вам нужно, чтобы этот файл был сгенерирован для правильной работы вашего .app. Чтобы убедиться, что он генерируется, выполните одно из следующих действий:
Добавьте следующее в ваш
.csprojфайл:
Добавьте
-p:UseAppHost=trueв вашу командуdotnet publish.
dotnet-bundle
:::warning dotnet-bundle не поддерживается, но все же должен работать.
Рекомендуется использовать net6-macos, который обработает создание пакета. :::
dotnet-bundle - это NuGet пакет, который публикует ваш проект, а затем создает .app файл для вас.
Сначала добавьте проект как PackageReference в ваш проект. Добавьте его через менеджер пакетов NuGet или добавив следующую строку в ваш .csproj файл:
После этого вы можете создать ваш .app, выполнив следующую команду в командной строке:
Вы можете указать другие параметры для команды dotnet msbuild. Например, если вы хотите опубликовать в режиме release:
или если вы хотите указать другое имя приложения:
Вместо того чтобы указывать CFBundleDisplayName и прочие параметры в командной строке, вы также можете указать их в вашем файле проекта:
По умолчанию dotnet-bundle поместит файл .app в ту же папку, что и выходные данные publish: [директория проекта]/bin/{Конфигурация}/netcoreapp3.1/osx-x64/publish/MyBestThingEver.app.
Для получения дополнительной информации о параметрах, которые можно передать, смотрите документацию dotnet-bundle.
Если вы создали .app на Windows, убедитесь, что выполнили chmod +x MyApp.app/Contents/MacOS/AppName с Unix-машини. В противном случае приложение не запустится на macOS.
Ручной метод
Сначала опубликуйте ваше приложение (документация dotnet publish):
Here's the translated version of the detailed tutorial on creating and packaging a macOS application using Avalonia and .NET Core:
Создание Info.plist файла, добавление или изменение ключей по необходимости:
Теперь можно создать структуру папки .app, как указано в начале этой страницы. Если вам нужен скрипт для автоматизации, вы можете использовать что-то подобное \(macOS/Unix\):
Если вы создали .app на Windows, убедитесь, что выполняете chmod +x MyApp.app/Contents/MacOS/AppName из Unix-машины. В противном случае приложение не запустится в macOS.
Подписание вашего приложения
После создания файла .app вам, вероятно, захочется подписать его, чтобы его можно было подтвердить и распространять пользователям без проблем с Gatekeeper. Нотаризация обязательна для приложений, распространяемых вне магазина приложений, начиная с macOS 10.15 \(Catalina\). Для успешной нотаризации вам нужно будет включить усиленный режим и выполнить codesign для вашего .app.
Для этого потребуется компьютер Mac, так как нам нужно будет использовать инструмент командной строки codesign из Xcode.
Запуск codesign и включение усиленного режима
Включение усиленного режима производится в том же шаге, что и подписание кода. Вам нужно подписать все файлы в пакете .app в папке Contents/MacOS, что проще сделать с помощью скрипта, так как файлов там много. Для подписания ваших файлов вам понадобится учетная запись разработчика Apple. Для нотаризации вашего приложения вам нужно будет выполнить следующие шаги с сертификатом разработчика Apple, требующим платной подписки Apple.
Также вам нужно будет установить инструменты командной строки Xcode. Вы можете сделать это, установив Xcode и запустив его, или выполнить xcode-select --install в командной строке и следовать подсказкам для установки инструментов.
Для начала включите усиленный режим с исключениями, создав файл MyAppEntitlements.entitlements:
Затем выполните этот скрипт для всех операций подписи:
Часть --options=runtime в строке codesign активирует усиленный режим с вашим приложением. Поскольку .NET Core может быть не полностью совместим с усиленным режимом, мы добавляем некоторые исключения для использования компилированного JIT-кода и разрешения отправки событий Apple. Исключение для компилированного JIT-кода необходимо для запуска приложений Avalonia под усиленным режимом. Второе исключение для событий Apple используется для устранения ошибок, которые могут появляться в Console.app.
Примечание: Microsoft перечисляет некоторые другие исключения усиленного режима, которые требуются для .NET Core. Единственное исключение, действительно необходимое для запуска приложения Avalonia, - com.apple.security.cs.allow-jit. Остальные могут представлять угрозу безопасности для вашего приложения. Используйте с осторожностью.
После подписания вашего приложения вы можете проверить, что оно подписано правильно, убедившись, что следующая команда не выводит ошибок: