32
32
import java .util .concurrent .ConcurrentMap ;
33
33
import kotlin .Unit ;
34
34
import kotlin .jvm .functions .Function1 ;
35
+ import net .bytebuddy .utility .nullability .MaybeNull ;
35
36
import org .gradle .api .Action ;
36
37
import org .gradle .api .GradleException ;
37
38
import org .gradle .api .Plugin ;
@@ -72,7 +73,8 @@ public class ByteBuddyAndroidPlugin implements Plugin<Project> {
72
73
/**
73
74
* The name of the Byte Buddy jar type.
74
75
*/
75
- private static final String BYTE_BUDDY_JAR_TYPE = "bytebuddy-jar" ;
76
+ public static final String BYTE_BUDDY_CLASSES_TYPE = "bytebuddy-classes" ;
77
+ public static final String BYTE_BUDDY_RESOURCES_TYPE = "bytebuddy-resources" ;
76
78
77
79
/*
78
80
* Resolves the dispatcher.
@@ -84,7 +86,7 @@ public class ByteBuddyAndroidPlugin implements Plugin<Project> {
84
86
Class <?> scopedArtifacts = Class .forName ("com.android.build.api.variant.ScopedArtifacts" );
85
87
Class <?> scopedArtifact = Class .forName ("com.android.build.api.artifact.ScopedArtifact" );
86
88
@ SuppressWarnings ("unchecked" )
87
- Object project = Enum .valueOf ((Class ) scope , "PROJECT " );
89
+ Object project = Enum .valueOf ((Class ) scope , "ALL " );
88
90
dispatcher = new TransformationDispatcher .ForApk74CompatibleAndroid (
89
91
Artifacts .class .getMethod ("forScope" , scope ),
90
92
scopedArtifacts .getMethod ("use" , TaskProvider .class ),
@@ -110,7 +112,6 @@ public void apply(Project project) {
110
112
if (currentAgpVersion .compareTo (new AndroidPluginVersion (7 , 2 )) < 0 ) {
111
113
throw new IllegalStateException ("Byte Buddy requires at least Gradle Plugin version 7.2+, but found " + currentAgpVersion );
112
114
}
113
- project .getDependencies ().registerTransform (AarGradleTransformAction .class , new AarGradleTransformAction .ConfigurationAction ());
114
115
project .getDependencies ().getAttributesSchema ().attribute (ARTIFACT_TYPE_ATTRIBUTE , new AttributeMatchingStrategyConfigurationAction ());
115
116
extension .onVariants (extension .selector ().all (), new VariantAction (project , project .getConfigurations ().create ("byteBuddy" , new ConfigurationConfigurationAction ())));
116
117
}
@@ -151,9 +152,26 @@ protected VariantAction(Project project, Configuration configuration) {
151
152
* {@inheritDoc}
152
153
*/
153
154
public void execute (Variant variant ) {
155
+ Configuration configuration = getByteBuddyConfiguration (variant );
156
+
157
+ if (TRANSFORMATION_DISPATCHER instanceof TransformationDispatcher .ForApk74CompatibleAndroid ) {
158
+ TRANSFORMATION_DISPATCHER .accept (project , variant , configuration , null );
159
+ return ;
160
+ }
161
+
162
+ // Legacy api usage.
154
163
Provider <ByteBuddyAndroidService > byteBuddyAndroidServiceProvider = project .getGradle ().getSharedServices ().registerIfAbsent (variant .getName () + "ByteBuddyAndroidService" ,
155
164
ByteBuddyAndroidService .class ,
156
165
new ByteBuddyAndroidService .ConfigurationAction (project .getExtensions ().getByType (BaseExtension .class )));
166
+ FileCollection classPath = RuntimeClassPathResolver .INSTANCE .apply (variant );
167
+ variant .getInstrumentation ().transformClassesWith (ByteBuddyAsmClassVisitorFactory .class , InstrumentationScope .ALL , new ByteBuddyTransformationConfiguration (project ,
168
+ configuration ,
169
+ byteBuddyAndroidServiceProvider ,
170
+ classPath ));
171
+ TRANSFORMATION_DISPATCHER .accept (project , variant , configuration , classPath );
172
+ }
173
+
174
+ private Configuration getByteBuddyConfiguration (Variant variant ) {
157
175
if (variant .getBuildType () == null ) {
158
176
throw new GradleException ("Build type for " + variant + " was null" );
159
177
}
@@ -167,12 +185,7 @@ public void execute(Variant variant) {
167
185
configuration = previous ;
168
186
}
169
187
}
170
- FileCollection classPath = RuntimeClassPathResolver .INSTANCE .apply (variant );
171
- variant .getInstrumentation ().transformClassesWith (ByteBuddyAsmClassVisitorFactory .class , InstrumentationScope .ALL , new ByteBuddyTransformationConfiguration (project ,
172
- configuration ,
173
- byteBuddyAndroidServiceProvider ,
174
- classPath ));
175
- TRANSFORMATION_DISPATCHER .accept (project , variant , configuration , classPath );
188
+ return configuration ;
176
189
}
177
190
}
178
191
@@ -247,9 +260,9 @@ protected OfModernAgp(Method getRuntimeConfiguration) {
247
260
protected FileCollection apply (Variant variant ) {
248
261
try {
249
262
return ((Configuration ) getRuntimeConfiguration .invoke (variant )).getIncoming ()
250
- .artifactView (this )
251
- .getArtifacts ()
252
- .getArtifactFiles ();
263
+ .artifactView (this )
264
+ .getArtifacts ()
265
+ .getArtifactFiles ();
253
266
} catch (IllegalAccessException exception ) {
254
267
throw new IllegalStateException ("Failed to access runtime configuration" , exception );
255
268
} catch (InvocationTargetException exception ) {
@@ -314,7 +327,7 @@ protected ByteBuddyTransformationConfiguration(Project project,
314
327
* {@inheritDoc}
315
328
*/
316
329
public Unit invoke (ByteBuddyInstrumentationParameters parameters ) {
317
- parameters .getByteBuddyClasspath ().from (configuration );
330
+ parameters .getByteBuddyClasspath ().from (getByteBuddyClasspath ( project , configuration ) );
318
331
parameters .getAndroidBootClasspath ().from (project .getExtensions ().getByType (BaseExtension .class ).getBootClasspath ());
319
332
parameters .getRuntimeClasspath ().from (classPath );
320
333
parameters .getByteBuddyService ().set (byteBuddyAndroidServiceProvider );
@@ -396,11 +409,9 @@ protected AttributeContainerConfigurationAction(Project project, String buildTyp
396
409
* {@inheritDoc}
397
410
*/
398
411
public void execute (AttributeContainer attributes ) {
399
- attributes .attribute (ARTIFACT_TYPE_ATTRIBUTE , BYTE_BUDDY_JAR_TYPE );
400
412
attributes .attribute (Category .CATEGORY_ATTRIBUTE , project .getObjects ().named (Category .class , Category .LIBRARY ));
401
413
attributes .attribute (BuildTypeAttr .ATTRIBUTE , project .getObjects ().named (BuildTypeAttr .class , buildType ));
402
414
attributes .attribute (Usage .USAGE_ATTRIBUTE , project .getObjects ().named (Usage .class , Usage .JAVA_RUNTIME ));
403
-
404
415
}
405
416
}
406
417
@@ -413,7 +424,7 @@ protected static class AttributeMatchingStrategyConfigurationAction implements A
413
424
* {@inheritDoc}
414
425
*/
415
426
public void execute (AttributeMatchingStrategy <String > stringAttributeMatchingStrategy ) {
416
- stringAttributeMatchingStrategy .getCompatibilityRules ().add (ByteBuddyJarRule .class );
427
+ stringAttributeMatchingStrategy .getCompatibilityRules ().add (ByteBuddyDependencyRule .class );
417
428
}
418
429
}
419
430
@@ -434,14 +445,22 @@ public void execute(Configuration configuration) {
434
445
/**
435
446
* A rule to check for jar compatibility.
436
447
*/
437
- public abstract static class ByteBuddyJarRule implements AttributeCompatibilityRule <String > {
448
+ public abstract static class ByteBuddyDependencyRule implements AttributeCompatibilityRule <String > {
438
449
439
450
/**
440
451
* {@inheritDoc}
441
452
*/
442
453
public void execute (CompatibilityCheckDetails <String > details ) {
443
- if (BYTE_BUDDY_JAR_TYPE .equals (details .getConsumerValue ()) && "jar" .equals (details .getProducerValue ())) {
444
- details .compatible ();
454
+ if (BYTE_BUDDY_CLASSES_TYPE .equals (details .getConsumerValue ())) {
455
+ String producerValue = details .getProducerValue ();
456
+ if ("java-classes-directory" .equals (producerValue ) || "android-classes-directory" .equals (producerValue )) {
457
+ details .compatible ();
458
+ }
459
+ } else if (BYTE_BUDDY_RESOURCES_TYPE .equals (details .getConsumerValue ())) {
460
+ String producerValue = details .getProducerValue ();
461
+ if ("java-resources-directory" .equals (producerValue ) || "android-java-res" .equals (producerValue )) {
462
+ details .compatible ();
463
+ }
445
464
}
446
465
}
447
466
}
@@ -467,7 +486,7 @@ enum ForLegacyAndroid implements TransformationDispatcher {
467
486
public void accept (Project project , Variant variant , Configuration configuration , FileCollection classPath ) {
468
487
TaskProvider <LegacyByteBuddyLocalClassesEnhancerTask > provider = project .getTasks ().register (variant .getName () + "BytebuddyLocalTransform" ,
469
488
LegacyByteBuddyLocalClassesEnhancerTask .class ,
470
- new LegacyByteBuddyLocalClassesEnhancerTask .ConfigurationAction (configuration , project .getExtensions ().getByType (BaseExtension .class ), classPath ));
489
+ new LegacyByteBuddyLocalClassesEnhancerTask .ConfigurationAction (getByteBuddyClasspath ( project , configuration ) , project .getExtensions ().getByType (BaseExtension .class ), classPath ));
471
490
variant .getArtifacts ()
472
491
.use (provider )
473
492
.wiredWith (GetLocalClassesFunction .INSTANCE , GetOutputDirFunction .INSTANCE )
@@ -562,13 +581,13 @@ protected ForApk74CompatibleAndroid(Method forScope, Method use, Method toTransf
562
581
* {@inheritDoc}
563
582
*/
564
583
public void accept (Project project , Variant variant , Configuration configuration , FileCollection classPath ) {
565
- TaskProvider <ByteBuddyLocalClassesEnhancerTask > provider = project .getTasks ().register (variant .getName () + "BytebuddyLocalTransform " ,
584
+ TaskProvider <ByteBuddyLocalClassesEnhancerTask > provider = project .getTasks ().register (variant .getName () + "BytebuddyTransform " ,
566
585
ByteBuddyLocalClassesEnhancerTask .class ,
567
- new ByteBuddyLocalClassesEnhancerTask .ConfigurationAction (configuration , project .getExtensions ().getByType (BaseExtension .class ), classPath ));
586
+ new ByteBuddyLocalClassesEnhancerTask .ConfigurationAction (getByteBuddyClasspath ( project , configuration ) , project .getExtensions ().getByType (BaseExtension .class )));
568
587
try {
569
588
toTransform .invoke (use .invoke (forScope .invoke (variant .getArtifacts (), scope ), provider ),
570
589
artifact ,
571
- GetLocalJarsFunction .INSTANCE ,
590
+ GetProjectJarsFunction .INSTANCE ,
572
591
GetLocalClassesDirsFunction .INSTANCE ,
573
592
GetOutputFileFunction .INSTANCE );
574
593
} catch (IllegalAccessException exception ) {
@@ -579,9 +598,9 @@ public void accept(Project project, Variant variant, Configuration configuration
579
598
}
580
599
581
600
/**
582
- * A function representation of resolving local jars.
601
+ * A function representation of resolving local and dependencies jars.
583
602
*/
584
- protected enum GetLocalJarsFunction implements Function1 <ByteBuddyLocalClassesEnhancerTask , ListProperty <RegularFile >> {
603
+ protected enum GetProjectJarsFunction implements Function1 <ByteBuddyLocalClassesEnhancerTask , ListProperty <RegularFile >> {
585
604
586
605
/**
587
606
* The singleton instance.
@@ -592,7 +611,7 @@ protected enum GetLocalJarsFunction implements Function1<ByteBuddyLocalClassesEn
592
611
* {@inheritDoc}
593
612
*/
594
613
public ListProperty <RegularFile > invoke (ByteBuddyLocalClassesEnhancerTask task ) {
595
- return task .getLocalJars ();
614
+ return task .getInputJars ();
596
615
}
597
616
}
598
617
@@ -641,6 +660,23 @@ public RegularFileProperty invoke(ByteBuddyLocalClassesEnhancerTask task) {
641
660
* @param configuration The configuration to use.
642
661
* @param classPath The class path to use.
643
662
*/
644
- void accept (Project project , Variant variant , Configuration configuration , FileCollection classPath );
663
+ void accept (Project project , Variant variant , Configuration configuration , @ MaybeNull FileCollection classPath );
664
+ }
665
+
666
+ /**
667
+ * For external dependencies, it provides their JAR files. For local project's dependencies, it provides their local
668
+ * build dirs for both classes and resources. The latter allows for faster and more reliable (up-to-date) compilation processes
669
+ * when using local plugins.
670
+ */
671
+ private static FileCollection getByteBuddyClasspath (Project project , Configuration byteBuddyConfiguration ) {
672
+ FileCollection resources = byteBuddyConfiguration .getIncoming ().artifactView (viewConfiguration -> {
673
+ viewConfiguration .lenient (false );
674
+ viewConfiguration .getAttributes ().attribute (ARTIFACT_TYPE_ATTRIBUTE , BYTE_BUDDY_RESOURCES_TYPE );
675
+ }).getFiles ();
676
+ FileCollection classes = byteBuddyConfiguration .getIncoming ().artifactView (viewConfiguration -> {
677
+ viewConfiguration .lenient (false );
678
+ viewConfiguration .getAttributes ().attribute (ARTIFACT_TYPE_ATTRIBUTE , BYTE_BUDDY_CLASSES_TYPE );
679
+ }).getFiles ();
680
+ return project .files (classes , resources );
645
681
}
646
682
}
0 commit comments