Skip to content

Replace ProGuard with R8 for Android shrinking - #1028

Open
AGulev wants to merge 8 commits into
devfrom
r8
Open

Replace ProGuard with R8 for Android shrinking#1028
AGulev wants to merge 8 commits into
devfrom
r8

Conversation

@AGulev

@AGulev AGulev commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Android builds can now use R8 for code shrinking and obfuscation, replacing the legacy ProGuard path. R8 preserves Android entry points, extension APIs, dependency consumer rules, and ServiceLoader metadata while producing a mapping file for deobfuscation. Builds without _app/app.keep continue to use D8 without shrinking.

Fix #566

Technical changes

  • Adds a dedicated R8 pipeline with bounded rule processing, generated keep rules for unconfigured extensions, version-targeted dependency rules, rewritten META-INF metadata, dex output, and mapping.txt.
  • Generates AAPT keep rules for manifest and resource entry points and combines them with application, extension, JAR, and AAR consumer rules.
  • Pins R8 8.13.19 in the Android build environment, exposes its path and version through SDK configuration, removes the ProGuard installation, and replaces DM_DEBUG_DISABLE_PROGUARD with DM_DEBUG_DISABLE_R8.
  • Reworks Gradle dependency resolution into one invocation that resolves releaseRuntimeClasspath, writes dependency locks and the dependency tree, and emits a deterministic JSON artifact manifest. Gradle is skipped entirely when no dependencies are declared.
  • Uses AGP artifact transforms to obtain EXPLODED_AAR directories and Jetifier-aware PROCESSED_JAR artifacts. Standalone JARs remain unprocessed when Jetifier is disabled, while android.useAndroidX stays enabled independently of transformation.
  • Removes Extender’s custom .gradle/unpacked cache and its extra copy/unpack pass. Artifact paths are canonicalized, validated, deduplicated, and consumed directly from the shared immutable Gradle/AGP cache, reducing duplicate cache storage and filesystem work.
  • Supports both traditional exploded AARs and AGP cache layouts, including jars/classes.jar, jars/libs, resources, assets, JNI libraries, manifests, and consumer rules.
  • Preserves legacy Maven resource package names while using collision-safe internal directories for artifacts with identical filenames from different components.
  • Keeps D8 as the non-shrinking fallback. Legacy _app/app.pro files no longer invoke ProGuard, and the R8 path targets Defold’s API 21+ platform baseline.
  • Adds unit and regression coverage for R8 rule selection and safety limits, AAR/JAR layouts, lambdas, ServiceLoader rewriting, Gradle artifact manifests, resource naming, and end-to-end AAR plus classifier-JAR handoff with Jetifier enabled and disabled.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ff65681b52

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/src/main/java/com/defold/extender/Extender.java
@ekharkunov
ekharkunov self-requested a review August 19, 2026 14:50
@github-actions

github-actions Bot commented Aug 19, 2026

Copy link
Copy Markdown

Summary - Extender code coverage report

Summary
Generated on: 08/28/2026 - 11:04:24
Coverage date: 08/28/2026 - 11:03:54
Parser: JaCoCo
Assemblies: 14
Classes: 93
Files: 93
Line coverage: 49.5% (3513 of 7083)
Covered lines: 3513
Uncovered lines: 3570
Coverable lines: 7083
Total lines: 14482
Branch coverage: 51.3% (1527 of 2971)
Covered branches: 1527
Total branches: 2971
Method coverage: Feature is only available for sponsors
Tag: 240_33165636752

Coverage

