升级到
cronet-embedded:119.6045.31
后,我从 R8 中遇到此构建失败:
ERROR: /re/dac/ted/gradle_home/caches/transforms-3/30da92821347fd2259fb4e0490f978c1/transformed/jetified-cronet-embedded-119.6045.31/proguard.txt:103:34: R8: Expected char '-' at /re/dac/ted/gradle_home/caches/transforms-3/30da92821347fd2259fb4e0490f978c1/transformed/jetified-cronet-embedded-119.6045.31/proguard.txt:103:34
-maximumremovedandroidloglevel 1 class ** {
^
Execution failed for task ':app:minifyReleaseWithR8'. org.gradle.workers.internal.DefaultWorkerExecutor$WorkExecutionException: A failure occurred while executing com.android.build.gradle.internal.tasks.R8Task$R8Runnable
我能找到的唯一 文档
maximumremovedandroidloglevel
没有显示该规则的 class
参数:
R8 可以通过 ProGuard 规则集以每个 APK 为基础删除日志记录 在编译时。以下示例删除 INFO 下面的所有内容 android.util.Log 的级别日志记录:允许
# This allows proguard to strip isLoggable() blocks containing only <=INFO log # code from release builds. -assumenosideeffects class android.util.Log { static *** i(...); static *** d(...); static *** v(...); static *** isLoggable(...); } -maximumremovedandroidloglevel 4
class
吗?我不认为
cronet
人们会运送这样一个明显损坏的库。
TLDR:cronet-embedded:119.6045.31
似乎需要AGP
8.3+
遗憾的是,我找不到任何关于如何使用 maximumremovedandroidloglevel
指令的更全面的文档,也找不到任何 cronet 或 R8 发行说明。我认为问题在于我们仍然使用 AGP
8.1.3
。我找到了我认为是 AGP 8.1.2 的R8 源代码,看起来解析器期望在解析后开始一个新的选项行
maximumremovedandroidloglevel 1
,这解释了错误消息:
skipWhitespace();
Integer maxRemovedAndroidLogLevel = acceptInteger();
if (maxRemovedAndroidLogLevel != null && maxRemovedAndroidLogLevel >= 1) {
configurationBuilder.joinMaxRemovedAndroidLogLevel(maxRemovedAndroidLogLevel);
} else {
throw parseError("Expected integer greater than or equal to 1", getPosition());
}
}```
next iteration:
```expectChar('-');
...
private void expectChar(char c) throws ProguardRuleParserException {
if (!acceptChar(c)) {
throw parseError("Expected char '" + c + "'");
}
}```
But in [R8 8.3's Parser](https://r8.googlesource.com/r8/+/refs/heads/8.3/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java#484) they now consume the `class` parameter
``` if (parseMaximumRemovedAndroidLogLevelRule(optionStart)) {
return true;
}
...
private boolean parseMaximumRemovedAndroidLogLevelRule(Position start)
throws ProguardRuleParserException {
if (acceptString("maximumremovedandroidloglevel")) {
skipWhitespace();
// First parse the mandatory log level int.
Integer maxRemovedAndroidLogLevel = acceptInteger();
if (maxRemovedAndroidLogLevel == null
|| maxRemovedAndroidLogLevel < MaximumRemovedAndroidLogLevelRule.NONE) {
throw parseError("Expected integer greater than or equal to 1", getPosition());
}
MaximumRemovedAndroidLogLevelRule.Builder builder =
MaximumRemovedAndroidLogLevelRule.builder()
.setMaxRemovedAndroidLogLevel(maxRemovedAndroidLogLevel)
.setOrigin(origin)
.setStart(start);
// Check if we can parse any class annotations or flag.
if (parseClassAnnotationsAndFlags(builder)) {
// Parse the remainder of the class specification.
parseClassSpecFromClassTypeInclusive(builder, false);
} else {
// Otherwise check if we can parse a class name.
parseClassType(
builder,
// Parse the remainder of the class specification.
() -> parseClassSpecFromClassNameInclusive(builder, false),
// In case of an error, move position back to the place we expected an (optional)
// class type.
expectedClassTypeStart -> position = expectedClassTypeStart.getOffsetAsInt());
}
if (builder.hasClassType()) {
Position end = getPosition();
configurationBuilder.addRule(
builder.setEnd(end).setSource(getSourceSnippet(contents, start, end)).build());
} else {
configurationBuilder.joinMaxRemovedAndroidLogLevel(maxRemovedAndroidLogLevel);
}
return true;
}
return false;
}```