1 /*
<lambda>null2 * Copyright 2023 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 package androidx.baselineprofile.gradle.utils
17
18 import com.android.build.api.dsl.AndroidSourceDirectorySet
19 import com.android.build.api.dsl.AndroidSourceSet
20 import com.android.build.api.dsl.ApkSigningConfig
21 import com.android.build.api.dsl.ApplicationBuildType
22 import com.android.build.api.dsl.BuildType
23 import com.android.build.gradle.internal.api.DefaultAndroidSourceDirectorySet
24 import com.android.build.gradle.internal.api.DefaultAndroidSourceFile
25 import org.gradle.api.GradleException
26 import org.gradle.api.NamedDomainObjectContainer
27 import org.gradle.api.Project
28
29 internal inline fun <reified T : BuildType> createExtendedBuildTypes(
30 project: Project,
31 extensionBuildTypes: NamedDomainObjectContainer<out T>,
32 newBuildTypePrefix: String,
33 crossinline filterBlock: (T) -> (Boolean),
34 crossinline newConfigureBlock: (base: T, ext: T) -> (Unit),
35 crossinline overrideConfigureBlock: (base: T, ext: T) -> (Unit),
36 extendedBuildTypeToOriginalBuildTypeMapping: MutableMap<String, String> = mutableMapOf()
37 ) {
38 extensionBuildTypes
39 .filter { buildType ->
40 if (buildType !is T) {
41 throw GradleException("Build type `${buildType.name}` is not of type ${T::class}")
42 }
43 filterBlock(buildType)
44 }
45 .forEach { buildType ->
46 val newBuildTypeName = camelCase(newBuildTypePrefix, buildType.name)
47
48 // Check in case the build type was created manually (to allow full customization)
49 val newBuildType = extensionBuildTypes.findByName(newBuildTypeName)
50 if (newBuildType != null) {
51 project.logger.info(
52 "Build type $newBuildTypeName won't be created because already exists."
53 )
54 // If the build type exists, we apply the `overrideConfigurationBlock`
55 newBuildType.apply {
56 matchingFallbacks += listOf(buildType.name)
57 overrideConfigureBlock(buildType, this)
58 }
59 } else {
60 // If the new build type doesn't exist, create it and apply the
61 // `newConfigurationBlock`
62 extensionBuildTypes.create(newBuildTypeName).apply {
63 initWith(buildType)
64 matchingFallbacks += listOf(buildType.name)
65 newConfigureBlock(buildType, this)
66 }
67 }
68
69 // Mapping the build type to the newly created
70 extendedBuildTypeToOriginalBuildTypeMapping[newBuildTypeName] = buildType.name
71 }
72 }
73
copySigningConfigIfNotSpecifiednull74 internal inline fun <reified T : BuildType> copySigningConfigIfNotSpecified(
75 baseBuildType: T,
76 extBuildType: T,
77 debugSigningConfig: ApkSigningConfig?
78 ) {
79 // If the build type is for applications, the signing config has not been defined yet,
80 // we copy the signing config of the original build type, or the debug one if the original
81 // doesn't have one.
82 if (
83 baseBuildType is ApplicationBuildType &&
84 extBuildType is ApplicationBuildType &&
85 extBuildType.signingConfig == null
86 ) {
87 extBuildType.signingConfig = baseBuildType.signingConfig ?: debugSigningConfig
88 }
89 }
90
createBuildTypeIfNotExistsnull91 internal inline fun <reified T : BuildType> createBuildTypeIfNotExists(
92 project: Project,
93 extensionBuildTypes: NamedDomainObjectContainer<out T>,
94 buildTypeName: String,
95 crossinline configureBlock: T.() -> (Unit),
96 ) {
97 // Check in case the build type was created manually (to allow full customization)
98 if (extensionBuildTypes.findByName(buildTypeName) != null) {
99 project.logger.info("Build type $buildTypeName won't be created because already exists.")
100 return
101 }
102 // If the new build type doesn't exist, create it simply extending the configured
103 // one (by default release).
104 extensionBuildTypes.create(buildTypeName).apply { configureBlock(this) }
105 }
106
copyBuildTypeSourcesnull107 internal fun copyBuildTypeSources(
108 extensionSourceSets: NamedDomainObjectContainer<out AndroidSourceSet>,
109 fromToMapping: Map<String, String>
110 ) {
111 extensionSourceSets
112 .filter { it.name in fromToMapping.keys }
113 .forEach { toSourceSets ->
114 val fromBuildType = fromToMapping[toSourceSets.name]!!
115 val fromSourceSets = extensionSourceSets.getByName(fromBuildType)
116
117 // Copies each specified source set
118 for (dirSet in
119 listOf<(AndroidSourceSet) -> (AndroidSourceDirectorySet)>(
120 { it.aidl },
121 { it.assets },
122 { it.java },
123 { it.jniLibs },
124 { it.kotlin },
125 { it.mlModels },
126 { it.renderscript },
127 { it.res },
128 { it.resources },
129 { it.shaders },
130 )) {
131 val fromSet = dirSet(fromSourceSets) as DefaultAndroidSourceDirectorySet
132 val toSet = dirSet(toSourceSets) as DefaultAndroidSourceDirectorySet
133 toSet.srcDirs(*fromSet.srcDirs.toTypedArray())
134 }
135
136 // Copies the manifest file
137 val manifestFile = (fromSourceSets.manifest as DefaultAndroidSourceFile).srcFile
138 toSourceSets.manifest.srcFile(manifestFile)
139 }
140 }
141