com/defold/extender - 43.3%
Name Line Branch
com/defold/extender 43.3% 49.4%
com/defold/extender/AppManifestConfiguration 100%
com/defold/extender/AppManifestPlatformConfig 100%
com/defold/extender/AsyncBuilder 0% 0%
com/defold/extender/BuilderConstants 80%
com/defold/extender/BuildProgressController 93.1% 91.6%
com/defold/extender/Configuration 100%
com/defold/extender/Extender 15% 15.5%
com/defold/extender/ExtenderApplication 0%
com/defold/extender/ExtenderBuildState 62.5% 57.1%
com/defold/extender/ExtenderConst 0%
com/defold/extender/ExtenderController 16.9% 21.4%
com/defold/extender/ExtenderException 100%
com/defold/extender/ExtenderUtil 70.5% 61.6%
com/defold/extender/ExtenderYamlSafeConstructor 100%
com/defold/extender/ExtensionManifestValidator 94.6% 86.3%
com/defold/extender/ManifestConfiguration 100%
com/defold/extender/ManifestPlatformConfig 100%
com/defold/extender/PlatformConfig 100%
com/defold/extender/PlatformNotSupportedException 0%
com/defold/extender/R8Builder 87.5% 76.8%
com/defold/extender/R8Configuration 93.5% 50%
com/defold/extender/R8RulePolicy 76% 70.4%
com/defold/extender/SandboxedPath 72.5% 71.4%
com/defold/extender/TemplateExecutor 39.1% 50%
com/defold/extender/Timer 100%
com/defold/extender/TreePrinter 0% 0%
com/defold/extender/Version 0%
com/defold/extender/VersionNotSupportedException 0%
com/defold/extender/WebSecurityConfig 0% 0%
com/defold/extender/WhitelistConfig 100%
com/defold/extender/ZipUtils 80.3% 69.2%
com/defold/extender/builders - 0%
Name Line Branch
com/defold/extender/builders 0% 0%
com/defold/extender/builders/CSharpBuilder 0% 0%
com/defold/extender/cache - 33.3%
Name Line Branch
com/defold/extender/cache 33.3% 16.6%
com/defold/extender/cache/CacheEntry 64.7% 75%
com/defold/extender/cache/CacheKeyGenerator 81.8% 100%
com/defold/extender/cache/DataCache
com/defold/extender/cache/DataCacheFactory 5% 0%
com/defold/extender/cache/DummyDataCache 80%
com/defold/extender/cache/GCPDataCache 0% 0%
com/defold/extender/cache/LocalDiskDataCache 64.7% 16.6%
com/defold/extender/cache/info - 100%
Name Line Branch
com/defold/extender/cache/info 100% ****
com/defold/extender/cache/info/CacheInfoFileParser 100%
com/defold/extender/cache/info/CacheInfoFileWriter 100%
com/defold/extender/cache/info/CacheInfoWrapper 100%
com/defold/extender/log - 14.2%
Name Line Branch
com/defold/extender/log 14.2% 0%
com/defold/extender/log/ExtenderLogEnhancer 0% 0%
com/defold/extender/log/ExtenderLogEnhancerConfiguration 0% 0%
com/defold/extender/log/Markers 80%
com/defold/extender/metrics - 38.8%
Name Line Branch
com/defold/extender/metrics 38.8% ****
com/defold/extender/metrics/MetricsWriter 38.8%
com/defold/extender/process - 73.4%
Name Line Branch
com/defold/extender/process 73.4% 75.4%
com/defold/extender/process/CommandLineTokenizer 97.7% 89.7%
com/defold/extender/process/ProcessExecutor 64.3% 61.1%
com/defold/extender/process/ProcessUtils 0% 0%
com/defold/extender/progress - 90.6%
Name Line Branch
com/defold/extender/progress 90.6% 81.6%
com/defold/extender/progress/BuildProgressEvent 100%
com/defold/extender/progress/BuildProgressService 90.2% 80.5%
com/defold/extender/progress/BuildStage 100% 100%
com/defold/extender/progress/ProgressReporter 40%
com/defold/extender/remote - 89%
Name Line Branch
com/defold/extender/remote 89% 67.2%
com/defold/extender/remote/RemoteBuildException 100%
com/defold/extender/remote/RemoteEngineBuilder 93.3% 71.8%
com/defold/extender/remote/RemoteHostConfiguration 100%
com/defold/extender/remote/RemoteInstanceConfig 100%
com/defold/extender/remote/RemoteProgressRelay 76.7% 60.8%
com/defold/extender/services - 58.8%
Name Line Branch
com/defold/extender/services 58.8% 47.2%
com/defold/extender/services/DataCacheService 79.8% 61.9%
com/defold/extender/services/DefoldSdkService 75.5% 61%
com/defold/extender/services/DefoldSdkServiceConfiguration
com/defold/extender/services/GCPInstanceService 1.1% 0%
com/defold/extender/services/GradleArtifact 100%
com/defold/extender/services/GradleService 0%
com/defold/extender/services/GradleServiceInterface
com/defold/extender/services/HealthReporterService 82.4% 55.2%
com/defold/extender/services/MockGradleService 0%
com/defold/extender/services/RealGradleService 55.9% 40%
com/defold/extender/services/UserUpdateService 0% 0%
com/defold/extender/services/cocoapods - 51.9%
Name Line Branch
com/defold/extender/services/cocoapods 51.9% 56.6%
com/defold/extender/services/cocoapods/CocoaPodsService 9.4% 20.6%
com/defold/extender/services/cocoapods/CocoaPodsServiceBuildState 16.6% 0%
com/defold/extender/services/cocoapods/CreateBuildSpecArgs 60.7%
com/defold/extender/services/cocoapods/IConfigParser
com/defold/extender/services/cocoapods/LanguageSet 66.6% 50%
com/defold/extender/services/cocoapods/MainPodfile 20%
com/defold/extender/services/cocoapods/PlatformAndLanguageSet 0% 0%
com/defold/extender/services/cocoapods/PlatformSet 0% 0%
com/defold/extender/services/cocoapods/PlistBuddyWrapper 0% 0%
com/defold/extender/services/cocoapods/PodBuildSpec 81.4% 65.4%
com/defold/extender/services/cocoapods/PodfileParser 94.9% 82.2%
com/defold/extender/services/cocoapods/PodfileParsingException 100%
com/defold/extender/services/cocoapods/PodSpec 60.4% 40%
com/defold/extender/services/cocoapods/PodSpecParser 89.5% 79.1%
com/defold/extender/services/cocoapods/PodUtils 63% 51.4%
com/defold/extender/services/cocoapods/ResolvedPods 52.7% 45.6%
com/defold/extender/services/cocoapods/XCConfigParser 94.5% 85.2%
com/defold/extender/services/data - 80.7%
Name Line Branch
com/defold/extender/services/data 80.7% 75%
com/defold/extender/services/data/DefoldSdk 87.5% 75%
com/defold/extender/services/data/GCPInstanceState 0%
com/defold/extender/tracing - 21.8%
Name Line Branch
com/defold/extender/tracing 21.8% 25%
com/defold/extender/tracing/ExtenderExecutor 0% 0%
com/defold/extender/tracing/ExtenderTracerInterceptor 100% 100%
com/defold/extender/tracing/TraceIdInResponseServletFilter 0% 0%
com/defold/extender/utils - 0%
Name Line Branch
com/defold/extender/utils 0% 0%
com/defold/extender/utils/FrameworkUtil 0% 0%
com/defold/extender/utils/PodBuildUtil 0% 0%

