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