gradle 忽略外部库的proguard配置

eagi6jfj  于 11个月前  发布在  其他
关注(0)|答案(3)|浏览(84)

所以,我想在我的项目中添加一个外部库。这个库本身很小,大约有300个方法。但是它的proguard配置非常自由。我在一个准系统项目中运行了一个简单的测试,有/没有这个库,有/没有proguard,这就是我得到的结果

Proguard    Lib     Method Count
N           N       15631
Y           N       6370
N           Y       15945
Y           Y       15573

字符串
正如您所看到的,启用proguard后,计数为~6000。但是当我添加库时,计数飙升至~15000,尽管库本身只有~300个方法。
所以我的问题是,我如何忽略这个特定库的proguard配置?

更新:

这是不可能的Android gradle插件现在.我发现android bug根本没有优先级.请避免回答提到“这是不可能的”,并保持问题开放,直到一个变通办法或官方决定是可能的.否则,你将收集赏金的一半没有增加价值.谢谢!

7d7tgy0s

7d7tgy0s1#

在这种情况下,您有几个选择:

  • 从aar中提取classes.jar文件,并将其作为普通的jar依赖项包含在项目中(当aar包含资源时将不起作用)
  • 更改AAR并从中删除消费者保护规则
  • 使用DexGuard,可以过滤掉不需要的消费者规则
  • 做一点gradle黑客,见下文

将以下内容添加到您的build.gradle:

afterEvaluate {
  // All proguard tasks shall depend on our filter task
  def proguardTasks = tasks.findAll { task ->
    task.name.startsWith('transformClassesAndResourcesWithProguardFor') }
  proguardTasks.each { task -> task.dependsOn filterConsumerRules }
}

// Let's define our custom task that filters some unwanted
// consumer proguard rules
task(filterConsumerRules) << {
  // Collect all consumer rules first
  FileTree allConsumerRules = fileTree(dir: 'build/intermediates/exploded-aar',
                                       include: '**/proguard.txt')

  // Now filter the ones we want to exclude:
  // Change it to fit your needs, replace library with
  // the name of the aar you want to filter.
  FileTree excludeRules = allConsumerRules.matching {
    include '**/library/**'
  }

  // Print some info and delete the file, so ProGuard
  // does not pick it up. We could also just rename it.
  excludeRules.each { File file ->
    println 'Deleting ProGuard consumer rule ' + file
    file.delete()
  }
}

字符串
使用DexGuard(7.2.02+)时,您可以将以下代码段添加到build.gradle中:

dexguard {
  // Replace library with the name of the aar you want to filter
  // The ** at the end will include every other rule.
  consumerRuleFilter '!**/library/**,**'
}


请注意,逻辑与上面的ProGuard示例相反,consumerRuleFilter将仅包括与模式匹配的消费者规则。

bttbmeg0

bttbmeg02#

如果您使用的是R8(自Android Gradle插件3.4.0起取代了ProGuard)-您可以通过向模块的build.gradle添加以下解决方案来过滤掉特定的消费者规则文件:

tasks.whenTaskAdded { Task task ->
    // Once 'minifyEnabled' is set to 'true' for a certain build type/variant - 
    // a 'minify<variantName>WithR8' task will be created for each such variant
    //
    // - This task is implemented by com.android.build.gradle.internal.tasks.R8Task
    // - R8Task extends from ProguardConfigurableTask
    // - ProguardConfigurableTask exposes property 'configurationFiles'
    // - configurationFiles contains all files that will be contributing R8 rules
    // - configurationFiles is mutable (its type is ConfigurableFileCollection)
    //
    // Thus - we can overwrite the list of files and filter them out as we please
    //
    // More details: https://cs.android.com/android-studio/platform/tools/base/+/mirror-goog-studio-main:build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/R8Task.kt
    if (task.name.startsWith("minify") && task.name.endsWith("WithR8")) {
        afterEvaluate {
            def filteredList = task.configurationFiles.filter {
                // Example paths in this collection:
                // /Users/me/MyProject/myModule/proguard-rules.pro
                // (for library dependencies) /Users/me/.gradle/caches/<...>/okhttp3.pro

                // The below filter condition will, for example, exclude consumer ProGuard rules file from the AndroidX RecyclerView library
                !it.path.contains("recyclerview-1.1.0")
            }
            task.configurationFiles.setFrom(filteredList.files)
        }
    }
}

字符串
上述变通方法已确认适用于Android Gradle插件4.2.2
如果决定依赖这样的解决方案-这可能是一个好主意,也添加某种自动检查和/或测试,以确保此过滤工作.鉴于该解决方案是相当脆弱的,可以打破与Android Gradle插件的未来更新.

sycxhyv7

sycxhyv73#

编辑:在Gradle 7.3中,您可以通过一种方法指定要忽略哪些依赖项的保持规则:https://developer.android.com/reference/tools/gradle-api/7.3/com/android/build/api/kitches/KeepRules#kitreExternalapplications(Kotlin.Array)
举例来说:

buildTypes {
    release {
        optimization.keepRules {
            it.ignoreExternalDependencies("androidx.lifecycle:lifecycle-runtime")
        }
    }
}

字符串
旧答案:受Jonas' answer启发,针对KotlinDSL进行了修改,并确认可在Android Gradle插件7.2.1上工作:

import com.android.build.gradle.internal.tasks.ProguardConfigurableTask

afterEvaluate {
    // Get each ProguardConfigurableTask
    tasks.withType(ProguardConfigurableTask::class.java).forEach { task ->
        // Remove proguard rules from lifecycle-runtime library
        val filteredConfigurationFiles = task.configurationFiles.filter { file ->
            !file.path.contains("lifecycle-runtime")
        }
        task.configurationFiles.setFrom(filteredConfigurationFiles)
    }
}

相关问题