@AGulev

AGulev commented Aug 19, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ffdf7fd5e5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/test-data/sdk/a/defoldsdk/extender/build.yml

@ekharkunov ekharkunov left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall good. See comments and suggestions

File artifact = new File((String) pathValue).getCanonicalFile();
GradleArtifact.Kind artifactKind;
String resourcePackageName = null;
if ("exploded-aar".equals(kind)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it worth to make strings as constants?

Comment thread server/src/main/java/com/defold/extender/ExtenderUtil.java
private static final String JAR_R8_RULE_PREFIX = "META-INF/com.android.tools/r8";
private static final String GENERATED_EXTENSION_KEEP_ATTRIBUTES =
"-keepattributes *Annotation*,Signature,InnerClasses,EnclosingMethod,MethodParameters,Exceptions";
static final int MAX_GENERATED_EXTENSION_CLASSES = 32 * 1024;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's worth to move parameters to config file. In case if we need change it in production it's easier and faster change configs instead of rebuilding and redeploying jar

Comment thread server/src/main/java/com/defold/extender/Extender.java
if (k.equals("PROGUARD")) {
continue;
}
boolean r8Environment = k.equals("R8") || k.equals("R8_VERSION");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand why we need that code here. If merged app manifests doesn't contain R8-related stuff than we even doesn't hit this. If R8 stuff presented - we will render environment value in any case. What is the purpose of this code?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not needed

return context;
}

Map<String, Object> createR8BuilderContext(Map<String, Object> src) throws ExtenderException {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we need such processing specifically for R8-related environment?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not needed, removed

@AGulev
AGulev requested a review from ekharkunov August 28, 2026 11:03
@AGulev

AGulev commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

I made fixes (if I understood all right), thnak you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Replace Proguard with R8

2 participants