blob: fd54ac77f194e25399f3a56c0e60c78373634bea [file] [log] [blame]
// Copyright (c) 2024, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8;
import com.android.tools.r8.keepanno.annotations.KeepForApi;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.EmbeddedRulesExtractor;
import com.android.tools.r8.utils.ExceptionDiagnostic;
import com.android.tools.r8.utils.ExceptionUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.SemanticVersion;
import com.android.tools.r8.utils.SemanticVersionUtils;
import com.android.tools.r8.utils.StringUtils;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.function.Supplier;
@KeepForApi
public class ExtractR8Rules {
private static void run(
AndroidApp app,
StringConsumer consumer,
boolean includeOriginComments,
SemanticVersion compilerVersion,
Reporter reporter) {
Supplier<SemanticVersion> semanticVersionSupplier =
SemanticVersionUtils.compilerVersionSemanticVersionSupplier(
compilerVersion,
"Using an artificial version newer than any known version for selecting"
+ " Proguard configurations embedded under META-INF/. This means that"
+ " all rules with a '-upto-' qualifier will be excluded and all"
+ " rules with a -from- qualifier will be included.",
reporter);
for (ProgramResourceProvider provider : app.getProgramResourceProviders()) {
DataResourceProvider dataResourceProvider = provider.getDataResourceProvider();
if (dataResourceProvider == null) {
return;
}
try {
EmbeddedRulesExtractor embeddedProguardConfigurationVisitor =
new EmbeddedRulesExtractor(reporter, semanticVersionSupplier);
dataResourceProvider.accept(embeddedProguardConfigurationVisitor);
embeddedProguardConfigurationVisitor.visitRelevantRules(
rules -> {
try {
if (includeOriginComments) {
consumer.accept("# Rules extracted from:", reporter);
consumer.accept(StringUtils.LINE_SEPARATOR, reporter);
consumer.accept("# ", reporter);
consumer.accept(rules.getOrigin().toString(), reporter);
consumer.accept(StringUtils.LINE_SEPARATOR, reporter);
}
consumer.accept(rules.get(), reporter);
consumer.accept(StringUtils.LINE_SEPARATOR, reporter);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
});
} catch (ResourceException e) {
reporter.error(new ExceptionDiagnostic(e));
}
}
consumer.finished(reporter);
}
/** Experimental API to extract embedded rules from libraries. */
public static void run(ExtractR8RulesCommand command) throws CompilationFailedException {
AndroidApp app = command.getInputApp();
StringConsumer rulesConsumer = command.getRulesConsumer();
boolean includeOriginComments = command.getIncludeOriginComments();
SemanticVersion compilerVersion = command.getCompilerVersion();
InternalOptions options = command.getInternalOptions();
ExceptionUtils.withCompilationHandler(
options.reporter,
() -> {
run(app, rulesConsumer, includeOriginComments, compilerVersion, options.reporter);
});
}
public static void main(String[] args) throws CompilationFailedException {
ExtractR8RulesCommand.Builder builder = ExtractR8RulesCommand.parse(args);
ExtractR8RulesCommand command = builder.build();
if (command.isPrintHelp()) {
System.out.println(ExtractR8RulesCommand.USAGE_MESSAGE);
return;
}
if (command.isPrintVersion()) {
System.out.println("ExtractR8Rules " + Version.LABEL);
return;
}
run(command);
}
}