Android new build system (gradle) and aspectj

后端 未结 5 527
再見小時候
再見小時候 2021-01-31 20:30

In Google IO the new build system gradle is announced to replace ant. My project is using aspectj and I would like to use it in my project. I couldn\'t figure out some variabl

5条回答
  •  一生所求
    2021-01-31 21:01

    Although previous answers scripts works for most of the situations, they doesn't cover some of the problems of using Android with AspectJ and Gradle.

    My test was to create a library project that should be used by anyone via mavenCentral or by me as a reference library project, and a test application project. The library project is the one that has all the aspects and the application test was trying to use those aspects. Giving this as a context, the resulting project structure was:

    HEAD-Gradle
    ---LibraryProject
    -------SomeAspects
    ---TestApplication
    -------Uses-SomeAspects
    

    The solutions I found that make it work are:

    1- For library projects you must use

    libraryVariants.all { variant -> 
    

    instead of

    android.applicationVariants.all { variant ->
    

    2- The build dir changed for 19.+ build tools of Android, so as it is suggested in one comment (thanks to "WithoutClass"), you have to use the exploded-aar dir instead of exploded-bundles dir in the tree variable definition. From:

    def tree = fileTree(dir: "${project.buildDir}/exploded-bundles", include: '**/classes.jar')
    

    To:

    def tree = fileTree(dir: "${project.buildDir}/exploded-aar", include: '**/classes.jar')
    

    3- The final problem I faced when making the integration was that if you have a library project, aspects defined on it were not found on the child project. To solve this you have to add the classes.jar of your custom library to the aspectJ compiler configuration. You can achieve this by adding to the dependencies:

    aspects project(":YourLibraryProject")
    

    and it is also needed to make some changes in the script provided in the final of this post.

    Right now the best script I can imagine that gives full support for aspectj using even library projects is:

    For dependencies:

    configurations {
        ajc
        aspects
        ajInpath
    }
    
    //Version of aspectj
    def aspectjVersion = '1.8.+'
    // The dependencies for this project
    dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar'])
        //Your dependencies to a custom library project
        compile project(":YourLibraryProject")
        aspects project(":YourLibraryProject")
        //Aspectj dependencies
        ajc "org.aspectj:aspectjtools:${aspectjVersion}"
        compile "org.aspectj:aspectjrt:${aspectjVersion}"
    }
    

    The compiler running script

    android.applicationVariants.all { variant ->
    
    variant.javaCompile.doLast {
        // Find the android.jar and add to iajc classpath
        def androidSdk = android.adbExe.parent + "/../platforms/" + android.compileSdkVersion + "/android.jar"
    
        def iajcClasspath = androidSdk + ":" + configurations.compile.asPath
        //This line and the fordward assignations allow the aspects support in the child project from the library project
        def customAspectsPath = configurations.aspects.asPath
        configurations.compile.dependencies.each { dep ->
            if(dep.hasProperty("dependencyProject")) {
                iajcClasspath += ":" + dep.dependencyProject.buildDir + "/bundles/${variant.buildType.name}/classes.jar"
                customAspectsPath += ":" + dep.dependencyProject.buildDir + "/bundles/${variant.buildType.name}/classes.jar"
            }
        }
    
        // handle aar dependencies pulled in by gradle (Android support library and etc)
    
        def tree = fileTree(dir: "${project.buildDir}/exploded-aar", include: '**/classes.jar')
        tree.each { jarFile ->
            iajcClasspath += ":" + jarFile
        }
    
        ant.taskdef( resource:"org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties", classpath: configurations.ajc.asPath)
        ant.iajc (
                source:sourceCompatibility,
                target:targetCompatibility,
                destDir:"${project.buildDir}/classes/${variant.dirName}",
                maxmem:"512m",
                fork:"true",
                aspectPath:customAspectsPath,
                inpath:configurations.ajInpath.asPath,
                sourceRootCopyFilter:"**/.svn/*,**/*.java",
                classpath:iajcClasspath
        ){
            sourceroots{
                android.sourceSets.main.java.srcDirs.each{
                    pathelement(location:it.absolutePath)
                }
                pathelement(location:"${project.buildDir}/source/r/${variant.dirName}")
            }
        }
    }
    }
    

    Remember that if you want to run AspectJ on a library-child project, you must have also this script on the build.gradle of the library.

提交回复
热议问题