diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/dsl/PlatformSettings.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/dsl/PlatformSettings.kt index 88257b3a75..88117cb303 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/dsl/PlatformSettings.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/dsl/PlatformSettings.kt @@ -20,8 +20,11 @@ open class MacOSPlatformSettings @Inject constructor(objects: ObjectFactory): Pl var packageName: String? = null var dockName: String? = null var setDockNameSameAsPackageName: Boolean = true + var packageBuildVersion: String? = null var dmgPackageVersion: String? = null + var dmgPackageBuildVersion: String? = null var pkgPackageVersion: String? = null + var pkgPackageBuildVersion: String? = null /** * An application's unique identifier across Apple's ecosystem. diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/configureApplication.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/configureApplication.kt index 66c10334d5..5587849149 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/configureApplication.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/configureApplication.kt @@ -296,6 +296,7 @@ internal fun AbstractJPackageTask.configurePlatformSettings(app: Application) { else provider { mac.dockName } ) + packageBuildVersion.set(packageBuildVersionFor(project, app, targetFormat)) nonValidatedMacBundleID.set(provider { mac.bundleID }) macExtraPlistKeysRawXml.set(provider { mac.infoPlistSettings.extraKeysRawXml }) nonValidatedMacSigningSettings = app.nativeDistributions.macOS.signing diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/packageVersions.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/packageVersions.kt index e2bed7c38d..d410e9c916 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/packageVersions.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/packageVersions.kt @@ -43,3 +43,31 @@ private fun NativeDistributions.packageVersionFor( ?: osSpecificVersion ?: packageVersion } + +internal fun packageBuildVersionFor( + project: Project, + app: Application, + targetFormat: TargetFormat +): Provider = + project.provider { + app.nativeDistributions.packageBuildVersionFor(targetFormat) + // fallback to normal version + ?: app.nativeDistributions.packageVersionFor(targetFormat) + ?: project.version.toString().takeIf { it != "unspecified" } + ?: "1.0.0" + } + +private fun NativeDistributions.packageBuildVersionFor( + targetFormat: TargetFormat +): String? { + check(targetFormat.targetOS == OS.MacOS) + val formatSpecificVersion: String? = when (targetFormat) { + TargetFormat.AppImage -> null + TargetFormat.Dmg -> macOS.dmgPackageBuildVersion + TargetFormat.Pkg -> macOS.pkgPackageBuildVersion + else -> error("invalid target format: $targetFormat") + } + val osSpecificVersion: String? = macOS.packageBuildVersion + return formatSpecificVersion + ?: osSpecificVersion +} diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/validation/validatePackageVersions.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/validation/validatePackageVersions.kt index 5fa1ef79db..301f4d7918 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/validation/validatePackageVersions.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/validation/validatePackageVersions.kt @@ -10,18 +10,13 @@ import org.gradle.api.Project import org.jetbrains.compose.desktop.application.dsl.Application import org.jetbrains.compose.desktop.application.dsl.TargetFormat import org.jetbrains.compose.desktop.application.internal.OS +import org.jetbrains.compose.desktop.application.internal.packageBuildVersionFor import org.jetbrains.compose.desktop.application.internal.packageVersionFor internal fun Project.validatePackageVersions(app: Application) { val errors = ErrorsCollector() for (targetFormat in app.nativeDistributions.targetFormats) { - val packageVersion = packageVersionFor(project, app, targetFormat).orNull - if (packageVersion == null) { - errors.addError(targetFormat, "no version was specified") - continue - } - val versionChecker: VersionChecker? = when (targetFormat) { TargetFormat.AppImage -> null TargetFormat.Deb -> DebVersionChecker @@ -30,13 +25,35 @@ internal fun Project.validatePackageVersions(app: Application) { TargetFormat.Dmg, TargetFormat.Pkg -> MacVersionChecker } - versionChecker?.apply { - if (!isValid(packageVersion)) { - errors.addError( - targetFormat, - "'$packageVersion' is not a valid version", - correctFormat = correctFormat - ) + val packageVersion = packageVersionFor(project, app, targetFormat).orNull + if (packageVersion == null) { + errors.addError(targetFormat, "no version was specified") + } else { + versionChecker?.apply { + if (!isValid(packageVersion)) { + errors.addError( + targetFormat, + "'$packageVersion' is not a valid version", + correctFormat = correctFormat + ) + } + } + } + + if (targetFormat.targetOS == OS.MacOS) { + val packageBuildVersion = packageBuildVersionFor(project, app, targetFormat).orNull + if (packageBuildVersion == null) { + errors.addError(targetFormat, "no build version was specified") + } else { + versionChecker?.apply { + if (!isValid(packageBuildVersion)) { + errors.addError( + targetFormat, + "'$packageBuildVersion' is not a valid build version", + correctFormat = correctFormat + ) + } + } } } } diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/tasks/AbstractJPackageTask.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/tasks/AbstractJPackageTask.kt index 3e53b50033..9a34ac6279 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/tasks/AbstractJPackageTask.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/tasks/AbstractJPackageTask.kt @@ -127,6 +127,10 @@ abstract class AbstractJPackageTask @Inject constructor( @get:Optional val macDockName: Property = objects.nullableProperty() + @get:Input + @get:Optional + val packageBuildVersion: Property = objects.nullableProperty() + @get:Input @get:Optional val winConsole: Property = objects.nullableProperty() @@ -477,7 +481,8 @@ abstract class AbstractJPackageTask @Inject constructor( val packageVersion = packageVersion.get()!! plist[PlistKeys.CFBundleShortVersionString] = packageVersion plist[PlistKeys.LSApplicationCategoryType] = "Unknown" - plist[PlistKeys.CFBundleVersion] = packageVersion + val packageBuildVersion = packageBuildVersion.orNull ?: packageVersion + plist[PlistKeys.CFBundleVersion] = packageBuildVersion val year = Calendar.getInstance().get(Calendar.YEAR) plist[PlistKeys.NSHumanReadableCopyright] = packageCopyright.orNull ?: "Copyright (C) $year" diff --git a/tutorials/Native_distributions_and_local_execution/README.md b/tutorials/Native_distributions_and_local_execution/README.md index 5dad5d495a..79df138556 100755 --- a/tutorials/Native_distributions_and_local_execution/README.md +++ b/tutorials/Native_distributions_and_local_execution/README.md @@ -130,6 +130,15 @@ You can use the following DSL properties (in order of descending priority): * `nativeDistributions..packageVersion` specifies a version for a single target OS; * `nativeDistributions.packageVersion` specifies a version for all packages; +For macOS you can also specify the build version using the following DSL properties (in order of descending priority): +* `nativeDistributions.macOS.PackageBuildVersion` specifies a build version for a single package format; +* `nativeDistributions.macOS.packageBuildVersion` specifies a build version for all macOS packages; + +If the build version is not specified, the package version is used. +See [CFBundleShortVersionString](https://developer.apple.com/documentation/bundleresources/information_property_list/cfbundleshortversionstring) (package version) +and [CFBundleVersion](https://developer.apple.com/documentation/bundleresources/information_property_list/cfbundleversion) (build version) +for more information about versions on macOS. + ``` kotlin compose.desktop { application { @@ -141,25 +150,32 @@ compose.desktop { // a version for all Linux distributables packageVersion = "..." // a version only for the deb package - debVersion = "..." + debPackageVersion = "..." // a version only for the rpm package - rpmVersion = "..." + rpmPackageVersion = "..." } macOS { // a version for all macOS distributables packageVersion = "..." // a version only for the dmg package - dmgVersion = "..." + dmgPackageVersion = "..." // a version only for the pkg package - pkgVersion = "..." + pkgPackageVersion = "..." + + // a build version for all macOS distributables + packageBuildVersion = "..." + // a build version only for the dmg package + dmgPackageBuildVersion = "..." + // a build version only for the pkg package + pkgPackageBuildVersion = "..." } windows { // a version for all Windows distributables packageVersion = "..." // a version only for the msi package - msiVersion = "..." + msiPackageVersion = "..." // a version only for the exe package - exeVersion = "..." + exePackageVersion = "..." } } } @@ -427,6 +443,12 @@ The following platform-specific options are available (see the section `Specifying package version` for details); * `pkgPackageVersion = "PKG_VERSION"` — a pkg-specific package version (see the section `Specifying package version` for details); + * `packageBuildVersion = "DMG_VERSION"` — a package build version + (see the section `Specifying package version` for details); + * `dmgPackageBuildVersion = "DMG_VERSION"` — a dmg-specific package build version + (see the section `Specifying package version` for details); + * `pkgPackageBuildVersion = "PKG_VERSION"` — a pkg-specific package build version + (see the section `Specifying package version` for details); * `infoPlist` — see the section `Customizing Info.plist on macOS` for details; * Windows: * `console = true` adds a console launcher for the application;