Нативные дистрибутивы
Здесь вы узнаете о нативных дистрибутивах: как создавать установщики и пакеты для всех поддерживаемых систем и как запускать приложение локально с теми же настройками, что и для дистрибутивов.
Подробнее о следующих темах:
Подробнее об основных задачах, таких как локальный запуск приложения, и дополнительных задачах, таких как минимизация и обфускация.
Как подключить модули JDK и работать с
ClassNotFoundException.Как задать свойства дистрибутива: версию пакета, версию JDK, выходной каталог, свойства средства запуска и метаданные.
Как управлять ресурсами с помощью библиотеки ресурсов, загрузки ресурсов JVM или добавления файлов в упакованные приложения.
Как настроить наборы исходного кода с помощью набора исходного кода Gradle, целевой платформы Kotlin JVM или вручную.
Как задать значок приложения для каждой ОС.
Параметры для конкретных платформ, например адрес электронной почты сопровождающего пакета в Linux и категория приложения для Apple App Store в macOS.
Настройка для macOS: подпись, нотариальное заверение и
Info.plist.
Плагин Gradle
Это руководство посвящено прежде всего упаковке приложений Compose с помощью плагина Compose Multiplatform Gradle. Плагин org.jetbrains.compose предоставляет задачи для базовой упаковки, обфускации и подписания кода для macOS.
Плагин упрощает упаковку приложений в нативные дистрибутивы с помощью jpackage и локальный запуск приложения. Дистрибутивные приложения — это автономные устанавливаемые двоичные файлы, которые включают все необходимые компоненты среды выполнения Java, поэтому устанавливать JDK в целевой системе не требуется.
Чтобы уменьшить размер пакета, плагин Gradle использует инструмент jlink, который позволяет включить в дистрибутивный пакет только необходимые модули Java. Однако необходимо настроить плагин Gradle, указав нужные модули. Подробнее см. в разделе Подключение модулей JDK.
В качестве альтернативы можно использовать Conveyor — внешний инструмент, разработанный не JetBrains. Conveyor поддерживает онлайн-обновления, кросс-сборку и ряд других функций, но для проектов с закрытым исходным кодом требуется лицензия. Подробнее см. в документации Conveyor.
Основные задачи
Основная настраиваемая единица плагина Compose Multiplatform Gradle — application (не путайте его с плагином Gradle application, который устарел).
Метод DSL application определяет общую конфигурацию для набора конечных двоичных файлов. Это позволяет упаковать коллекцию файлов вместе с дистрибутивом JDK в набор сжатых двоичных установщиков различных форматов.
Для поддерживаемых операционных систем доступны следующие форматы:
macOS:
.dmg(TargetFormat.Dmg),.pkg(TargetFormat.Pkg)Windows:
.exe(TargetFormat.Exe),.msi(TargetFormat.Msi)Linux:
.deb(TargetFormat.Deb),.rpm(TargetFormat.Rpm)
Ниже приведен пример файла build.gradle.kts с базовой конфигурацией настольного приложения:
При сборке проекта плагин создает следующие задачи:
Задача Gradle |
Описание |
|---|---|
|
Упаковывает приложение в соответствующий двоичный файл |
|
Объединяет все задачи упаковки приложения. Это задача жизненного цикла. |
|
Создает один файл JAR со всеми зависимостями для текущей операционной системы. Для этой задачи необходимо использовать |
|
Запускает приложение локально из точки входа, указанной в |
|
Создает конечный образ приложения без создания установщика. |
|
Запускает предварительно упакованный образ приложения. |
Все доступные задачи перечислены в окне инструментов Gradle. После выполнения задачи Gradle создает выходные двоичные файлы в каталоге ${project.buildDir}/compose/binaries.
Подключение модулей JDK
Чтобы уменьшить размер дистрибутива, плагин Gradle использует jlink, который помогает включить только необходимые модули JDK.
Пока плагин Gradle не определяет необходимые модули JDK автоматически. Это не приведет к проблемам при компиляции, однако отсутствие необходимых модулей может вызвать ClassNotFoundException во время выполнения.
Если при запуске упакованного приложения или задачи runDistributable возникает ClassNotFoundException, можно подключить дополнительные модули JDK с помощью метода DSL modules:
compose.desktop {
application {
nativeDistributions {
modules("java.sql")
// Alternatively: includeAllModules = true
}
}
}
Необходимые модули можно указать вручную или запустить suggestModules. Задача suggestModules использует инструмент статического анализа jdeps, чтобы определить возможные отсутствующие модули. Обратите внимание, что вывод инструмента может быть неполным или содержать ненужные модули.
Если размер дистрибутива не имеет принципиального значения и им можно пренебречь, можно включить все модули среды выполнения с помощью свойства DSL includeAllModules.
Настройка свойств дистрибутива
Версия пакета
Для пакетов нативного дистрибутива необходимо указывать определенную версию. Чтобы задать версию пакета, используйте следующие свойства DSL, перечисленные в порядке убывания приоритета:
nativeDistributions.<os>.<packageFormat>PackageVersionзадает версию для одного формата пакета.nativeDistributions.<os>.packageVersionзадает версию для одной целевой ОС.nativeDistributions.packageVersionзадает версию для всех пакетов.
В macOS также можно задать версию сборки с помощью следующих свойств DSL, также перечисленных в порядке убывания приоритета:
nativeDistributions.macOS.<packageFormat>PackageBuildVersionзадает версию сборки для одного формата пакета.nativeDistributions.macOS.packageBuildVersionзадает версию сборки для всех пакетов macOS.
Если версия сборки не задана, Gradle использует вместо нее версию пакета. Подробнее о версионировании в macOS см. в документации по CFBundleShortVersionString и CFBundleVersion.
Ниже приведен шаблон для указания версий пакетов в порядке приоритета:
При указании версии пакета соблюдайте следующие правила:
Тип файла |
Формат версии |
Подробности |
|---|---|---|
|
|
|
|
|
|
|
|
Подробнее см. в документации Debian. |
|
Любой формат |
Версия не должна содержать символ |
Версия JDK
Плагин использует jpackage, для которого требуется JDK версии не ниже JDK 17. Указывая версию JDK, убедитесь, что выполнено хотя бы одно из следующих условий:
Переменная среды
JAVA_HOMEуказывает на совместимую версию JDK.-
Свойство
javaHomeзадано с помощью DSL:compose.desktop { application { javaHome = System.getenv("JDK_17") } }
Выходной каталог
Чтобы использовать собственный выходной каталог для нативных дистрибутивов, настройте свойство outputBaseDir, как показано ниже:
compose.desktop {
application {
nativeDistributions {
outputBaseDir.set(project.layout.buildDirectory.dir("customOutputDir"))
}
}
}
Свойства средства запуска
Чтобы настроить запуск приложения, можно задать следующие свойства:
Свойство |
Описание |
|---|---|
|
Полное имя класса, содержащего метод |
|
Аргументы метода |
|
Аргументы JVM приложения. |
Пример конфигурации:
compose.desktop {
application {
mainClass = "MainKt"
args += listOf("-customArgument")
jvmArgs += listOf("-Xmx2G")
}
}
Метаданные
В блоке DSL nativeDistributions можно настроить следующие свойства:
Свойство |
Описание |
Значение по умолчанию |
|---|---|---|
|
Имя приложения. |
Имя проекта Gradle |
|
Версия приложения. |
Версия проекта Gradle |
|
Описание приложения. |
Нет |
|
Сведения об авторских правах на приложение. |
Нет |
|
Поставщик приложения. |
Нет |
|
Файл лицензии приложения. |
Нет |
Пример конфигурации:
compose.desktop {
application {
nativeDistributions {
packageName = "ExampleApp"
packageVersion = "0.1-SNAPSHOT"
description = "Compose Multiplatform App"
copyright = "© 2024 My Name. All rights reserved."
vendor = "Example vendor"
licenseFile.set(project.file("LICENSE.txt"))
}
}
}
Управление ресурсами
Для упаковки и загрузки ресурсов можно использовать библиотеку ресурсов Compose Multiplatform, загрузку ресурсов JVM или добавлять файлы в упакованные приложения.
Библиотека ресурсов
Самый простой способ настроить ресурсы проекта — использовать библиотеку ресурсов. С ее помощью можно обращаться к ресурсам в общем коде на всех поддерживаемых платформах. Подробнее см. в разделе Ресурсы Multiplatform.
Загрузка ресурсов JVM
Compose Multiplatform для настольных систем работает на платформе JVM, поэтому ресурсы можно загружать из файла .jar с помощью API java.lang.Class. Доступ к файлу в каталоге src/main/resources можно получить через Class::getResource или Class::getResourceAsStream.
Добавление файлов в упакованное приложение
В некоторых случаях загрузка ресурсов из файлов .jar может быть неудобной, например, если у вас есть ресурсы для конкретных целевых платформ и нужно включить файлы только в пакет macOS, но не Windows.
В таких случаях можно настроить плагин Gradle для включения дополнительных файлов ресурсов в каталог установки. Укажите корневой каталог ресурсов с помощью DSL:
compose.desktop {
application {
mainClass = "MainKt"
nativeDistributions {
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
packageVersion = "1.0.0"
appResourcesRootDir.set(project.layout.projectDirectory.dir("resources"))
}
}
}
В приведенном выше примере корневым каталогом ресурсов задан <PROJECT_DIR>/resources.
Плагин Gradle включает файлы из подкаталогов ресурсов следующим образом:
Общие ресурсы: файлы из
<RESOURCES_ROOT_DIR>/commonвключаются во все пакеты независимо от целевой ОС или архитектуры.Ресурсы для конкретной ОС: файлы из
<RESOURCES_ROOT_DIR>/<OS_NAME>включаются только в пакеты, собранные для определенной операционной системы. Допустимые значения<OS_NAME>:windows,macosиlinux.Ресурсы для конкретных ОС и архитектуры: файлы из
<RESOURCES_ROOT_DIR>/<OS_NAME>-<ARCH_NAME>включаются только в пакеты, собранные для определенного сочетания операционной системы и архитектуры процессора. Допустимые значения<ARCH_NAME>:x64иarm64. Например, файлы из<RESOURCES_ROOT_DIR>/macos-arm64будут включены только в пакеты для компьютеров Mac с Apple Silicon.
Доступ к включенным ресурсам можно получить с помощью системного свойства compose.application.resources.dir:
import java.io.File
val resourcesDir = File(System.getProperty("compose.application.resources.dir"))
fun main() {
println(resourcesDir.resolve("resource.txt").readText())
}
Пользовательские наборы исходного кода
Можно использовать конфигурацию по умолчанию, если вы применяете плагины org.jetbrains.kotlin.jvm или org.jetbrains.kotlin.multiplatform:
Конфигурация с
org.jetbrains.kotlin.jvmвключает содержимое набора исходного кодаmainsource set.Конфигурация с
org.jetbrains.kotlin.multiplatformвключает содержимое одной целевой платформы JVM. Если задать несколько целевых платформ JVM, конфигурация по умолчанию отключается. В этом случае плагин необходимо настроить вручную или указать одну целевую платформу (см. ниже).
Если конфигурация по умолчанию неоднозначна или недостаточна, ее можно настроить несколькими способами:
С помощью набора исходного кода Gradle:
plugins {
kotlin("jvm")
id("org.jetbrains.compose")
}
val customSourceSet = sourceSets.create("customSourceSet")
compose.desktop {
application {
from(customSourceSet)
}
}
С помощью целевой платформы JVM Kotlin:
plugins {
kotlin("multiplatform")
id("org.jetbrains.compose")
}
kotlin {
jvm("customJvmTarget") {}
}
compose.desktop {
application {
from(kotlin.targets["customJvmTarget"])
}
}
Вручную:
Используйте
disableDefaultConfiguration, чтобы отключить настройки по умолчанию.Используйте
fromFiles, чтобы указать включаемые файлы.Укажите свойство файла
mainJar, ссылающееся на файл.jarс главным классом.Используйте
dependsOn, чтобы добавить зависимости задач ко всем задачам плагина.
compose.desktop {
application {
disableDefaultConfiguration()
fromFiles(project.fileTree("libs/") { include("**/*.jar") })
mainJar.set(project.file("main.jar"))
dependsOn("mainJarTask")
}
}
Значок приложения
Убедитесь, что значок приложения представлен в следующих форматах для соответствующих ОС:
.icnsдля macOS.icoдля Windows.pngдля Linux
compose.desktop {
application {
nativeDistributions {
macOS {
iconFile.set(project.file("icon.icns"))
}
windows {
iconFile.set(project.file("icon.ico"))
}
linux {
iconFile.set(project.file("icon.png"))
}
}
}
}
Платформо-зависимые параметры
Платформо-зависимые настройки можно задать с помощью соответствующих блоков DSL:
compose.desktop {
application {
nativeDistributions {
macOS {
// Options for macOS
}
windows {
// Options for Windows
}
linux {
// Options for Linux
}
}
}
}
В следующей таблице описаны все поддерживаемые платформо-зависимые параметры. Не рекомендуется использовать недокументированные свойства.
Платформа |
Параметр |
Описание |
|---|---|---|
Все платформы |
|
Задает путь к платформо-зависимому значку приложения. Подробнее см. в разделе Значок приложения. |
|
Задает платформо-зависимую версию пакета. Подробнее см. в разделе Версия пакета. |
|
|
Задает абсолютный или относительный путь к каталогу установки по умолчанию. В Windows также можно использовать |
|
Linux |
|
Переопределяет имя приложения по умолчанию. |
|
Задает адрес электронной почты сопровождающего пакета. |
|
|
Задает группу меню для приложения. |
|
|
Задает значение выпуска для пакета rpm или значение ревизии для пакета deb. |
|
|
Задает значение группы для пакета rpm или значение раздела для пакета deb. |
|
|
Задает тип лицензии для пакета rpm. |
|
|
Задает версию пакета для deb. Подробнее см. в разделе Версия пакета. |
|
|
Задает версию пакета для rpm. Подробнее см. в разделе Версия пакета. |
|
macOS |
|
Задает уникальный идентификатор приложения, который может содержать только буквенно-цифровые символы ( |
|
Имя приложения. |
|
|
Имя приложения, отображаемое в строке меню, пункте меню «About <App>» и в Dock. Значение по умолчанию — |
|
|
Минимальная версия macOS, необходимая для запуска приложения. Подробнее см. в разделе |
|
|
См. руководство Подписание и нотариальное заверение дистрибутивов для macOS. |
|
|
Указывает, нужно ли собирать и подписывать приложение для Apple App Store. Требуется JDK 17 или новее. |
|
|
Категория приложения для Apple App Store. При сборке для App Store значением по умолчанию является |
|
|
Задает путь к файлу с правами, используемыми при подписании. Если вы указываете собственный файл, добавьте в него права, необходимые Java-приложениям. Файл sandbox.plist используется по умолчанию при сборке для App Store. Обратите внимание, что этот файл по умолчанию может различаться в зависимости от версии JDK. Если файл не указан, плагин использует права по умолчанию, предоставляемые |
|
|
Задает путь к файлу с правами, используемыми при подписании среды выполнения JVM. Если вы указываете собственный файл, добавьте в него права, необходимые Java-приложениям. Файл sandbox.plist используется по умолчанию при сборке для App Store. Обратите внимание, что этот файл по умолчанию может различаться в зависимости от версии JDK. Если файл не указан, плагин использует права по умолчанию, предоставляемые |
|
|
Задает версию пакета для DMG. Подробнее см. в разделе Версия пакета. |
|
|
Задает версию пакета для PKG. Подробнее см. в разделе Версия пакета. |
|
|
Задает версию сборки пакета. Подробнее см. в разделе Версия пакета. |
|
|
Задает версию сборки пакета для DMG. Подробнее см. в разделе Версия пакета. |
|
|
Задает версию сборки пакета для PKG. Подробнее см. в разделе Версия пакета. |
|
|
См. раздел |
|
Windows |
|
Добавляет консольную программу запуска для приложения. |
|
Позволяет настраивать путь установки во время установки. |
|
|
Позволяет устанавливать приложение отдельно для каждого пользователя. |
|
|
Добавляет приложение в указанную группу меню «Пуск». |
|
|
Задает уникальный идентификатор, позволяющий пользователям обновлять приложение с помощью установщика, если доступна версия новее установленной. Значение должно оставаться неизменным для одного приложения. Подробнее см. в разделе Как создать GUID. |
|
|
Задает версию пакета для MSI. Подробнее см. в разделе Версия пакета. |
|
|
Задает версию пакета для EXE. Подробнее см. в разделе Версия пакета. |
Конфигурация для macOS
Подписание и нотариальное заверение в macOS
Современные версии macOS не позволяют пользователям запускать неподписанные приложения, загруженные из интернета. При попытке запустить такое приложение появится следующая ошибка: «YourApp повреждено, и его нельзя открыть. Следует извлечь образ диска».
Инструкции по подписанию и нотариальному заверению приложения см. в нашем руководстве.
Список свойств Information в macOS
DSL поддерживает основные платформо-зависимые настройки, однако могут возникнуть ситуации, выходящие за рамки предоставленных возможностей. Если вам нужно указать значения Info.plist, которые не представлены в DSL, можно использовать фрагмент XML без обработки. Этот XML будет добавлен в Info.plist приложения.
Пример: диплинкинг
-
Определите пользовательскую схему URL в файле
build.gradle.kts:compose.desktop { application { mainClass = "MainKt" nativeDistributions { targetFormats(TargetFormat.Dmg) packageName = "Deep Linking Example App" macOS { bundleID = "org.jetbrains.compose.examples.deeplinking" infoPlist { extraKeysRawXml = macExtraPlistKeys } } } } } val macExtraPlistKeys: String get() = """ <key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleURLName</key> <string>Example deep link</string> <key>CFBundleURLSchemes</key> <array> <string>compose</string> </array> </dict> </array> """ -
Используйте класс
java.awt.Desktop, чтобы настроить обработчик URI в файлеsrc/main/main.kt:import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.compose.ui.window.singleWindowApplication import java.awt.Desktop fun main() { var text by mutableStateOf("Hello, World!") try { Desktop.getDesktop().setOpenURIHandler { event -> text = "Open URI: " + event.uri } } catch (e: UnsupportedOperationException) { println("setOpenURIHandler is unsupported") } singleWindowApplication { MaterialTheme { Text(text) } } } Выполните задачу
runDistributable:./gradlew runDistributable.
В результате ссылки, например compose://foo/bar, можно будет перенаправлять из браузера в приложение.
Минификация и обфускация
Плагин Compose Multiplatform для Gradle включает встроенную поддержку ProGuard. ProGuard — это инструмент с открытым исходным кодом для минификации и обфускации кода.
Для каждой задачи упаковки по умолчанию (без ProGuard) плагин Gradle предоставляет задачу release (с ProGuard):
Задача Gradle |
Описание |
|---|---|
|
По умолчанию: Release: |
Создает образ приложения со встроенными JDK и ресурсами. |
|
По умолчанию: Release: |
Запускает образ приложения со встроенными JDK и ресурсами. |
|
По умолчанию: Release: |
Запускает неупакованное приложение |
|
По умолчанию: Release: |
Упаковывает образ приложения в файл |
|
По умолчанию: Release: |
Упаковывает образ приложения в формат, совместимый с текущей ОС. |
|
По умолчанию: Release: |
Упаковывает образ приложения в uber (fat) `.jar`. |
|
По умолчанию: Release: |
Загружает образ приложения |
|
По умолчанию: Release: |
Проверяет, успешно ли прошло нотариальное заверение (только macOS). |
Конфигурация по умолчанию включает несколько предопределенных правил ProGuard:
Образ приложения минифицируется, то есть неиспользуемые классы удаляются.
В качестве точки входа используется
compose.desktop.application.mainClass.Добавлено несколько правил
keep, чтобы среда выполнения Compose продолжала работать.
В большинстве случаев для создания минифицированного приложения дополнительная конфигурация не требуется. Однако ProGuard может не отслеживать некоторые способы использования в байт-коде, например обращение к классу через рефлексию. Если проблемы возникают только после обработки ProGuard, может потребоваться добавить пользовательские правила.
Настроить ProGuard можно с помощью DSL Gradle в блоке buildTypes.release.proguard, используя следующие параметры:
-
configurationFilesзадает пользовательские файлы конфигурации ProGuard.compose.desktop { application { buildTypes.release.proguard { configurationFiles.from(project.file("compose-desktop.pro")) } } } -
obfuscateвключает обфускацию кода. По умолчанию обфускация отключена.compose.desktop { application { buildTypes.release.proguard { obfuscate.set(true) } } } -
optimizeуправляет оптимизациями ProGuard. По умолчанию оптимизации включены.compose.desktop { application { buildTypes.release.proguard { optimize.set(false) } } } -
joinOutputJarsсоздает один uber-JAR. По умолчанию ProGuard создает отдельный файл.jarдля каждого входного.jar.compose.desktop { application { buildTypes.release.proguard { joinOutputJars.set(true) } } } -
versionзадает конкретную версию ProGuard. Для JDK 25 требуется ProGuard версии не ниже 7.8.0. Эта версия используется по умолчанию начиная с Compose Multiplatform 1.12.0. Если вы используете более раннюю версию Compose Multiplatform и выполняете сборку с JDK 25, явно задайте для этого свойства значение7.8.0:compose.desktop { application { buildTypes.release.proguard { version.set("7.8.0") } } }
Полный список правил ProGuard и параметров конфигурации см. в руководстве по ProGuard от Guardsquare.
Что дальше?
Изучите руководства по компонентам для настольных приложений.
© 2010–2026 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/multiplatform/compose-native-distribution.html