@@ -507,13 +507,16 @@ public static RuleConfiguredTargetBuilder createAndroidBinary(
507507 boolean postprocessingRewritesMap = androidSemantics .postprocessClassesRewritesMap (ruleContext );
508508 boolean desugarJava8LibsGeneratesMap =
509509 AndroidCommon .getAndroidConfig (ruleContext ).desugarJava8Libs ();
510+ boolean optimizingDexing = ruleContext .getExecutablePrerequisite (":optimizing_dexer" ) != null ;
510511 if (generateProguardMap ) {
511512 // Determine the output of the Proguard map from shrinking the app. This depends on the
512513 // additional steps which can process the map before the final Proguard map artifact is
513514 // generated.
514515 if (!hasProguardSpecs && !postprocessingRewritesMap ) {
515516 // When no shrinking happens a generating rule for the output map artifact is still needed.
516517 proguardOutputMap = androidSemantics .getProguardOutputMap (ruleContext );
518+ } else if (optimizingDexing ) {
519+ proguardOutputMap = ProguardHelper .getProguardTempArtifact (ruleContext , "pre_dexing.map" );
517520 } else if (postprocessingRewritesMap ) {
518521 // Proguard map from shrinking goes to postprocessing.
519522 proguardOutputMap =
@@ -545,13 +548,13 @@ public static RuleConfiguredTargetBuilder createAndroidBinary(
545548 if (proguardOutput .hasMapping ()) {
546549 // Determine the Proguard map artifacts for the additional steps (if any) if shrinking of
547550 // the app is enabled.
548- if (postprocessingRewritesMap && desugarJava8LibsGeneratesMap ) {
551+ if (( optimizingDexing || postprocessingRewritesMap ) && desugarJava8LibsGeneratesMap ) {
549552 // Proguard map from preprocessing will be merged with Proguard map for desugared
550553 // library.
551554 postProcessingOutputMap =
552555 getDxArtifact (ruleContext , "_proguard_output_for_desugared_library.map" );
553556 finalProguardOutputMap = androidSemantics .getProguardOutputMap (ruleContext );
554- } else if (postprocessingRewritesMap ) {
557+ } else if (optimizingDexing || postprocessingRewritesMap ) {
555558 // No desugared library, Proguard map from preprocessing is the final Proguard map.
556559 postProcessingOutputMap = androidSemantics .getProguardOutputMap (ruleContext );
557560 finalProguardOutputMap = postProcessingOutputMap ;
@@ -592,7 +595,10 @@ public static RuleConfiguredTargetBuilder createAndroidBinary(
592595 resourceApk .getMainDexProguardConfig (),
593596 resourceClasses ,
594597 derivedJarFunction ,
595- proguardOutputMap );
598+ proguardOutputMap ,
599+ postProcessingOutputMap ,
600+ proguardOutput .getLibraryJar (),
601+ !proguardSpecs .isEmpty ());
596602
597603 DexPostprocessingOutput dexPostprocessingOutput =
598604 androidSemantics .postprocessClassesDexZip (
@@ -1120,11 +1126,12 @@ private static ProguardOutput createEmptyProguardAction(
11201126 ProguardOutput outputs =
11211127 ProguardHelper .getProguardOutputs (
11221128 proguardOutputJar ,
1123- /*proguardSeeds=*/ null ,
1124- /*proguardUsage=*/ null ,
1129+ /* proguardSeeds= */ null ,
1130+ /* proguardUsage= */ null ,
11251131 ruleContext ,
11261132 semantics ,
1127- proguardOutputMap );
1133+ proguardOutputMap ,
1134+ null );
11281135 outputs .addAllToSet (failures );
11291136 ruleContext .registerAction (
11301137 new FailAction (
@@ -1318,8 +1325,12 @@ private static DexingOutput dex(
13181325 @ Nullable Artifact mainDexProguardSpec ,
13191326 JavaTargetAttributes attributes ,
13201327 Function <Artifact , Artifact > derivedJarFunction ,
1321- @ Nullable Artifact proguardOutputMap )
1328+ @ Nullable Artifact proguardOutputMap ,
1329+ @ Nullable Artifact postProcessingOutputMap ,
1330+ @ Nullable Artifact libraryJar ,
1331+ boolean isOptimizedBuild )
13221332 throws InterruptedException , RuleErrorException {
1333+ FilesToRunProvider optimizingDexer = ruleContext .getExecutablePrerequisite (":optimizing_dexer" );
13231334 List <String > dexopts = ruleContext .getExpander ().withDataLocations ().tokenized ("dexopts" );
13241335 MultidexMode multidexMode = getMultidexMode (ruleContext );
13251336 if (!supportsMultidexMode (ruleContext , multidexMode )) {
@@ -1370,7 +1381,55 @@ private static DexingOutput dex(
13701381 }
13711382
13721383 Artifact classesDex = getDxArtifact (ruleContext , "classes.dex.zip" );
1373- if (dexShards > 1 ) {
1384+ if (optimizingDexer != null && isOptimizedBuild ) {
1385+ SpawnAction .Builder dexAction =
1386+ new SpawnAction .Builder ()
1387+ .useDefaultShellEnvironment ()
1388+ .setExecutable (optimizingDexer )
1389+ .setProgressMessage ("Optimized dexing for %{label}" )
1390+ .setMnemonic ("OptimizingDex" )
1391+ .addInput (proguardedJar )
1392+ .addOutput (classesDex );
1393+
1394+ boolean nativeMultidex = multidexMode == MultidexMode .NATIVE ;
1395+ CustomCommandLine .Builder dexCommand =
1396+ CustomCommandLine .builder ()
1397+ .addExecPath (proguardedJar )
1398+ .add ("--release" )
1399+ .add ("--no-desugaring" )
1400+ .addExecPath ("--output" , classesDex )
1401+ .addAll (dexopts );
1402+
1403+ if (proguardOutputMap != null ) {
1404+ dexAction .addInput (proguardOutputMap ).addOutput (postProcessingOutputMap );
1405+ dexCommand
1406+ .addExecPath ("--pg-map" , proguardOutputMap )
1407+ .addExecPath ("--pg-map-output" , postProcessingOutputMap );
1408+ }
1409+
1410+ // TODO(b/261110876): Pass min SDK through here based on the value in the merged manifest. The
1411+ // current value is statically defined for the entire depot.
1412+ // We currently set the minimum SDK version to 21 if you are doing native multidex as that is
1413+ // required for native multidex to work in the first place and as a result is required for
1414+ // correct behavior from the dexer.
1415+ int sdk = nativeMultidex ? Math .max (21 , minSdkVersion ) : minSdkVersion ;
1416+ if (sdk != 0 ) {
1417+ dexCommand .add ("--min-api" , Integer .toString (sdk ));
1418+ }
1419+ if (mainDexList != null ) {
1420+ dexCommand .addExecPath ("--main-dex-list" , mainDexList );
1421+ dexAction .addInput (mainDexList );
1422+ }
1423+ if (libraryJar != null ) {
1424+ dexCommand .addExecPath ("--lib" , libraryJar );
1425+ dexAction .addInput (libraryJar );
1426+ }
1427+
1428+ dexAction .addCommandLine (dexCommand .build ());
1429+ ruleContext .registerAction (dexAction .build (ruleContext ));
1430+ return new DexingOutput (
1431+ classesDex , javaResourceSourceJar , ImmutableList .of (classesDex ), mainDexList );
1432+ } else if (dexShards > 1 ) {
13741433 ImmutableList <Artifact > shards =
13751434 makeShardArtifacts (ruleContext , dexShards , usesDexArchives ? ".jar.dex.zip" : ".jar" );
13761435
0 commit comments