乐闻世界logo
搜索文章和话题

Gradle 如何实现构建变体和多环境配置?

2月22日 14:08

Gradle 支持多种构建变体和产品风味,这对于 Android 开发和多环境部署尤为重要。以下是 Gradle 构建变体的详细说明:

构建变体概念

构建变体(Build Variants)是 Gradle 中用于生成不同版本应用程序的机制,它允许开发者基于不同的配置生成多个构建输出。

Android 构建变体

基本配置

groovy
android { // 构建类型 buildTypes { debug { applicationIdSuffix ".debug" versionNameSuffix "-debug" debuggable true minifyEnabled false } release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' signingConfig signingConfigs.release } } // 产品风味 flavorDimensions "version", "environment" productFlavors { free { dimension "version" applicationId "com.example.app.free" versionName "1.0-free" } paid { dimension "version" applicationId "com.example.app.paid" versionName "1.0-paid" } dev { dimension "environment" buildConfigField "String", "API_URL", "\"https://dev.api.example.com\"" resValue "string", "app_name", "My App (Dev)" } staging { dimension "environment" buildConfigField "String", "API_URL", "\"https://staging.api.example.com\"" resValue "string", "app_name", "My App (Staging)" } prod { dimension "environment" buildConfigField "String", "API_URL", "\"https://api.example.com\"" resValue "string", "app_name", "My App" } } }

构建变体组合

上面的配置会生成以下构建变体:

  • freeDevDebug
  • freeDevRelease
  • freeStagingDebug
  • freeStagingRelease
  • freeProdDebug
  • freeProdRelease
  • paidDevDebug
  • paidDevRelease
  • paidStagingDebug
  • paidStagingRelease
  • paidProdDebug
  • paidProdRelease

Java/Kotlin 构建变体

使用源集

groovy
// build.gradle sourceSets { main { java { srcDirs 'src/main/java' } resources { srcDirs 'src/main/resources' } } // 自定义源集 custom { java { srcDirs 'src/custom/java' } resources { srcDirs 'src/custom/resources' } } } // 为特定构建类型配置源集 android.sourceSets { debug { java.srcDirs 'src/debug/java' res.srcDirs 'src/debug/res' } release { java.srcDirs 'src/release/java' res.srcDirs 'src/release/res' } }

使用任务变体

groovy
// 为不同环境创建任务 tasks.register('buildDev') { group = 'build' description = 'Build for development environment' doLast { // 开发环境构建逻辑 } } tasks.register('buildStaging') { group = 'build' description = 'Build for staging environment' doLast { // 预发布环境构建逻辑 } } tasks.register('buildProd') { group = 'build' description = 'Build for production environment' doLast { // 生产环境构建逻辑 } }

多环境配置

使用配置文件

groovy
// build.gradle ext { environments = [ dev: [ apiUrl: 'https://dev.api.example.com', dbUrl: 'jdbc:mysql://dev-db.example.com:3306/mydb', enableDebug: true ], staging: [ apiUrl: 'https://staging.api.example.com', dbUrl: 'jdbc:mysql://staging-db.example.com:3306/mydb', enableDebug: false ], prod: [ apiUrl: 'https://api.example.com', dbUrl: 'jdbc:mysql://prod-db.example.com:3306/mydb', enableDebug: false ] ] } // 根据环境变量选择配置 def environment = project.hasProperty('env') ? project.env : 'dev' def config = environments[environment] tasks.register('buildWithConfig') { doLast { println "Building for environment: ${environment}" println "API URL: ${config.apiUrl}" println "DB URL: ${config.dbUrl}" println "Debug enabled: ${config.enableDebug}" } }

使用属性文件

groovy
// 创建配置任务 tasks.register('generateConfig') { def env = project.hasProperty('env') ? project.env : 'dev' def configFile = file("config/${env}.properties") inputs.file configFile outputs.dir('build/config') doLast { copy { from configFile into 'build/config' rename { 'application.properties' } } } } // 依赖配置任务 tasks.named('processResources') { dependsOn 'generateConfig' from 'build/config' }

动态变体生成

基于输入生成变体

groovy
// build.gradle def variants = ['variant1', 'variant2', 'variant3'] variants.each { variant -> tasks.register("build${variant.capitalize()}") { group = 'build' description = "Build ${variant}" doLast { println "Building ${variant}" // 变体特定的构建逻辑 } } } // 创建聚合任务 tasks.register('buildAllVariants') { group = 'build' description = 'Build all variants' dependsOn variants.collect { "build${it.capitalize()}" } }

基于配置文件生成变体

groovy
// variants.json [ { "name": "variant1", "version": "1.0.0", "features": ["feature1", "feature2"] }, { "name": "variant2", "version": "2.0.0", "features": ["feature1", "feature3"] } ] // build.gradle import groovy.json.JsonSlurper def variantsFile = file('variants.json') def variants = new JsonSlurper().parse(variantsFile) variants.each { variant -> tasks.register("build${variant.name.capitalize()}") { group = 'build' description = "Build ${variant.name} v${variant.version}" doLast { println "Building ${variant.name} version ${variant.version}" println "Features: ${variant.features.join(', ')}" } } }

变体特定依赖

为不同变体配置依赖

groovy
// Android 项目 dependencies { implementation 'androidx.core:core-ktx:1.9.0' // Debug 特定依赖 debugImplementation 'com.facebook.stetho:stetho:1.6.0' debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.10' // Release 特定依赖 releaseImplementation 'com.squareup.okhttp3:okhttp:4.10.0' // 产品风味特定依赖 freeImplementation 'com.google.android.gms:play-services-ads:21.3.0' paidImplementation 'com.example:premium-features:1.0.0' // 构建变体特定依赖 freeDevImplementation 'com.example:dev-tools:1.0.0' paidProdImplementation 'com.example:prod-analytics:1.0.0' }

Java 项目变体依赖

groovy
configurations { devImplementation stagingImplementation prodImplementation } dependencies { implementation 'org.springframework.boot:spring-boot-starter-web:3.0.0' devImplementation 'org.springframework.boot:spring-boot-devtools:3.0.0' stagingImplementation 'org.springframework.boot:spring-boot-starter-actuator:3.0.0' prodImplementation 'org.springframework.boot:spring-boot-starter-security:3.0.0' } // 为不同环境创建任务 tasks.register('runDev', JavaExec) { group = 'application' classpath = sourceSets.main.runtimeClasspath + configurations.devImplementation mainClass = 'com.example.Application' args = ['--spring.profiles.active=dev'] } tasks.register('runStaging', JavaExec) { group = 'application' classpath = sourceSets.main.runtimeClasspath + configurations.stagingImplementation mainClass = 'com.example.Application' args = ['--spring.profiles.active=staging'] } tasks.register('runProd', JavaExec) { group = 'application' classpath = sourceSets.main.runtimeClasspath + configurations.prodImplementation mainClass = 'com.example.Application' args = ['--spring.profiles.active=prod'] }

变体特定资源

Android 资源变体

shell
app/ ├── src/ │ ├── main/ │ │ ├── res/ │ │ │ ├── values/ │ │ │ │ └── strings.xml │ │ │ └── drawable/ │ │ │ └── icon.png │ ├── debug/ │ │ └── res/ │ │ └── values/ │ │ └── strings.xml │ ├── free/ │ │ └── res/ │ │ └── values/ │ │ └── strings.xml │ └── paid/ │ └── res/ │ └── values/ │ └── strings.xml

Java 资源变体

groovy
sourceSets { main { resources { srcDirs 'src/main/resources' } } dev { resources { srcDirs 'src/dev/resources' } } staging { resources { srcDirs 'src/staging/resources' } } prod { resources { srcDirs 'src/prod/resources' } } } // 为不同环境创建 JAR tasks.register('devJar', Jar) { group = 'build' from sourceSets.main.output from sourceSets.dev.output archiveFileName = 'app-dev.jar' } tasks.register('stagingJar', Jar) { group = 'build' from sourceSets.main.output from sourceSets.staging.output archiveFileName = 'app-staging.jar' } tasks.register('prodJar', Jar) { group = 'build' from sourceSets.main.output from sourceSets.prod.output archiveFileName = 'app-prod.jar' }

最佳实践

1. 合理规划变体维度

groovy
// 避免过多的变体组合 flavorDimensions "version" // 只使用一个维度 productFlavors { free { dimension "version" } paid { dimension "version" } }

2. 使用共享配置

groovy
// 定义共享配置 def commonConfig = { versionCode 1 versionName "1.0.0" minSdkVersion 21 targetSdkVersion 33 } android { defaultConfig commonConfig }

3. 使用变体过滤器

groovy
android { variantFilter { variant -> def names = variant.flavors*.name if (names.contains("paid") && names.contains("dev")) { variant.setIgnore(true) // 忽略 paidDev 变体 } } }

4. 使用构建变体特定的任务

groovy
android.applicationVariants.all { variant -> def variantName = variant.name.capitalize() tasks.register("process${variantName}Resources") { doLast { println "Processing resources for ${variant.name}" } } }

5. 使用版本目录管理变体

groovy
// gradle/libs.versions.toml [versions] spring-boot = "3.0.0" [libraries] spring-boot-web = { module = "org.springframework.boot:spring-boot-starter-web", version.ref = "spring-boot" } // 在 build.gradle 中使用 dependencies { implementation libs.spring.boot.web }
标签:Gradle