diff --git a/kotlin-native/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt b/kotlin-native/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt index c6a47bfe87a..de76943e28d 100644 --- a/kotlin-native/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt +++ b/kotlin-native/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt @@ -380,6 +380,7 @@ class K2Native : CLICompiler() { } }) putIfNotNull(RUNTIME_LOGS, arguments.runtimeLogs) + putIfNotNull(BUNDLE_ID, parseBundleId(arguments, outputKind, configuration)) } } } @@ -642,7 +643,20 @@ private fun parseKeyValuePairs( } }?.toMap() - +private fun parseBundleId( + arguments: K2NativeCompilerArguments, + outputKind: CompilerOutputKind, + configuration: CompilerConfiguration +): String? { + val argumentValue = arguments.bundleId + return if (argumentValue != null && outputKind != CompilerOutputKind.FRAMEWORK) { + configuration.report(STRONG_WARNING, "Setting a bundle ID is only supported when producing a framework " + + "but the compiler is producing ${outputKind.name.lowercase()}") + null + } else { + argumentValue + } +} fun main(args: Array) = K2Native.main(args) fun mainNoExitWithGradleRenderer(args: Array) = K2Native.mainNoExitWithGradleRenderer(args) diff --git a/kotlin-native/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.kt b/kotlin-native/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.kt index 621ccf7166f..686de3583b9 100644 --- a/kotlin-native/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.kt +++ b/kotlin-native/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.kt @@ -102,6 +102,13 @@ class K2NativeCompilerArguments : CommonCompilerArguments() { // Make sure to prepend them with -X. // Keep the list lexically sorted. + @Argument( + value = "-Xbundle-id", + valueDescription = "", + description = "Bundle ID to be set in Info.plist of a produced framework" + ) + var bundleId: String? = null + @Argument( value = "-Xcache-directory", valueDescription = "", diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt index 6bdce5a7301..3de7226ecd6 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt @@ -12,6 +12,8 @@ import org.jetbrains.kotlin.konan.target.CompilerOutputKind class KonanConfigKeys { companion object { // Keep the list lexically sorted. + val BUNDLE_ID: CompilerConfigurationKey + = CompilerConfigurationKey.create("bundle ID to be set in Info.plist of a produced framework") val CHECK_DEPENDENCIES: CompilerConfigurationKey = CompilerConfigurationKey.create("check dependencies and download the missing ones") val DEBUG: CompilerConfigurationKey diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt index e768121cc56..9d466c6441c 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.konan.objcexport import org.jetbrains.kotlin.backend.konan.* import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.KonanConfigKeys.Companion.BUNDLE_ID import org.jetbrains.kotlin.backend.konan.descriptors.getPackageFragments import org.jetbrains.kotlin.backend.konan.descriptors.isInterface import org.jetbrains.kotlin.backend.konan.getExportedDependencies @@ -157,8 +158,9 @@ internal class ObjCExport(val context: Context, symbolTable: SymbolTable) { } val file = directory.child("Info.plist") - val pkg = guessMainPackage() // TODO: consider showing warning if it is root. - val bundleId = pkg.child(Name.identifier(name)).asString() + // TODO: consider showing warning if the main package is root. + val bundleId = context.configuration[BUNDLE_ID] + ?: guessMainPackage().child(Name.identifier(name)).asString() val platform = properties.platformName() val minimumOsVersion = properties.osVersionMin diff --git a/kotlin-native/backend.native/tests/build.gradle b/kotlin-native/backend.native/tests/build.gradle index 843f79638e3..0b2f82e9470 100644 --- a/kotlin-native/backend.native/tests/build.gradle +++ b/kotlin-native/backend.native/tests/build.gradle @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.konan.target.* import org.jetbrains.kotlin.UtilsKt import java.nio.file.Paths +import java.util.regex.Pattern import static org.jetbrains.kotlin.konan.target.Architecture.* @@ -5241,6 +5242,7 @@ if (isAppleTarget(project)) { final File lazyHeader = file("$dir/$target-lazy.h") doLast { + // Check lazy header. final String expectedLazyHeaderName = "expectedLazy.h" final String expectedLazyHeaderDir = file("objcexport/") final File expectedLazyHeader = new File(expectedLazyHeaderDir, expectedLazyHeaderName) @@ -5260,6 +5262,16 @@ if (isAppleTarget(project)) { throw new Error("$expectedLazyHeader file patched;\nre-run the test and don't forget to commit the patch") } + // Check bundle ID. + final String frameworkPath = "$dir/$target/${frameworkName}.framework" + final Pattern pattern = ~"CFBundleIdentifier\n\\s*foo.bar" + final String plistPath = (target.family == Family.OSX) ? + "$frameworkPath/Resources/Info.plist" : + "$frameworkPath/Info.plist" + final String plistContent = file(plistPath).text + if (!pattern.matcher(plistContent).find()) { + throw new Error("Unexpected Info.plist content:\n$plistContent") + } } def libraryName = frameworkName + "Library" @@ -5278,7 +5290,7 @@ if (isAppleTarget(project)) { framework(frameworkName) { sources = ['objcexport'] library = libraryName - opts = ["-Xemit-lazy-objc-header=$lazyHeader", "-Xexport-kdoc"] + opts = ["-Xemit-lazy-objc-header=$lazyHeader", "-Xexport-kdoc", "-Xbundle-id=foo.bar"] } swiftSources = ['objcexport'] if (isNoopGC) {