diff --git a/application/binary/build.gradle.kts b/application/binary/build.gradle.kts index 7db498de..c9888fc0 100644 --- a/application/binary/build.gradle.kts +++ b/application/binary/build.gradle.kts @@ -25,4 +25,6 @@ androidBinary( target(":core:mvvm:library"), target(":core:di:library") ) -) \ No newline at end of file +) +// TODO: enable when create crashlytics project +// .withPlugins(Plugins.googleServices, Plugins.crashlytics()) \ No newline at end of file diff --git a/application/build.gradle.kts b/application/build.gradle.kts index 94f09ecc..b19a6b4b 100644 --- a/application/build.gradle.kts +++ b/application/build.gradle.kts @@ -5,6 +5,7 @@ buildscript { } dependencies { classpath("androidx.navigation:navigation-safe-args-gradle-plugin:2.3.2") + classpath("com.google.firebase:firebase-crashlytics-gradle:2.4.1") } } diff --git a/application/buildSrc/build.gradle.kts b/application/buildSrc/build.gradle.kts index 4c72e2bd..2e07ea97 100644 --- a/application/buildSrc/build.gradle.kts +++ b/application/buildSrc/build.gradle.kts @@ -5,6 +5,7 @@ plugins { dependencies { implementation(project(":plugins:android")) implementation(project(":plugins:deps-core")) + implementation("com.google.firebase:firebase-crashlytics-gradle:2.4.1") } repositories { diff --git a/application/buildSrc/src/main/java/Google.kt b/application/buildSrc/src/main/java/Google.kt index 312a48a2..757aff1a 100644 --- a/application/buildSrc/src/main/java/Google.kt +++ b/application/buildSrc/src/main/java/Google.kt @@ -24,4 +24,7 @@ object google { val gson = deps( "com.google.code.gson:gson:${versions.google.gson}".dep ) + + val firebase = transitivePlatform("com.google.firebase:firebase-bom:26.1.0") + } \ No newline at end of file diff --git a/application/buildSrc/src/main/java/Plugins.kt b/application/buildSrc/src/main/java/Plugins.kt new file mode 100644 index 00000000..e7e7d667 --- /dev/null +++ b/application/buildSrc/src/main/java/Plugins.kt @@ -0,0 +1,21 @@ +import com.google.firebase.crashlytics.buildtools.gradle.CrashlyticsExtension +import tools.forma.android.plugin.PluginWrapper +import tools.forma.android.plugin.pluginConfiguration + +object Plugins { + + val navigationSafeArgs: PluginWrapper = PluginWrapper( + "androidx.navigation.safeargs.kotlin" + ) + + val googleServices = PluginWrapper("com.google.gms.google-services") + + fun crashlytics(mappingFileUploadEnabled: Boolean = false) = PluginWrapper( + "com.google.firebase.crashlytics", + google.firebase, + pluginConfiguration { + this.mappingFileUploadEnabled = mappingFileUploadEnabled + } + ) + +} \ No newline at end of file diff --git a/application/core/navigation/library/build.gradle.kts b/application/core/navigation/library/build.gradle.kts index 0bdbe7f5..affb685b 100644 --- a/application/core/navigation/library/build.gradle.kts +++ b/application/core/navigation/library/build.gradle.kts @@ -3,7 +3,4 @@ androidLibrary( dependencies = deps( androidx.navigation ) -) -// TODO https://github.com/formatools/forma/issues/35 -// Need configurable plugin integration here -apply(plugin = "androidx.navigation.safeargs.kotlin") \ No newline at end of file +).withPlugin(Plugins.navigationSafeArgs) \ No newline at end of file diff --git a/plugins/android/src/main/java/TargetBuilder.kt b/plugins/android/src/main/java/TargetBuilder.kt new file mode 100644 index 00000000..51a9d26b --- /dev/null +++ b/plugins/android/src/main/java/TargetBuilder.kt @@ -0,0 +1,18 @@ +import org.gradle.api.Project +import tools.forma.android.plugin.PluginWrapper + +class TargetBuilder( + private val project: Project +) { + + fun withPlugin(pluginWrapper: PluginWrapper<*>): TargetBuilder { + pluginWrapper(project) + return this + } + + fun withPlugins(vararg pluginWrappers: PluginWrapper<*>): TargetBuilder { + pluginWrappers.forEach { withPlugin(it) } + return this + } + +} \ No newline at end of file diff --git a/plugins/android/src/main/java/androidBinary.kt b/plugins/android/src/main/java/androidBinary.kt index e3b4717f..9d20871f 100644 --- a/plugins/android/src/main/java/androidBinary.kt +++ b/plugins/android/src/main/java/androidBinary.kt @@ -1,17 +1,16 @@ +import org.gradle.api.Project import tools.forma.android.feature.AndroidBinaryFeatureConfiguration import tools.forma.android.feature.androidBinaryFeatureDefinition import tools.forma.android.feature.applyFeatures -import tools.forma.android.target.BinaryTargetTemplate +import tools.forma.android.owner.NoOwner import tools.forma.android.owner.Owner +import tools.forma.android.target.BinaryTargetTemplate import tools.forma.android.utils.BuildConfiguration -import tools.forma.validation.EmptyValidator -import tools.forma.validation.validate -import tools.forma.android.owner.NoOwner import tools.forma.android.validation.disallowResources import tools.forma.deps.FormaDependency -import org.gradle.api.Project - import tools.forma.deps.applyDependencies +import tools.forma.validation.EmptyValidator +import tools.forma.validation.validate /** * Android Binary target - application entry point. @@ -35,7 +34,7 @@ fun Project.androidBinary( testInstrumentationRunner: String = androidJunitRunner, consumerMinificationFiles: Set = emptySet(), manifestPlaceholders: Map = emptyMap() -) { +): TargetBuilder { disallowResources() @@ -57,5 +56,7 @@ fun Project.androidBinary( dependencies = dependencies, repositoriesConfiguration = Forma.configuration.repositories ) + + return TargetBuilder(this) } diff --git a/plugins/android/src/main/java/androidLibrary.kt b/plugins/android/src/main/java/androidLibrary.kt index da845216..f8c0e743 100644 --- a/plugins/android/src/main/java/androidLibrary.kt +++ b/plugins/android/src/main/java/androidLibrary.kt @@ -1,20 +1,20 @@ +import org.gradle.api.Project import tools.forma.android.feature.AndroidLibraryFeatureConfiguration import tools.forma.android.feature.androidLibraryFeatureDefinition import tools.forma.android.feature.applyFeatures +import tools.forma.android.feature.kaptConfigurationFeature import tools.forma.android.feature.kotlinAndroidFeatureDefinition -import tools.forma.android.target.LibraryTargetTemplate import tools.forma.android.owner.NoOwner import tools.forma.android.owner.Owner +import tools.forma.android.target.LibraryTargetTemplate import tools.forma.android.utils.BuildConfiguration -import tools.forma.validation.EmptyValidator -import tools.forma.validation.validate import tools.forma.android.visibility.Public import tools.forma.android.visibility.Visibility import tools.forma.deps.FormaDependency import tools.forma.deps.NamedDependency -import org.gradle.api.Project -import tools.forma.android.feature.kaptConfigurationFeature import tools.forma.deps.applyDependencies +import tools.forma.validation.EmptyValidator +import tools.forma.validation.validate /** * TODO Can't depend on widgets, cant depend on databindings @@ -30,7 +30,7 @@ fun Project.androidLibrary( buildConfiguration: BuildConfiguration = BuildConfiguration(), consumerMinificationFiles: Set = emptySet(), manifestPlaceholders: Map = emptyMap() -) { +): TargetBuilder { target.validate(LibraryTargetTemplate) val libraryFeatureConfiguration = AndroidLibraryFeatureConfiguration( packageName, @@ -52,5 +52,7 @@ fun Project.androidLibrary( repositoriesConfiguration = Forma.configuration.repositories, configurationFeatures = kaptConfigurationFeature() ) + + return TargetBuilder(this) } diff --git a/plugins/android/src/main/java/tools/forma/android/plugin/PluginConfiguration.kt b/plugins/android/src/main/java/tools/forma/android/plugin/PluginConfiguration.kt new file mode 100644 index 00000000..c061cdea --- /dev/null +++ b/plugins/android/src/main/java/tools/forma/android/plugin/PluginConfiguration.kt @@ -0,0 +1,11 @@ +package tools.forma.android.plugin + +import kotlin.reflect.KClass + +data class PluginConfiguration( + val extensionClass: KClass, + val configuration: (TPluginExtension.() -> Unit) +) + +inline fun pluginConfiguration(noinline configuration: (TPluginExtension.() -> Unit)) = + PluginConfiguration(TPluginExtension::class, configuration) \ No newline at end of file diff --git a/plugins/android/src/main/java/tools/forma/android/plugin/PluginWrapper.kt b/plugins/android/src/main/java/tools/forma/android/plugin/PluginWrapper.kt new file mode 100644 index 00000000..85a53c1c --- /dev/null +++ b/plugins/android/src/main/java/tools/forma/android/plugin/PluginWrapper.kt @@ -0,0 +1,30 @@ +package tools.forma.android.plugin + +import Forma +import emptyDependency +import org.gradle.api.Project +import org.gradle.kotlin.dsl.apply +import org.gradle.kotlin.dsl.the +import tools.forma.deps.FormaDependency +import tools.forma.deps.applyDependencies +import tools.forma.validation.EmptyValidator + +class PluginWrapper( + private val pluginId: String, + private val dependencies: FormaDependency = emptyDependency(), + private val pluginConfiguration: PluginConfiguration? = null +) { + + operator fun invoke(project: Project) { + project.apply(plugin = pluginId) + pluginConfiguration?.let { + it.configuration(project.the(it.extensionClass)) + } + project.applyDependencies( + validator = EmptyValidator, + dependencies = dependencies, + repositoriesConfiguration = Forma.configuration.repositories + ) + } + +} \ No newline at end of file diff --git a/plugins/deps-core/src/main/java/dependencies.kt b/plugins/deps-core/src/main/java/dependencies.kt index e1836601..f92ef0a9 100644 --- a/plugins/deps-core/src/main/java/dependencies.kt +++ b/plugins/deps-core/src/main/java/dependencies.kt @@ -1,18 +1,19 @@ import org.gradle.api.Project - +import tools.forma.deps.ConfigurationType import tools.forma.deps.DepType +import tools.forma.deps.EmptyDependency +import tools.forma.deps.FileDependency import tools.forma.deps.FileSpec -import tools.forma.deps.NameSpec -import tools.forma.deps.TargetSpec -import tools.forma.deps.ConfigurationType +import tools.forma.deps.FormaDependency import tools.forma.deps.Implementation import tools.forma.deps.Kapt -import tools.forma.deps.FormaDependency -import tools.forma.deps.FileDependency import tools.forma.deps.MixedDependency -import tools.forma.deps.EmptyDependency -import tools.forma.deps.TargetDependency +import tools.forma.deps.NameSpec import tools.forma.deps.NamedDependency +import tools.forma.deps.PlatformDependency +import tools.forma.deps.PlatformSpec +import tools.forma.deps.TargetDependency +import tools.forma.deps.TargetSpec import tools.forma.target.FormaTarget import java.io.File @@ -43,12 +44,14 @@ inline fun emptyDependency(): T = when { fun FormaDependency.forEach( nameAction: (NameSpec) -> Unit = {}, targetAction: (TargetSpec) -> Unit = {}, - fileAction: (FileSpec) -> Unit = {} + fileAction: (FileSpec) -> Unit = {}, + platformAction: (PlatformSpec) -> Unit = {} ) { - dependency.forEach loop@ { spec -> + dependency.forEach loop@{ spec -> return@loop when (spec) { is TargetSpec -> targetAction(spec) is NameSpec -> nameAction(spec) + is PlatformSpec -> platformAction(spec) is FileSpec -> fileAction(spec) } } @@ -63,12 +66,19 @@ internal fun FormaDependency.hasConfigType(configType: ConfigurationType): Boole fun deps(vararg names: String): NamedDependency = transitiveDeps(names = *names, transitive = false) +fun platform(vararg names: String): PlatformDependency = transitivePlatform(*names, transitive = false) + +fun transitivePlatform(vararg names: String, transitive: Boolean = true): PlatformDependency = + PlatformDependency(names.toList().map { PlatformSpec(it, Implementation, transitive) }) + fun transitiveDeps(vararg names: String, transitive: Boolean = true): NamedDependency = NamedDependency(names.toList().map { NameSpec(it, Implementation, transitive) }) @Suppress("DeprecatedCallableAddReplaceWith") -@Deprecated("Deprecated in favor of targets version of this function:\n" + - "deps(target(\":name\"))") +@Deprecated( + "Deprecated in favor of targets version of this function:\n" + + "deps(target(\":name\"))" +) fun deps(vararg projects: Project): TargetDependency = TargetDependency(projects.toList().map { TargetSpec(it.target, Implementation) }) @@ -93,5 +103,5 @@ val String.kapt: NamedDependency get() = kapt(this) val Project.target: FormaTarget get() = FormaTarget(this) -fun Project.target(name: String) : FormaTarget = FormaTarget(project(name)) +fun Project.target(name: String): FormaTarget = FormaTarget(project(name)) diff --git a/plugins/deps-core/src/main/java/tools/forma/deps/ConfigurationType.kt b/plugins/deps-core/src/main/java/tools/forma/deps/ConfigurationType.kt index b1da66f3..b669405d 100644 --- a/plugins/deps-core/src/main/java/tools/forma/deps/ConfigurationType.kt +++ b/plugins/deps-core/src/main/java/tools/forma/deps/ConfigurationType.kt @@ -34,4 +34,10 @@ class NameSpec( val transitive: Boolean = false ) : DepSpec(config) +class PlatformSpec( + val name: String, + config: ConfigurationType, + val transitive: Boolean = false +) : DepSpec(config) + typealias DepType = List diff --git a/plugins/deps-core/src/main/java/tools/forma/deps/DependencyHandler.kt b/plugins/deps-core/src/main/java/tools/forma/deps/DependencyHandler.kt index 0921b564..b27599b8 100644 --- a/plugins/deps-core/src/main/java/tools/forma/deps/DependencyHandler.kt +++ b/plugins/deps-core/src/main/java/tools/forma/deps/DependencyHandler.kt @@ -36,6 +36,18 @@ fun DependencyHandler.addDependencyTo( configuration ) +// TODO: only using for platform, maybe make addPlatformDependencyTo? +fun DependencyHandler.addDependencyTo( + configurationName: String, + dependency: Dependency, + configuration: (ExternalModuleDependency).() -> Unit +): ExternalModuleDependency = addDependencyTo( + this, + configurationName, + dependency, + configuration +) + /** * Adds a dependency to the 'implementation' configuration. * diff --git a/plugins/deps-core/src/main/java/tools/forma/deps/FormaDependency.kt b/plugins/deps-core/src/main/java/tools/forma/deps/FormaDependency.kt index f58effaa..fff21ed4 100644 --- a/plugins/deps-core/src/main/java/tools/forma/deps/FormaDependency.kt +++ b/plugins/deps-core/src/main/java/tools/forma/deps/FormaDependency.kt @@ -6,6 +6,10 @@ sealed class FormaDependency( object EmptyDependency : FormaDependency() +class PlatformDependency( + val names: List = emptyList() +) : FormaDependency(names) + class NamedDependency( val names: List = emptyList() ) : FormaDependency(names) diff --git a/plugins/deps-core/src/main/java/tools/forma/deps/applyDependencies.kt b/plugins/deps-core/src/main/java/tools/forma/deps/applyDependencies.kt index 8079455d..76616787 100644 --- a/plugins/deps-core/src/main/java/tools/forma/deps/applyDependencies.kt +++ b/plugins/deps-core/src/main/java/tools/forma/deps/applyDependencies.kt @@ -1,11 +1,11 @@ package tools.forma.deps -import tools.forma.validation.Validator import emptyDependency import forEach import org.gradle.api.Project import org.gradle.api.artifacts.dsl.RepositoryHandler import org.gradle.kotlin.dsl.dependencies +import tools.forma.validation.Validator fun Project.applyDependencies( validator: Validator, @@ -27,7 +27,8 @@ fun Project.applyDependencies( addDependencyTo(it.config.name, it.name) { isTransitive = it.transitive } }, projectAction, - { add(it.config.name, files(it.file)) } + { add(it.config.name, files(it.file)) }, + { addDependencyTo(it.config.name, platform(it.name)) { isTransitive = it.transitive } } ) testDependencies.forEach( { addDependencyTo("testImplementation", it.name) { isTransitive = it.transitive } },