Gradle - selective module compilation (reuse jar otherwise)
Asked Answered
M

2

16

I am using a lot of modules in my project (local and online ones, >20 most of the time) and I can say that normally non of them must be checked nor recompiled. I could include them all as .jar files which would speed up build time but I would prefer following:

  • setup something where I define that gradle should build a .jar for all my modules and reuse them
  • if needed I just disable this setup and build my project (perfectly a clean build would do that)
  • I want to be able to edit my modules in the project, that's why I don't want to include them directly as .jar files.

I want faster build times but I do not want to have to build the .jar files and add them manually to my project.

Any ideas on how and if this is possible? Can I realise that via some setup or via a gradle task or similar?

Maggiore answered 3/11, 2016 at 6:44 Comment(8)
Is it only pure java libraries or will you pull in android libraries as well?Henigman
mostly android libraries...Maggiore
So actually mostly .aar files?Henigman
It depends... Not always, but .aar becoming more and more popular. I'm glad to get any tipp, even if it only solves part of the problemMaggiore
That's not really fun. The only thing I know doing something like it is github.com/adwiv/android-fat-aar. But I don't have experience with it.Henigman
That looks interesting. ThanksMaggiore
@Maggiore I provided some part of solution, but still working on it. Anyway this is interesting question, because we can you this solution, for our projects too)Arenas
Why?!. Do not reinvent the wheel. Gradle already handles most of what you're asking. External jars are downloaded and cached locally, and if they do not change, they are not fetched again. (you can force a redownload when needed with --refresh-dependencies) Local project are not rebuilt if their source does not change. The behavior you're asking for is already built into gradle dependency management and caching. What in gradle's default behavior is insufficient for your needs?Lear
A
6

Let me think about verification libraries, which is exist in .jar and which we should download. In other case, you can provide several type of product flavors. And after this just select Build Flavors for your work.

productFlavors {
        fastDebug {
            applicationIdSuffix ".jar"
        }
        regularDegub {
            applicationIdSuffix ".regular"
        }
        ....
        // Other Configuration
    }

dependencies {
    ...
    // Jar Debug by adding only Jar
    fastDegubCompile fileTree(dir: 'libs', include: '*.jar')
    fastDegubCompile 'com.android.support:support-v4:23.1.1'

    ...
    // Regular Debug with downloading all libraries
    // Including only specific from project files
    regularDegubCompile 'com.squareup.picasso:picasso:2.5.2'
    regularDegubCompile 'com.android.support:support-v4:23.1.1'
    regularDegubCompile files('libs/specific1.jar', 'libs/specific2.jar')

} 

| UPDATE |

So after some workaround, I see that Gradle gathering libraries into some cache, where i can see source. But I still searching to way of correct verification libraries with project configuration.

For now i wrote script for gathering Files from Gradle cache location. And copying them into new location, where we can use build flavors,. This works really quick (less that 7 seconds for 200 libraries), but still need improvements (see above).

if I do not have time, for the next update, please, fill free to extend solution. Thanks for understanding.

// Task for calling from Gradle Scripts
// -----------------------------------

task gatheringJarFilesTask << {
    println("Gathering Jars Start...")
    gatheringJarFiles(gradleCacheLocation, foundedJarsList)
    println("------------------------------")
    println("Gathering Jars End! Start copying!")
    copyFiles(projectJarsLocation, foundedJarsList)

}


// Constants, which might be optimized too
// -----------------------------------

def gradleCacheLocation = '/home/kasyangenka/.gradle/caches/modules-2/files-2.1'
def projectJarsLocation = '/home/kasyangenka/Projects/GradleScriptsTest/app/libs'
List<String> foundedJarsList = []

// Main Script Methods
// -----------------------------------

def gatheringJarFiles(baseDirPath, gatheredList) {
    new File(baseDirPath).eachFile {file ->
        println("-> Current file: " + file.getName())
        if (file.isDirectory()) {
            gatheringJarFiles(file.getAbsolutePath(), gatheredList)
        }
        def containsLib = (file.getName().contains(".jar")
                || file.getName().contains(".aar"));

        if (containsLib)  {
            println("->> Adding Jar file: " + file.getAbsolutePath())
            gatheredList.add(file.getAbsolutePath())
        }
    }
}

def copyFiles (destiny, List sourceList) {
    sourceList.each {filePath ->
        copy {
            from filePath
            into destiny
        }
    }
}
Arenas answered 10/11, 2016 at 14:54 Comment(4)
This would mean, I would have to manually create the jars once and put them into the libs folder, correct? Is that your suggestion? And then I can decide to use the jars via fastDegubCompile or to get the up-to-date versions of my dependencies via regularDegubCompileMaggiore
@Maggiore Yes, as you described in question.Arenas
I wanted to be able to create the jars direclty via a gradle script not to just use jars... Maybe you have an idea for that as well?Maggiore
@Maggiore So yeah, now I see, I think i will write and update gradle task for this. Thanks.Arenas
A
3

I think the Continuous build feature introduced from Gradle 2.5 is trying to fix the problem what you meet, though it's not exactly what you need. Pass -t or --continuous to gradlew command to use it, following is the description for -t option.

-t, --continuous        Enables continuous build. Gradle does not exit and will re-execute tasks when task file inputs change. [incubating]

And quoted from the document:

Gradle's incremental build support ensures that only the tasks that are actually affected by the change are executed.

See: https://docs.gradle.org/current/userguide/continuous_build.html

Alsatian answered 11/11, 2016 at 13:48 Comment(5)
I was thinking that android studio supports gradle 2.14.1 only currently, but I was wrong. It supports >= 2.14.1 with the current gradle plugin 2.2.0. Do youn know where I can deifne gradlew parameters in android studio? I only know where to pass in gradle paramters...Maggiore
@Maggiore You can define it from Preferences->Build,Execution,Deployment->Compiler->Command line OptionsAlsatian
Aren't those flags for the gradle command and not for the gradlew command?Maggiore
@Maggiore I don't know your OS, but for me, on Mac, there is no gradle command, just gradlew command, whatever the name, it's the command used to build.Alsatian
I have a quite complex project with many sub modules, tried this with gradle 3.1 and I've seen a few endless rebuilds sadly... Seems like this is not working correctly. Additionally, I don't want to have constant rebuilds although if the rebuild is done on a thread and is as fast as I'm programming without disturbing my programming, this would be an alternative solutionMaggiore

© 2022 - 2024 — McMap. All rights reserved.