Cuy*_*yer 0 android gradle android-gradle-plugin gradle-kotlin-dsl
我正在尝试了解 Android 中的模块化是如何工作的。我正在使用 Kotlin DSL。
在每个 build.gradle.kts 文件中,我是否必须添加默认配置,例如 minSdk、目标 SDK 等?换句话说,我是否只能在应用程序模块 build.gradle.kts 文件中设置配置,而在其他模块中(例如功能)是否可以只声明依赖项?
NowInAndroid 应用程序的 build.gradle.kts 文件具有以下代码:
plugins {
id("nowinandroid.android.feature")
id("nowinandroid.android.library.compose")
id("nowinandroid.android.library.jacoco")
}
android {
namespace = "com.google.samples.apps.nowinandroid.feature.bookmarks"
}
dependencies {
implementation(libs.androidx.compose.material3.windowSizeClass)
}
Run Code Online (Sandbox Code Playgroud)
它只声明依赖项和插件,但我认为这些插件中有不同的配置。
我看到的另一种方法是使用继承其他 build.gradle 文件
apply {
(path to build.gradle) file
}
Run Code Online (Sandbox Code Playgroud)
但使用该方法时,我无法声明名称空间,因此我必须将其添加到 build.gradle 文件中,该文件在不同功能之间共享,如果没有它,我将无法访问给定功能模块中的资源。
多项目构建中的构建逻辑可以组织成可重用的插件(Gradle 约定插件)。
\n约定插件并不是指特定的插件(如 com.android.library),而是指一类预编译的插件,其作用是提取一些共享的构建逻辑。
首先,让我们手动创建一个build-logic具有以下结构的新模块调用:
rootProject\n\xe2\x94\x9c\xe2\x94\x80build-logic\n\xe2\x94\x82 \xe2\x94\x82 settings.gradle.kts\n\xe2\x94\x82 \xe2\x94\x94\xe2\x94\x80convention\n\xe2\x94\x82 \xe2\x94\x82 build.gradle.kts\n\xe2\x94\x82 \xe2\x94\x94\xe2\x94\x80src\n\xe2\x94\x82 \xe2\x94\x94\xe2\x94\x80main\n\xe2\x94\x82 \xe2\x94\x94\xe2\x94\x80kotlin\n\xe2\x94\x82 AndroidLibraryConventionPlugin.kt\n\xe2\x94\x9c\xe2\x94\x80...\nRun Code Online (Sandbox Code Playgroud)\n 我们将通过组合构建将该模块包含build-logic在根项目中。
\n\n复合构建只是包含其他构建的构建。在许多方面,复合构建与 Gradle 多项目构建类似,只不过它不包含单个项目,而是包含完整的构建。
\n
rootProject/settings.gradle.kts:
rootProject\n\xe2\x94\x9c\xe2\x94\x80build-logic\n\xe2\x94\x82 \xe2\x94\x82 settings.gradle.kts\n\xe2\x94\x82 \xe2\x94\x94\xe2\x94\x80convention\n\xe2\x94\x82 \xe2\x94\x82 build.gradle.kts\n\xe2\x94\x82 \xe2\x94\x94\xe2\x94\x80src\n\xe2\x94\x82 \xe2\x94\x94\xe2\x94\x80main\n\xe2\x94\x82 \xe2\x94\x94\xe2\x94\x80kotlin\n\xe2\x94\x82 AndroidLibraryConventionPlugin.kt\n\xe2\x94\x9c\xe2\x94\x80...\nRun Code Online (Sandbox Code Playgroud)\n \n\n包含在复合构建中的构建自然被称为“包含的构建”。包含的构建不与复合构建或其他包含的构建共享任何配置。每个包含的构建都是独立配置和执行的。
\n
由于包含的构建是完全独立的,因此我们需要在 中声明存储库源settings.gradle.kts,并显式声明版本目录文件的路径。
rootProject/build-logic/settings.gradle.kts:
pluginManagement {\n includeBuild("build-logic") // include build-logic module\n repositories {\n google()\n mavenCentral()\n gradlePluginPortal()\n }\n}\n\ndependencyResolutionManagement {\n repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)\n repositories {\n google()\n mavenCentral()\n }\n}\n\nrootProject.name = "GradleConventionPluginsSample"\ninclude(":app")\nRun Code Online (Sandbox Code Playgroud)\n请注意,您需要确保文件 rootProject/gradle/verison.toml 存在,并向其中添加以下行。
\nrootProject/gradle/verison.toml:
dependencyResolutionManagement {\n repositories {\n google()\n mavenCentral()\n }\n versionCatalogs {\n create("libs") {\n // make sure the file rootProject/gradle/verison.toml exists!\n from(files("../gradle/libs.versions.toml"))\n }\n }\n}\n\nrootProject.name = "build-logic"\ninclude(":convention")\nRun Code Online (Sandbox Code Playgroud)\n rootProject/build-logic/convention/build.gradle.kts:
[versions]\n...\nandroidGradlePlugin = "8.1.2"\nkotlin = "1.9.10"\n\n\n[libraries]\n...\n# Dependencies of the included build-logic\nandroid-gradlePlugin = { group = "com.android.tools.build", name = "gradle", version.ref = "androidGradlePlugin" }\nkotlin-gradlePlugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" }\n\n[plugins]\n...\nRun Code Online (Sandbox Code Playgroud)\n在 的文件中build-logic/convention/build.gradle.kts,我们应用kotlin-dsl插件,添加依赖项...最后注册约定插件。
请注意,我们还没有实现implementationClass,这是我们的最后一步。
\n将共享构建逻辑放入其中,AndroidLibraryConventionPlugin以便我们可以在其他 Android 库模块中重用它。
rootProject/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile\n\nplugins {\n `kotlin-dsl`\n}\n\ngroup = "com.bqliang.gradleconventionplugins.buildlogic"\n\n// Configure the build-logic plugins to target JDK 17\n// This matches the JDK used to build the project, and is not related to what is running on device.\njava {\n sourceCompatibility = JavaVersion.VERSION_17\n targetCompatibility = JavaVersion.VERSION_17\n}\ntasks.withType<KotlinCompile>().configureEach {\n kotlinOptions {\n jvmTarget = JavaVersion.VERSION_17.toString()\n }\n}\n\ndependencies {\n compileOnly(libs.android.gradlePlugin)\n compileOnly(libs.kotlin.gradlePlugin)\n}\n\ngradlePlugin {\n // register the convention plugin\n plugins {\n register("androidLibrary") {\n id = "bqliang.android.library"\n implementationClass = "AndroidLibraryConventionPlugin"\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n\n我的Gradle版本是8.4,如果你在上面的代码中找不到某些类,你可以先尝试升级你的Gradle版本。
\n
\nrootProject/gradle/wrapper/gradle-wrapper.properties:
\ndistributionUrl=https://services.gradle.org/distributions/gradle-8.4-bin.zip
因为我们已经在使用版本目录。为什么不把我们刚刚创建的 AndroidLibraryConventionPlugin 的插件 id 放在libs.versions.toml文件中呢?
rootProject/gralde/libs.versions.toml:
import com.android.build.api.dsl.CommonExtension\nimport com.android.build.gradle.LibraryExtension\nimport org.gradle.api.JavaVersion\nimport org.gradle.api.Plugin\nimport org.gradle.api.Project\nimport org.gradle.kotlin.dsl.configure\nimport org.gradle.kotlin.dsl.withType\nimport org.jetbrains.kotlin.gradle.tasks.KotlinCompile\n\nclass AndroidLibraryConventionPlugin : Plugin<Project> {\n override fun apply(project: Project) {\n with(project) {\n with(pluginManager) {\n apply("com.android.library")\n apply("org.jetbrains.kotlin.android")\n }\n\n extensions.configure<LibraryExtension> {\n configureKotlinAndroid(this)\n defaultConfig.targetSdk = 34\n }\n }\n }\n\n private fun Project.configureKotlinAndroid(\n commonExtension: CommonExtension<*, *, *, *, *>,\n ) {\n commonExtension.apply {\n compileSdk = 34\n\n defaultConfig {\n minSdk = 26\n }\n\n compileOptions {\n sourceCompatibility = JavaVersion.VERSION_11\n targetCompatibility = JavaVersion.VERSION_11\n }\n }\n\n configureKotlin()\n }\n\n private fun Project.configureKotlin() {\n // Use withType to workaround https://youtrack.jetbrains.com/issue/KT-55947\n tasks.withType<KotlinCompile>().configureEach {\n kotlinOptions {\n // Set JVM target to 11\n jvmTarget = JavaVersion.VERSION_11.toString()\n }\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n 现在我们可以在其他android库模块中使用AndroidLibraryConventionPlugin了。创建一个由 Android Studio 调用的新 Android 库模块mylibrary。module中的build.gradle.ktsmylibrary如下:
[versions]\n...\n\n[libraries]\n...\n\n[plugins]\nbqliang-android-library = { id = "bqliang.android.library", version = "unspecified" }\n...\nRun Code Online (Sandbox Code Playgroud)\n我们已将上述有关 Android 库的构建逻辑放入 中AndroidLibraryConventionPlugin,因此我们可以删除它们并仅应用我们的约定插件。
@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed\nplugins {\n alias(libs.plugins.com.android.library)\n alias(libs.plugins.org.jetbrains.kotlin.android)\n}\n\nandroid {\n namespace = "com.bqliang.mylibrary"\n compileSdk = 33\n\n defaultConfig {\n minSdk = 24\n\n testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"\n consumerProguardFiles("consumer-rules.pro")\n }\n\n ...\n compileOptions {\n sourceCompatibility = JavaVersion.VERSION_1_8\n targetCompatibility = JavaVersion.VERSION_1_8\n }\n kotlinOptions {\n jvmTarget = "1.8"\n }\n}\n\ndependencies {\n ...\n}\nRun Code Online (Sandbox Code Playgroud)\n伟大的!我们创建了一个可重用的约定插件,可以在多个项目之间共享构建逻辑。通过这种方式,我们可以从不同的模块中抽象出相同的构建逻辑(如compileSdk、sourceCompatibility、targetCompatibility...)。据我所知,现在Android项目中也使用这种方式。
\n上面只是一个非常简单的示例,实际上您可以在约定插件中共享更多构建逻辑,例如productFlavors、Jetpack Compose、Room、构建类型、测试等。
\n这些插件是可附加的和可组合的,并尝试只完成单一职责。然后模块可以选择它们需要的配置。
\n参考:
\n| 归档时间: |
|
| 查看次数: |
930 次 |
| 最近记录: |