1 /*
2 * Copyright 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package androidx.build
18
19 import androidx.build.gradle.extraPropertyOrNull
20 import java.util.Locale
21 import org.gradle.api.Project
22 import org.gradle.kotlin.dsl.create
23 import org.gradle.kotlin.dsl.findByType
24
25 /**
26 * A comma-separated list of target platform groups you wish to enable or disable.
27 *
28 * For example, `-jvm,+mac,+linux,+js` disables all JVM (including Android) target platforms and
29 * enables all Mac (including iOS), Linux, and JavaScript target platforms.
30 */
31 const val ENABLED_KMP_TARGET_PLATFORMS = "androidx.enabled.kmp.target.platforms"
32
33 /** Target platform groups supported by the AndroidX implementation of Kotlin multi-platform. */
34 enum class PlatformGroup {
35 JVM,
36 JS,
37 WASM,
38 MAC,
39 WINDOWS,
40 LINUX,
41 DESKTOP,
42 ANDROID_NATIVE;
43
44 companion object {
45 /** Target platform groups which require native compilation (e.g. LLVM). */
46 val native = listOf(MAC, LINUX, WINDOWS, ANDROID_NATIVE)
47
48 /**
49 * Target platform groups which are enabled by default. We currently enable all platforms by
50 * default.
51 */
52 val enabledByDefault = listOf(ANDROID_NATIVE, DESKTOP, JS, JVM, LINUX, MAC, WASM, WINDOWS)
53 }
54 }
55
56 /** Target platforms supported by the AndroidX implementation of Kotlin multi-platform. */
57 enum class PlatformIdentifier(val id: String, val group: PlatformGroup) {
58 JVM("jvm", PlatformGroup.JVM),
59 JVM_STUBS("jvmStubs", PlatformGroup.JVM),
60 JS("js", PlatformGroup.JS),
61 WASM_JS("wasmJs", PlatformGroup.WASM),
62 ANDROID("android", PlatformGroup.JVM),
63 ANDROID_NATIVE_ARM32("androidNativeArm32", PlatformGroup.ANDROID_NATIVE),
64 ANDROID_NATIVE_ARM64("androidNativeArm64", PlatformGroup.ANDROID_NATIVE),
65 ANDROID_NATIVE_X86("androidNativeX86", PlatformGroup.ANDROID_NATIVE),
66 ANDROID_NATIVE_X64("androidNativeX64", PlatformGroup.ANDROID_NATIVE),
67 MAC_ARM_64("macosarm64", PlatformGroup.MAC),
68 MAC_OSX_64("macosx64", PlatformGroup.MAC),
69 MINGW_X_64("mingwx64", PlatformGroup.WINDOWS),
70 LINUX_ARM_64("linuxarm64", PlatformGroup.LINUX),
71 LINUX_X_64("linuxx64", PlatformGroup.LINUX),
72 LINUX_X_64_STUBS("linuxx64Stubs", PlatformGroup.LINUX),
73 IOS_SIMULATOR_ARM_64("iossimulatorarm64", PlatformGroup.MAC),
74 IOS_X_64("iosx64", PlatformGroup.MAC),
75 IOS_ARM_64("iosarm64", PlatformGroup.MAC),
76 WATCHOS_SIMULATOR_ARM_64("watchossimulatorarm64", PlatformGroup.MAC),
77 WATCHOS_X_64("watchosx64", PlatformGroup.MAC),
78 WATCHOS_ARM_32("watchosarm32", PlatformGroup.MAC),
79 WATCHOS_ARM_64("watchosarm64", PlatformGroup.MAC),
80 WATCHOS_DEVICE_ARM_64("watchosdevicearm64", PlatformGroup.MAC),
81 TVOS_SIMULATOR_ARM_64("tvossimulatorarm64", PlatformGroup.MAC),
82 TVOS_X_64("tvosx64", PlatformGroup.MAC),
83 TVOS_ARM_64("tvosarm64", PlatformGroup.MAC),
84 DESKTOP("desktop", PlatformGroup.JVM);
85
86 companion object {
<lambda>null87 private val byId = values().associateBy { it.id }
88
fromIdnull89 fun fromId(id: String): PlatformIdentifier? = byId[id]
90 }
91 }
92
93 fun parseTargetPlatformsFlag(flag: String?): Set<PlatformGroup> {
94 if (flag.isNullOrBlank()) {
95 return PlatformGroup.enabledByDefault.toSortedSet()
96 }
97 val enabled = PlatformGroup.enabledByDefault.toMutableList()
98 flag.split(",").forEach {
99 val directive = it.firstOrNull() ?: ""
100 val platform = it.drop(1)
101 when (directive) {
102 '+' -> enabled.addAll(matchingPlatformGroups(platform))
103 '-' -> enabled.removeAll(matchingPlatformGroups(platform))
104 else -> {
105 throw RuntimeException("Invalid value $flag for $ENABLED_KMP_TARGET_PLATFORMS")
106 }
107 }
108 }
109 return enabled.toSortedSet()
110 }
111
matchingPlatformGroupsnull112 private fun matchingPlatformGroups(flag: String) =
113 if (flag == "native") {
114 PlatformGroup.native
115 } else {
116 listOf(PlatformGroup.valueOf(flag.uppercase(Locale.getDefault())))
117 }
118
119 private val Project.enabledKmpPlatforms: Set<PlatformGroup>
120 get() {
121 val extension: KmpPlatformsExtension =
122 extensions.findByType() ?: extensions.create("androidx.build.KmpPlatforms", this)
123 return extension.enabledKmpPlatforms
124 }
125
126 /** Extension used to store parsed KMP configuration information. */
127 private open class KmpPlatformsExtension(project: Project) {
128 val enabledKmpPlatforms =
129 parseTargetPlatformsFlag(
130 project.extraPropertyOrNull(ENABLED_KMP_TARGET_PLATFORMS) as? String
131 )
132 }
133
Projectnull134 fun Project.enableJs(): Boolean = enabledKmpPlatforms.contains(PlatformGroup.JS)
135
136 fun Project.enableAndroidNative(): Boolean =
137 enabledKmpPlatforms.contains(PlatformGroup.ANDROID_NATIVE)
138
139 fun Project.enableMac(): Boolean = enabledKmpPlatforms.contains(PlatformGroup.MAC)
140
141 fun Project.enableWindows(): Boolean = enabledKmpPlatforms.contains(PlatformGroup.WINDOWS)
142
143 fun Project.enableLinux(): Boolean = enabledKmpPlatforms.contains(PlatformGroup.LINUX)
144
145 fun Project.enableJvm(): Boolean = enabledKmpPlatforms.contains(PlatformGroup.JVM)
146
147 fun Project.enableDesktop(): Boolean = enabledKmpPlatforms.contains(PlatformGroup.DESKTOP)
148
149 fun Project.enableWasmJs(): Boolean = enabledKmpPlatforms.contains(PlatformGroup.WASM)
150