@@ -18,14 +18,18 @@ import java.io.File
18
18
import java.nio.file.Paths
19
19
import org.gradle.api.Plugin
20
20
import org.gradle.api.Project
21
+ import org.gradle.api.artifacts.ProjectDependency
21
22
import org.gradle.api.publish.PublishingExtension
23
+ import org.gradle.api.publish.maven.MavenPom
22
24
import org.gradle.api.publish.maven.MavenPublication
23
25
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin
24
26
import org.gradle.api.tasks.TaskProvider
25
27
import org.gradle.kotlin.dsl.apply
26
28
import org.gradle.kotlin.dsl.configure
27
29
import org.gradle.kotlin.dsl.create
30
+ import org.gradle.kotlin.dsl.findByType
28
31
import org.gradle.kotlin.dsl.register
32
+ import org.w3c.dom.Element
29
33
30
34
abstract class BaseFirebaseLibraryPlugin : Plugin <Project > {
31
35
@@ -94,22 +98,173 @@ abstract class BaseFirebaseLibraryPlugin : Plugin<Project> {
94
98
sources.value(project.provider { srcDirs })
95
99
}
96
100
101
+ /* *
102
+ * Adds + configures the [MavenPublishPlugin] for the given [project].
103
+ *
104
+ * This provides the repository we publish to (a folder in the root build directory), and
105
+ * configures maven pom generation.
106
+ *
107
+ * @see [applyPomTransformations]
108
+ * @see [FirebaseLibraryExtension.applyPomCustomization]
109
+ */
97
110
protected fun configurePublishing (project : Project , firebaseLibrary : FirebaseLibraryExtension ) {
98
- project.afterEvaluate {
99
- project. apply<MavenPublishPlugin >()
100
- project. extensions.configure<PublishingExtension > {
111
+ with ( project) {
112
+ apply<MavenPublishPlugin >()
113
+ extensions.configure<PublishingExtension > {
101
114
repositories.maven {
102
- val s = project.rootProject.buildDir.toString() + " /m2repository"
103
- url = File (s).toURI()
115
+ url = rootProject.fileFromBuildDir(" m2repository" ).toURI()
104
116
name = " BuildDir"
105
117
}
106
118
publications.create<MavenPublication >(" mavenAar" ) {
107
- from(project.components.findByName(firebaseLibrary.type.componentName))
108
- artifactId = firebaseLibrary.artifactId.get()
109
- groupId = firebaseLibrary.groupId.get()
110
- firebaseLibrary.applyPomCustomization(pom)
119
+ afterEvaluate {
120
+ artifactId =
121
+ firebaseLibrary.artifactId.get() // these dont get populated until afterEvaluate :(
122
+ groupId = firebaseLibrary.groupId.get()
123
+
124
+ firebaseLibrary.applyPomCustomization(pom)
125
+ firebaseLibrary.applyPomTransformations(pom)
126
+ from(components.findByName(firebaseLibrary.type.componentName))
127
+ }
111
128
}
112
129
}
113
130
}
114
131
}
132
+
133
+ /* *
134
+ * Performs various transformations needed to ensure the given [pom] is ready for a release.
135
+ *
136
+ * The transformations are done lazily via the [withXml][MavenPom.withXml] provider.
137
+ *
138
+ * @param pom the [MavenPom] to prepare
139
+ * @see [convertToCompileDependency]
140
+ * @see [addTypeWithAARSupport]
141
+ */
142
+ // TODO(b/270576405): Combine with applyPomCustomization when migrating FirebaseLibraryExtension
143
+ private fun FirebaseLibraryExtension.applyPomTransformations (pom : MavenPom ) {
144
+ pom.withXml {
145
+ val dependencies = asElement().findElementsByTag(" dependency" )
146
+ val androidDependencies = resolveAndroidDependencies()
147
+ for (dependency in dependencies) {
148
+ convertToCompileDependency(dependency)
149
+ addTypeWithAARSupport(dependency, androidDependencies)
150
+ }
151
+ }
152
+ }
153
+
154
+ /* *
155
+ * Adds + configures the `scope` element as a direct descendant of the provided [Element].
156
+ *
157
+ * Sets the [textContent][Element.getTextContent] of `scope` to "compile"- regardless of its
158
+ * initial value. This is needed to avoid a breaking change until the bug below is fixed.
159
+ *
160
+ * @param dependency the element to append the `scope` to
161
+ * @see applyPomTransformations
162
+ */
163
+ // TODO(b/277605778): Remove after configurations have been migrated to the right type
164
+ private fun convertToCompileDependency (dependency : Element ) {
165
+ dependency.findOrCreate(" scope" ).textContent = " compile"
166
+ }
167
+
168
+ /* *
169
+ * Adds + configures the `type` element as a direct descendant of the provided [Element].
170
+ *
171
+ * The `type` element specifies what the given [dependency] is published as. This could be another
172
+ * `pom`, a `jar`, an `aar`, etc., Usually, the [MavenPublishPlugin] can infer these types; this
173
+ * is not the case however with `aar` artifacts.
174
+ *
175
+ * This method will check if the provided [dependency] is in the provided list of artifact strings
176
+ * ([androidLibraries]), and map it to an `aar` or `jar` as needed.
177
+ *
178
+ * The following is an example of a `type` element:
179
+ * ```
180
+ * <dependency>
181
+ * <type>aar</type>
182
+ * </dependency>
183
+ * ```
184
+ *
185
+ * @param dependency the element to append the `type` to
186
+ * @param androidLibraries a list of dependencies for this given SDK that publish `aar` artifacts
187
+ * @see applyPomTransformations
188
+ */
189
+ // TODO(b/277607560): Remove when Gradle's MavenPublishPlugin adds functionality for aar types
190
+ private fun addTypeWithAARSupport (dependency : Element , androidLibraries : List <String >) {
191
+ dependency.findOrCreate(" type" ).apply {
192
+ textContent = if (androidLibraries.contains(dependency.toArtifactString())) " aar" else " jar"
193
+ }
194
+ }
115
195
}
196
+
197
+ /* *
198
+ * A list of _all_ dependencies that publish `aar` artifacts.
199
+ *
200
+ * This is collected via the [runtimeClasspath][FirebaseLibraryExtension.getRuntimeClasspath], and
201
+ * includes project level dependencies as well as external dependencies.
202
+ *
203
+ * The dependencies are mapped to their [artifactName].
204
+ *
205
+ * @see resolveProjectLevelDependencies
206
+ * @see resolveExternalAndroidLibraries
207
+ */
208
+ // TODO(b/277607560): Remove when Gradle's MavenPublishPlugin adds functionality for aar types
209
+ fun FirebaseLibraryExtension.resolveAndroidDependencies () =
210
+ resolveExternalAndroidLibraries() +
211
+ resolveProjectLevelDependencies()
212
+ .filter { it.type == LibraryType .ANDROID }
213
+ .map { it.artifactName }
214
+
215
+ /* *
216
+ * A list of project level dependencies.
217
+ *
218
+ * This is collected via the [runtimeClasspath][FirebaseLibraryExtension.getRuntimeClasspath].
219
+ *
220
+ * @throws RuntimeException if a project level dependency is found that doesn't have
221
+ * [FirebaseLibraryExtension]
222
+ */
223
+ // TODO(b/277607560): Remove when Gradle's MavenPublishPlugin adds functionality for aar types
224
+ fun FirebaseLibraryExtension.resolveProjectLevelDependencies () =
225
+ project.configurations
226
+ .getByName(runtimeClasspath)
227
+ .allDependencies
228
+ .mapNotNull { it as ? ProjectDependency }
229
+ .map {
230
+ it.dependencyProject.extensions.findByType<FirebaseLibraryExtension >()
231
+ ? : throw RuntimeException (
232
+ " Project level dependencies must have the firebaseLibrary plugin. The following dependency does not: ${it.artifactName} "
233
+ )
234
+ }
235
+
236
+ /* *
237
+ * A list of _external_ dependencies that publish `aar` artifacts.
238
+ *
239
+ * This is collected via the [runtimeClasspath][FirebaseLibraryExtension.getRuntimeClasspath], using
240
+ * an [ArtifactView][org.gradle.api.artifacts.ArtifactView] that filters for `aar` artifactType.
241
+ *
242
+ * Artifacts are mapped to their respective display name:
243
+ * ```
244
+ * groupId:artifactId:version
245
+ * ```
246
+ */
247
+ // TODO(b/277607560): Remove when Gradle's MavenPublishPlugin adds functionality for aar types
248
+ fun FirebaseLibraryExtension.resolveExternalAndroidLibraries () =
249
+ project.configurations
250
+ .getByName(runtimeClasspath)
251
+ .incoming
252
+ .artifactView { attributes { attribute(" artifactType" , " aar" ) } }
253
+ .artifacts
254
+ .map { it.variant.displayName.substringBefore(" " ) }
255
+
256
+ /* *
257
+ * The name provided to this artifact when published.
258
+ *
259
+ * Syntax sugar for:
260
+ * ```
261
+ * "$mavenName:$version"
262
+ * ```
263
+ *
264
+ * For example, the following could be an artifact name:
265
+ * ```
266
+ * "com.google.firebase:firebase-common:16.0.5"
267
+ * ```
268
+ */
269
+ val FirebaseLibraryExtension .artifactName: String
270
+ get() = " $mavenName :$version "
0 commit comments