Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,7 @@ maven_install(
"android.arch.lifecycle:livedata-core",
"android.arch.lifecycle:runtime",
"android.arch.lifecycle:viewmodel",
"androidx.fragment:fragment",
"com.android.databinding:baseLibrary",
"com.android.databinding:library",
"com.android.support.test.espresso:espresso-core",
Expand All @@ -459,7 +460,6 @@ maven_install(
"com.android.support:support-compat",
"com.android.support:support-core-ui",
"com.android.support:support-core-utils",
"com.android.support:support-fragment",
"com.android.support:support-vector-drawable",
"com.android.support:versionedparcelable",
"com.android.support:viewpager",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,10 @@ import com.grab.grazel.gradle.GradleProjectInfo
import com.grab.grazel.gradle.MigrationChecker
import com.grab.grazel.gradle.MigrationCriteriaModule
import com.grab.grazel.gradle.RepositoryDataSource
import com.grab.grazel.gradle.dependencies.DefaultDependencyGraphsService
import com.grab.grazel.gradle.dependencies.DefaultDependencyResolutionService
import com.grab.grazel.gradle.dependencies.DependenciesDataSource
import com.grab.grazel.gradle.dependencies.DependenciesGraphsBuilder
import com.grab.grazel.gradle.dependencies.DependenciesModule
import com.grab.grazel.gradle.dependencies.DependencyGraphs
import com.grab.grazel.gradle.variant.AndroidVariantDataSource
import com.grab.grazel.gradle.variant.VariantBuilder
import com.grab.grazel.gradle.variant.VariantMatcher
Expand Down Expand Up @@ -96,6 +95,8 @@ internal interface GrazelComponent {
fun manifestValuesBuilder(): ManifestValuesBuilder

fun dependencyResolutionService(): GradleProvider<DefaultDependencyResolutionService>
fun dependencyGraphsService(): GradleProvider<DefaultDependencyGraphsService>
fun configurationDataSource(): Lazy<ConfigurationDataSource>
fun repositoryDataSource(): Lazy<RepositoryDataSource>
}

Expand Down Expand Up @@ -124,10 +125,6 @@ internal interface GrazelModule {
@Provides
fun @receiver:RootProject Project.provideGrazelExtension(): GrazelExtension = the()

@Provides
@Singleton
fun DependenciesGraphsBuilder.provideDependencyGraphs(): DependencyGraphs = build()

@Provides
@Singleton
fun GrazelExtension.provideKotlinExtension() = rules.kotlin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ package com.grab.grazel.gradle

import com.grab.grazel.GrazelExtension
import com.grab.grazel.di.qualifiers.RootProject
import com.grab.grazel.gradle.dependencies.DefaultDependencyGraphsService
import com.grab.grazel.gradle.dependencies.DependencyGraphs
import com.grab.grazel.gradle.dependencies.model.WorkspaceDependencies
import dagger.Lazy
import com.grab.grazel.util.GradleProvider
import org.gradle.api.Project
import org.gradle.kotlin.dsl.provideDelegate
import java.io.File
Expand All @@ -43,7 +44,7 @@ interface GradleProjectInfo {
internal class DefaultGradleProjectInfo(
override val rootProject: Project,
override val grazelExtension: GrazelExtension,
private val dependencyGraphsProvider: Lazy<DependencyGraphs>,
private val dependencyGraphsService: GradleProvider<DefaultDependencyGraphsService>,
private val workspaceDependencies: WorkspaceDependencies
) : GradleProjectInfo {

Expand All @@ -53,19 +54,19 @@ internal class DefaultGradleProjectInfo(
@param:RootProject
private val rootProject: Project,
private val grazelExtension: GrazelExtension,
private val dependencyGraphsProvider: Lazy<DependencyGraphs>,
private val dependencyGraphsService: GradleProvider<DefaultDependencyGraphsService>,
) {
fun create(
workspaceDependencies: WorkspaceDependencies
): GradleProjectInfo = DefaultGradleProjectInfo(
rootProject,
grazelExtension,
dependencyGraphsProvider,
dependencyGraphsService,
workspaceDependencies
)
}

private val projectGraph: DependencyGraphs get() = dependencyGraphsProvider.get()
private val projectGraph: DependencyGraphs get() = dependencyGraphsService.get().get()

override val hasDagger: Boolean by lazy {
workspaceDependencies
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@

package com.grab.grazel.gradle

import com.grab.grazel.gradle.dependencies.DefaultDependencyGraphsService
import com.grab.grazel.gradle.dependencies.DependenciesDataSource
import com.grab.grazel.gradle.dependencies.DependencyGraphs
import dagger.Lazy
import com.grab.grazel.util.GradleProvider
import dagger.Module
import dagger.Provides
import dagger.multibindings.ElementsIntoSet
Expand All @@ -44,7 +44,7 @@ internal object MigrationCriteriaModule {

@Singleton
internal class MigrationChecker @Inject constructor(
private val dependencyGraphsProvider: Lazy<DependencyGraphs>,
private val dependencyGraphsService: GradleProvider<DefaultDependencyGraphsService>,
private val migrationCriteria: Set<@JvmSuppressWildcards MigrationCriteria>
) : MigrationCriteria {
/**
Expand All @@ -63,7 +63,8 @@ internal class MigrationChecker @Inject constructor(
return when {
canMigrateInternal(project) -> true
else -> {
dependencyGraphsProvider
dependencyGraphsService
.get()
.get()
.dependenciesSubGraphByVariant(project)
.all(::canMigrateInternal)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ internal interface DependenciesModule {
@RootProject rootProject: Project
): GradleProvider<@JvmSuppressWildcards DefaultDependencyResolutionService> =
DefaultDependencyResolutionService.register(rootProject)

@Singleton
@Provides
fun dependencyGraphsService(
@RootProject rootProject: Project
): GradleProvider<@JvmSuppressWildcards DefaultDependencyGraphsService> =
DefaultDependencyGraphsService.register(rootProject)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/*
* Copyright 2022 Grabtaxi Holdings PTE LTD (GRAB)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.grab.grazel.gradle.dependencies

import com.grab.grazel.di.qualifiers.RootProject
import com.grab.grazel.gradle.ConfigurationDataSource
import com.grab.grazel.gradle.dependencies.DependencyGraphsService.Companion.SERVICE_NAME
import com.grab.grazel.gradle.variant.AndroidVariantDataSource
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import org.gradle.api.Project
import org.gradle.api.services.BuildService
import org.gradle.api.services.BuildServiceParameters

/**
* A [BuildService] to lazily build and cache dependency graphs during task execution phase.
*
* This ensures that Gradle configuration resolution happens during execution phase rather than
* configuration phase, following Gradle best practices.
*/
internal interface DependencyGraphsService : BuildService<DependencyGraphsService.Params>,
AutoCloseable {

/**
* Get the dependency graphs. Lazily builds the graphs on first access using dependencies
* provided via [configure].
*
* @throws IllegalStateException if [configure] has not been called
*/
fun get(): DependencyGraphs

/**
* Configure the service with dependencies needed to build graphs. This should be called during
* task configuration phase. The actual graph building is deferred until [get] is called.
*
* @param rootProject The root Gradle project
* @param dependenciesDataSource Source for project dependencies
* @param configurationDataSource Source for configuration data
* @param androidVariantDataSource Source for Android variant data
*/
fun configure(
rootProject: Project,
dependenciesDataSource: DependenciesDataSource,
configurationDataSource: ConfigurationDataSource,
androidVariantDataSource: AndroidVariantDataSource
)

companion object {
internal const val SERVICE_NAME = "DependencyGraphsService"
}

interface Params : BuildServiceParameters
}

internal abstract class DefaultDependencyGraphsService : DependencyGraphsService {
private var dependencyGraphs: DependencyGraphs? = null
private val buildMutex = Mutex()

private var rootProject: Project? = null
private var dependenciesDataSource: DependenciesDataSource? = null
private var configurationDataSource: ConfigurationDataSource? = null
private var androidVariantDataSource: AndroidVariantDataSource? = null

override fun configure(
rootProject: Project,
dependenciesDataSource: DependenciesDataSource,
configurationDataSource: ConfigurationDataSource,
androidVariantDataSource: AndroidVariantDataSource
) {
this.rootProject = rootProject
this.dependenciesDataSource = dependenciesDataSource
this.configurationDataSource = configurationDataSource
this.androidVariantDataSource = androidVariantDataSource
}

override fun get(): DependencyGraphs {
// Lazily build on first access
if (dependencyGraphs == null) {
val root = rootProject
?: error("DependencyGraphsService not configured. Call configure() first during task configuration.")
val deps = dependenciesDataSource
?: error("DependencyGraphsService not configured. Call configure() first during task configuration.")
val config = configurationDataSource
?: error("DependencyGraphsService not configured. Call configure() first during task configuration.")
val variants = androidVariantDataSource
?: error("DependencyGraphsService not configured. Call configure() first during task configuration.")

runBlocking {
buildMutex.withLock {
if (dependencyGraphs == null) {
dependencyGraphs = DependenciesGraphsBuilder(
root,
deps,
config,
variants
).build()
}
}
}
}
return dependencyGraphs!!
}

override fun close() {
dependencyGraphs = null
rootProject = null
dependenciesDataSource = null
configurationDataSource = null
androidVariantDataSource = null
}

companion object {
internal fun register(@RootProject rootProject: Project) = rootProject
.gradle
.sharedServices
.registerIfAbsent(SERVICE_NAME, DefaultDependencyGraphsService::class.java) {}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,21 @@ import org.gradle.api.Project

internal interface AndroidVariantDataSource {
/**
* Variant filter instance to filter out unsupported variants
* Returns the variant filter instance to filter out unsupported variants.
*
* Note: This function may be computed on each call by reading from [GrazelExtension.android.variantFilter].
* This ensures the filter is evaluated after user configuration runs.
*/
val variantFilter: Action<VariantFilter>?
fun getVariantFilter(): Action<VariantFilter>?

/**
* This method will return the flavors which are ignored after evaluate the ignore variants
* determined by [variantFilter]
* determined by [getVariantFilter]
*/
fun getIgnoredFlavors(project: Project): List<ProductFlavor>

/**
* This method will return the variants which are ignored by the configuration determined by [variantFilter]
* This method will return the variants which are ignored by the configuration determined by [getVariantFilter]
*/
fun getIgnoredVariants(project: Project): List<BaseVariant>

Expand Down Expand Up @@ -92,9 +95,11 @@ internal class DefaultVariantFilter(variant: BaseVariant) : VariantFilter {

internal class DefaultAndroidVariantDataSource(
private val androidVariantsExtractor: AndroidVariantsExtractor,
override val variantFilter: Action<VariantFilter>? = null,
private val variantFilterProvider: () -> Action<VariantFilter>? = { null },
) : AndroidVariantDataSource {

override fun getVariantFilter(): Action<VariantFilter>? = variantFilterProvider()

private fun Project.androidVariants() =
androidVariantsExtractor.getVariants(this) +
androidVariantsExtractor.getUnitTestVariants(this) +
Expand Down Expand Up @@ -168,7 +173,7 @@ internal class DefaultAndroidVariantDataSource(
private fun ignoredVariantFilter(
variant: BaseVariant
): Boolean = DefaultVariantFilter(variant)
.apply { variantFilter?.execute(this) }
.apply { getVariantFilter()?.execute(this) }
.ignored
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ internal interface VariantModule {
androidVariantsExtractor: DefaultAndroidVariantsExtractor,
@RootProject rootProject: Project
): AndroidVariantDataSource = DefaultAndroidVariantDataSource(
variantFilter = android.variantFilter,
variantFilterProvider = { android.variantFilter },
androidVariantsExtractor = androidVariantsExtractor
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import com.android.build.gradle.api.AndroidSourceSet
import com.grab.grazel.GrazelExtension
import com.grab.grazel.bazel.rules.Multidex
import com.grab.grazel.bazel.starlark.BazelDependency
import com.grab.grazel.gradle.dependencies.DefaultDependencyGraphsService
import com.grab.grazel.gradle.dependencies.DependenciesDataSource
import com.grab.grazel.gradle.variant.VariantGraphKey
import com.grab.grazel.gradle.variant.VariantType
Expand All @@ -37,7 +38,7 @@ import com.grab.grazel.gradle.variant.nameSuffix
import com.grab.grazel.migrate.android.SourceSetType.JAVA_KOTLIN
import com.grab.grazel.migrate.dependencies.calculateDirectDependencyTags
import com.grab.grazel.migrate.kotlin.kotlinParcelizeDeps
import dagger.Lazy
import com.grab.grazel.util.GradleProvider
import org.gradle.api.Project
import org.gradle.kotlin.dsl.getByType
import javax.inject.Inject
Expand All @@ -59,11 +60,11 @@ constructor(
private val androidManifestParser: AndroidManifestParser,
private val grazelExtension: GrazelExtension,
private val dependenciesDataSource: DependenciesDataSource,
private val dependencyGraphsProvider: Lazy<DependencyGraphs>,
private val dependencyGraphsService: GradleProvider<DefaultDependencyGraphsService>,
private val gradleDependencyToBazelDependency: GradleDependencyToBazelDependency
) : AndroidLibraryDataExtractor {

private val projectDependencyGraphs get() = dependencyGraphsProvider.get()
private val projectDependencyGraphs: DependencyGraphs get() = dependencyGraphsService.get().get()

override fun extract(
project: Project,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import com.android.build.gradle.BaseExtension
import com.android.build.gradle.api.AndroidSourceSet
import com.grab.grazel.GrazelExtension
import com.grab.grazel.bazel.starlark.BazelDependency
import com.grab.grazel.gradle.dependencies.DefaultDependencyGraphsService
import com.grab.grazel.gradle.dependencies.DependenciesDataSource
import com.grab.grazel.gradle.dependencies.DependencyGraphs
import com.grab.grazel.gradle.dependencies.GradleDependencyToBazelDependency
Expand All @@ -30,7 +31,7 @@ import com.grab.grazel.gradle.variant.AndroidVariantDataSource
import com.grab.grazel.gradle.variant.MatchedVariant
import com.grab.grazel.gradle.variant.getMigratableBuildVariants
import com.grab.grazel.gradle.variant.nameSuffix
import dagger.Lazy
import com.grab.grazel.util.GradleProvider
import org.gradle.api.Project
import org.gradle.kotlin.dsl.getByType
import java.io.File
Expand All @@ -50,14 +51,14 @@ internal class DefaultAndroidInstrumentationBinaryDataExtractor
@Inject constructor(
private val variantDataSource: AndroidVariantDataSource,
private val dependenciesDataSource: DependenciesDataSource,
private val dependencyGraphsProvider: Lazy<DependencyGraphs>,
private val dependencyGraphsService: GradleProvider<DefaultDependencyGraphsService>,
private val gradleDependencyToBazelDependency: GradleDependencyToBazelDependency,
private val androidManifestParser: AndroidManifestParser,
private val manifestValuesBuilder: ManifestValuesBuilder,
private val keyStoreExtractor: KeyStoreExtractor,
private val grazelExtension: GrazelExtension,
) : AndroidInstrumentationBinaryDataExtractor {
private val projectDependencyGraphs get() = dependencyGraphsProvider.get()
private val projectDependencyGraphs: DependencyGraphs get() = dependencyGraphsService.get().get()

override fun extract(
project: Project,
Expand Down
Loading
Loading