3232import java .util .concurrent .ConcurrentMap ;
3333import kotlin .Unit ;
3434import kotlin .jvm .functions .Function1 ;
35+ import net .bytebuddy .utility .nullability .MaybeNull ;
3536import org .gradle .api .Action ;
3637import org .gradle .api .GradleException ;
3738import org .gradle .api .Plugin ;
@@ -72,7 +73,8 @@ public class ByteBuddyAndroidPlugin implements Plugin<Project> {
7273 /**
7374 * The name of the Byte Buddy jar type.
7475 */
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" ;
7678
7779 /*
7880 * Resolves the dispatcher.
@@ -84,7 +86,7 @@ public class ByteBuddyAndroidPlugin implements Plugin<Project> {
8486 Class <?> scopedArtifacts = Class .forName ("com.android.build.api.variant.ScopedArtifacts" );
8587 Class <?> scopedArtifact = Class .forName ("com.android.build.api.artifact.ScopedArtifact" );
8688 @ SuppressWarnings ("unchecked" )
87- Object project = Enum .valueOf ((Class ) scope , "PROJECT " );
89+ Object project = Enum .valueOf ((Class ) scope , "ALL " );
8890 dispatcher = new TransformationDispatcher .ForApk74CompatibleAndroid (
8991 Artifacts .class .getMethod ("forScope" , scope ),
9092 scopedArtifacts .getMethod ("use" , TaskProvider .class ),
@@ -110,7 +112,6 @@ public void apply(Project project) {
110112 if (currentAgpVersion .compareTo (new AndroidPluginVersion (7 , 2 )) < 0 ) {
111113 throw new IllegalStateException ("Byte Buddy requires at least Gradle Plugin version 7.2+, but found " + currentAgpVersion );
112114 }
113- project .getDependencies ().registerTransform (AarGradleTransformAction .class , new AarGradleTransformAction .ConfigurationAction ());
114115 project .getDependencies ().getAttributesSchema ().attribute (ARTIFACT_TYPE_ATTRIBUTE , new AttributeMatchingStrategyConfigurationAction ());
115116 extension .onVariants (extension .selector ().all (), new VariantAction (project , project .getConfigurations ().create ("byteBuddy" , new ConfigurationConfigurationAction ())));
116117 }
@@ -151,9 +152,26 @@ protected VariantAction(Project project, Configuration configuration) {
151152 * {@inheritDoc}
152153 */
153154 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.
154163 Provider <ByteBuddyAndroidService > byteBuddyAndroidServiceProvider = project .getGradle ().getSharedServices ().registerIfAbsent (variant .getName () + "ByteBuddyAndroidService" ,
155164 ByteBuddyAndroidService .class ,
156165 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 ) {
157175 if (variant .getBuildType () == null ) {
158176 throw new GradleException ("Build type for " + variant + " was null" );
159177 }
@@ -167,12 +185,7 @@ public void execute(Variant variant) {
167185 configuration = previous ;
168186 }
169187 }
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 ;
176189 }
177190 }
178191
@@ -247,9 +260,9 @@ protected OfModernAgp(Method getRuntimeConfiguration) {
247260 protected FileCollection apply (Variant variant ) {
248261 try {
249262 return ((Configuration ) getRuntimeConfiguration .invoke (variant )).getIncoming ()
250- .artifactView (this )
251- .getArtifacts ()
252- .getArtifactFiles ();
263+ .artifactView (this )
264+ .getArtifacts ()
265+ .getArtifactFiles ();
253266 } catch (IllegalAccessException exception ) {
254267 throw new IllegalStateException ("Failed to access runtime configuration" , exception );
255268 } catch (InvocationTargetException exception ) {
@@ -314,7 +327,7 @@ protected ByteBuddyTransformationConfiguration(Project project,
314327 * {@inheritDoc}
315328 */
316329 public Unit invoke (ByteBuddyInstrumentationParameters parameters ) {
317- parameters .getByteBuddyClasspath ().from (configuration );
330+ parameters .getByteBuddyClasspath ().from (getByteBuddyClasspath ( project , configuration ) );
318331 parameters .getAndroidBootClasspath ().from (project .getExtensions ().getByType (BaseExtension .class ).getBootClasspath ());
319332 parameters .getRuntimeClasspath ().from (classPath );
320333 parameters .getByteBuddyService ().set (byteBuddyAndroidServiceProvider );
@@ -396,11 +409,9 @@ protected AttributeContainerConfigurationAction(Project project, String buildTyp
396409 * {@inheritDoc}
397410 */
398411 public void execute (AttributeContainer attributes ) {
399- attributes .attribute (ARTIFACT_TYPE_ATTRIBUTE , BYTE_BUDDY_JAR_TYPE );
400412 attributes .attribute (Category .CATEGORY_ATTRIBUTE , project .getObjects ().named (Category .class , Category .LIBRARY ));
401413 attributes .attribute (BuildTypeAttr .ATTRIBUTE , project .getObjects ().named (BuildTypeAttr .class , buildType ));
402414 attributes .attribute (Usage .USAGE_ATTRIBUTE , project .getObjects ().named (Usage .class , Usage .JAVA_RUNTIME ));
403-
404415 }
405416 }
406417
@@ -413,7 +424,7 @@ protected static class AttributeMatchingStrategyConfigurationAction implements A
413424 * {@inheritDoc}
414425 */
415426 public void execute (AttributeMatchingStrategy <String > stringAttributeMatchingStrategy ) {
416- stringAttributeMatchingStrategy .getCompatibilityRules ().add (ByteBuddyJarRule .class );
427+ stringAttributeMatchingStrategy .getCompatibilityRules ().add (ByteBuddyDependencyRule .class );
417428 }
418429 }
419430
@@ -434,14 +445,22 @@ public void execute(Configuration configuration) {
434445 /**
435446 * A rule to check for jar compatibility.
436447 */
437- public abstract static class ByteBuddyJarRule implements AttributeCompatibilityRule <String > {
448+ public abstract static class ByteBuddyDependencyRule implements AttributeCompatibilityRule <String > {
438449
439450 /**
440451 * {@inheritDoc}
441452 */
442453 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+ }
445464 }
446465 }
447466 }
@@ -467,7 +486,7 @@ enum ForLegacyAndroid implements TransformationDispatcher {
467486 public void accept (Project project , Variant variant , Configuration configuration , FileCollection classPath ) {
468487 TaskProvider <LegacyByteBuddyLocalClassesEnhancerTask > provider = project .getTasks ().register (variant .getName () + "BytebuddyLocalTransform" ,
469488 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 ));
471490 variant .getArtifacts ()
472491 .use (provider )
473492 .wiredWith (GetLocalClassesFunction .INSTANCE , GetOutputDirFunction .INSTANCE )
@@ -562,13 +581,13 @@ protected ForApk74CompatibleAndroid(Method forScope, Method use, Method toTransf
562581 * {@inheritDoc}
563582 */
564583 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 " ,
566585 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 )));
568587 try {
569588 toTransform .invoke (use .invoke (forScope .invoke (variant .getArtifacts (), scope ), provider ),
570589 artifact ,
571- GetLocalJarsFunction .INSTANCE ,
590+ GetProjectJarsFunction .INSTANCE ,
572591 GetLocalClassesDirsFunction .INSTANCE ,
573592 GetOutputFileFunction .INSTANCE );
574593 } catch (IllegalAccessException exception ) {
@@ -579,9 +598,9 @@ public void accept(Project project, Variant variant, Configuration configuration
579598 }
580599
581600 /**
582- * A function representation of resolving local jars.
601+ * A function representation of resolving local and dependencies jars.
583602 */
584- protected enum GetLocalJarsFunction implements Function1 <ByteBuddyLocalClassesEnhancerTask , ListProperty <RegularFile >> {
603+ protected enum GetProjectJarsFunction implements Function1 <ByteBuddyLocalClassesEnhancerTask , ListProperty <RegularFile >> {
585604
586605 /**
587606 * The singleton instance.
@@ -592,7 +611,7 @@ protected enum GetLocalJarsFunction implements Function1<ByteBuddyLocalClassesEn
592611 * {@inheritDoc}
593612 */
594613 public ListProperty <RegularFile > invoke (ByteBuddyLocalClassesEnhancerTask task ) {
595- return task .getLocalJars ();
614+ return task .getInputJars ();
596615 }
597616 }
598617
@@ -641,6 +660,23 @@ public RegularFileProperty invoke(ByteBuddyLocalClassesEnhancerTask task) {
641660 * @param configuration The configuration to use.
642661 * @param classPath The class path to use.
643662 */
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 );
645681 }
646682}
0 commit comments