Exclude aidl files from Javadoc task with Gradle - android

I'm currently discovering Android Studio and Gradle and migrating all the build chain of my project from bash scripts to Gradle configurations. It's probably going to be awesome in the end, but meanwhile I'm struggling.
What I want to do now is quite simple. I have a standard rule to generate Javadoc from my source (I took this snippet from http://snowdream.github.io/blog/android/2013/11/01/how-to-generate-javadocs-with-android-gradle-plugin/):
android.libraryVariants.all { variant ->
task("generate${variant.name.capitalize()}Javadoc", type: Javadoc) {
source = variant.javaCompile.source
def androidJar = "${android.sdkDirectory}/platforms/${android.compileSdkVersion}/android.jar"
classpath = files(variant.javaCompile.classpath.files, androidJar)
options {
links "http://docs.oracle.com/javase/7/docs/api/"
linksOffline "http://d.android.com/reference","${android.sdkDirectory}/docs/reference"
}
exclude '**/BuildConfig.java'
exclude '**/R.java'
}
}
But my project also contains AIDL files and I don't want these aidl files (nor the .java files generated from them) to be included to the Javadoc.
I tried the rule:
exclude "**/$buildDir/**"
... and I tried a thousand others, but none works and my interfaces and Stub are processed into HTML files.
I beg for your help! Thanks a lot.

After hours of research about how Gradle and Groovy work, the best way I found is:
exclude {
it.file.path.contains('aidl')
}
However, I'm still unsatisfied. I do feel something less brutal could be done using variant.aidlCompile.sourceOutputDir that points to the Java files generated by AIDL. But I could not compare the iterated elements in the Closure to this File, or FileTree, or whatever shape I give it...
EDIT:
After further research, another method is to hide the interfaces defined in AIDL using a custom Doclet that supports #hide tag (like Doclava). I preferred this method because it doesn't cause errors during Javadoc generation.

Related

How to exclude a Kotlin file? [duplicate]

With Java, we are excluding like this:
java {
srcDir 'src'
exclude '**/myTests/**'
}
I want to make the same thing with Kotlin.
I am trying to find some documentation on this in official documentation configuring Kotlin, but without any success.
What I've expected and already tried (and of course without any success):
kotlin {
srcDir 'src'
exclude '**/myTests/*.kt'
}
java {
srcDir 'src'
exclude '**/myTests/*.kt'
}
There isn't any Kotlin related configuration.
Why I am saying this: I have all the Kotlin files into the kotlin directory and Java files into java directory. But while configuring, I have added:
sourceSets {
main.java.srcDirs += "src/main/kotlin"
}
This means that with src/main/java, add source files from src/main/kotlin also while compiling.
This should solve your issue.
Android (likely need improvement, seems flaky):
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile.class).configureEach {
it.exclude('**/TestExcludeKotlinClass.kt')
}
If you use a Kotlin Gradle project, try this:
tasks.withType<KotlinCompile> {
exclude("**/packageToExlude/**")}
In my case, a non-Android project.
I came across a way to make this work specifically for Android unit tests (but I'm assuming it's adaptable) using a combination of other solutions here:
def filesToExclude = [
'**/*TestOne*.kt',
'**/*TestTwo*.kt',
...
]
tasks.withType(org.gradle.api.tasks.SourceTask.class).configureEach {
it.exclude(filesToExclude)
}
android.sourceSets.test.kotlin.exclude(filesToExclude)
In my particular case, the extra wildcards around the test name were needed due to other generation occurring (specifically, Dagger with kapt).
This seems to be a bit hacky way to approach it, but it works by ensuring the test target is excluded from all tasks that it could actually be excluded from (including both build & kapt tasks). The sourceSets exclusion is still necessary for the file not to be picked up for compilation (I think this is the Kotlin Gradle Plugin doing it, but it might also be the Android Gradle Plugin).

How to exclude Kotlin files from compiling with Gradle

With Java, we are excluding like this:
java {
srcDir 'src'
exclude '**/myTests/**'
}
I want to make the same thing with Kotlin.
I am trying to find some documentation on this in official documentation configuring Kotlin, but without any success.
What I've expected and already tried (and of course without any success):
kotlin {
srcDir 'src'
exclude '**/myTests/*.kt'
}
java {
srcDir 'src'
exclude '**/myTests/*.kt'
}
There isn't any Kotlin related configuration.
Why I am saying this: I have all the Kotlin files into the kotlin directory and Java files into java directory. But while configuring, I have added:
sourceSets {
main.java.srcDirs += "src/main/kotlin"
}
This means that with src/main/java, add source files from src/main/kotlin also while compiling.
This should solve your issue.
Android (likely need improvement, seems flaky):
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile.class).configureEach {
it.exclude('**/TestExcludeKotlinClass.kt')
}
If you use a Kotlin Gradle project, try this:
tasks.withType<KotlinCompile> {
exclude("**/packageToExlude/**")}
In my case, a non-Android project.
I came across a way to make this work specifically for Android unit tests (but I'm assuming it's adaptable) using a combination of other solutions here:
def filesToExclude = [
'**/*TestOne*.kt',
'**/*TestTwo*.kt',
...
]
tasks.withType(org.gradle.api.tasks.SourceTask.class).configureEach {
it.exclude(filesToExclude)
}
android.sourceSets.test.kotlin.exclude(filesToExclude)
In my particular case, the extra wildcards around the test name were needed due to other generation occurring (specifically, Dagger with kapt).
This seems to be a bit hacky way to approach it, but it works by ensuring the test target is excluded from all tasks that it could actually be excluded from (including both build & kapt tasks). The sourceSets exclusion is still necessary for the file not to be picked up for compilation (I think this is the Kotlin Gradle Plugin doing it, but it might also be the Android Gradle Plugin).

How to exclude a cpp file in experimental gradle?

I'm trying to use Android Studio 1.3.1 to compile an NDK project using the experimental gradle syntax.
My build.gradle looks very much like the one from the Teapot example
With the exception that my source tree has some files which I don't want to include in the build. I can't remove these files so I need gradle to ignore them.
I tried adding an exclude definition:
android.sources {
main {
jni {
source {
srcDirs 'src/main/jni'
excludes += "src/main/jni/FileToExclude.cpp"
}
}
}
}
but that did not affect the outcome. gradle still tries to compile this file.
I tried excludes, exclude with =, += and with nothing at all but no permutation works.
From what I've found, the correct directive to exclude the file from the build is exclude, not excludes. Check your build.gradle to make sure you didn't make a mistake here (you've used excludes in the provided sample).
Upd: ok, after some research I found this thread on the AOSP issue tracker. The topic starter says the following:
The java/resources components of the sourcesets allow for include/exclude patterns.
We should do this for aidl/rs/jni/assets.
The issue is still open so I suppose this functionality has to be implemented in the Android Gradle plugin or Android Studio or in both of them (and isn't implemented yet). It'll be implemented in Android Studio 1.5, at least this is what the tags are saying.
I think you are giving path of the file in wrong manner.
It should be:
srcDir 'src/main/jni'
exclude 'FileToExclude.cpp'
You can follow this link.
https://discuss.gradle.org/t/how-can-i-exclude-certain-java-files-from-being-compiled/5287/2
Also note that you should use exclude instead of excludes and srcDir instead of srcDirs.
I looked into the android source, it looks like you could update the filter to exclude your file. I don't know what version of the gradle plugin you are using, so I can't be sure what the underlying api is. You could try setting the PatternFilterable manually to exclude the file.
android.sources {
main {
jni {
source {
srcDirs 'src/main/jni'
getFilter().exclude('**/FileToExclude.cpp')
}
}
}
}
I looked at Gradle Code Review, and saw that LanguageSourceSet was being used. Looking at the Gradle documentation for LanguageSourceSet, which you can access a SourceDirectorySet, which has a PatternFilterable that you can set the exclude on.
As it's still experimental there's not a much of documentation on Gradle Experimental. But with some experimentation I was able to dig a way on how to exclude some files, i.e.:
model {
//...
android.sources {
//...
jni {
//...
source {
excludes.add("<FILE PATH>") // You can have multiple excludes.add(...)
}
}
}
}
Note: the solution works on gradle-experimental 0.7.0
The easiest way is to set the properties in build.gradle:
sourceSets.main.jni.srcDirs = [] // now, AS will not try to compile your source files
sourceSets.main.jniLibs.srcDirs = ['libs'] // now, AS will pick up the compiled SO files from libs (where ndk-build will normally put them)
You can also define a "buildNative" task, to run ndk-build as part of compileTask, as defined in this answer.

Exclude class from resulting dex file

I have a problem. I have a structure of project looking like this:
P
|-SubP1
|-SubP2
There are two stub classes android.media.IRemoteDisplay in both packages. They differ in implementation, but that's not the matter - they will be replaced by system classes when I'll run the app on Android.
However, there is a problem - I can't build the project because dexMerger fails - it says there are two conflicting classes. I can understand that error - after all, there are really two conflicting classes :)
But when I try to exclude these files in build.gradle like this:
sourceSets {
main {
java {
srcDir 'src'
exclude '**/android/media/**'
}
}
}
The compilation fails because it can't find android.media.IRemoteControlDisplay class(and it's nested classes).
How can I still use these classes, but exclude them from resulting DEX file?
Please DON'T question if it's right to exclude the class from compiled project - it's the right thing to do, I already did it, but manually - by pre-compiling SubP1 and SubP2 to jars and then manually removing IRemoteController.class from these jar files and then including those jars in P.
I'll also be satisfied with that solution:
1. Build SubP1
2. Remove IRemoteControlDisplay.class from SubP1.jar
3. Build SubP2
4. Remove IRemoteControlDisplay.class from SubP2.jar
5. Add SubP1.jar and SubP2.jar as dependencies to P
6. Build P
If that's possible, please let me know.
Finally, I've been able to do it.
What I needed was a runtime dependency instead of compilation-time dependency. So, I've created submodule for SubP1 called SubSubP1(for example) moved the android.media.IRemoteDisplay into the SubSubP1, and created submodule SubSubP2 for SubP2, and did the same with stub class. Then I've declared the dependency as following for SubP1 and SubP2:
dependencies {
provided project(':SubP1:SubSubP1')
}
and
dependencies {
provided project(':SubP2:SubSubP2')
}
And that did the trick! Instead of compiling the classes, Gradle assumed that they will be loaded at runtime.

Gradle create multi project Jar

So I've been playing in Gradle and Android Studio now since the early days of their inception. However, I find myself banging my head on the walls far more times then it is worth at times :(.
I have spent a day and a half trying to resolve my current dilemma.
Where I work we use a lot of shared library projects. This means that unlike Gradle's native assumption, my projects are NOT all nested under one parent project. (BUT this is NOT my question) I have gotten this working.
After our projects have become complete and ready to go, it has been asked to create an SDK for the current project infrastructure for external use. Now in the old IntelliJ I would simply generate some JavaDocs and create an Artifact that includes all dependencies, then another on that does not include the dependency jars and name them respectfully.
However, in Gradle this appears to be very difficult, maybe even unsupported, and I can't find anyone else that has done it after more then 10 hours of Googling and trial and error, I finally decided to make a demo project to show exactly what I'm doing and what I'm trying to accomplish.
I need to do a few things.
Generate a Jar file that includes ALL module dependency code and dependent Jar files
Generate a Jar file that includes ALL module dependency code and ZERO dependent Jar files
Generate an AAR file that includes All module dependency code and dependent Jar files as well as resources for launching our Activity if they want to use it.
Generate an AAR file that includes All module dependency code and ZERO Jar files as well as resources for launching our Activity if they want to use it.
So there in lies my problem. Each module when running a Task with (type: Jar) simply generates it's own code. I'm managed to get the dependent Jar files to compile in once, but then there is no regular source code, but I have NEVER been able to get a Module's source code to be included in the Jar file which is my biggest hurdle right now.
Here is a list of Tasks that I have tried without accomplishing this simple task yet.
evaluationDependsOn(':dependencyModule')
task myJar(type: Jar){
appendix = 'myJar'
from android.sourceSets.main.allSource.files
}
task uberJar (type: Jar){
from(configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }) {
exclude "META-INF/*.SF"
exclude "META-INF/*.DSA"
exclude "META-INF/*.RSA"
}
}
task fatJar(type: Jar, dependsOn: 'compileJava') {
from {
sourceSets.main.output.classesDir
}
// Add all dependencies except for android.jar to the fat jar
from {
configurations.compile.findAll {
it.getName() != 'android.jar'
}.collect {
it.isDirectory() ? it : zipTree(it)
}
}
archiveName = 'fatJar.jar'
}
task jarFat(type: Jar) {
appendix = "fat"
from android.sourceSets.main.java
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}
task sourcesJar(type: Jar) {
from android.sourceSets.main.allSource
classifier = 'sources'
}
task clearJar(type: Delete) {
delete 'build/libs/myCompiledLibrary.jar'
}
task makeJar(type: Copy) {
from('build/bundles/release/')
into('build/libs/')
include('classes.jar')
rename ('classes.jar', 'myCompiledLibrary.jar')
}
makeJar.dependsOn(clearJar, build)
task jar(type: Jar) {
from android.sourceSets.main.allJava
}
task deployJar(type: Jar, dependsOn: jar) {
baseName = project.name + '-deploy'
deps = configurations.runtime + configurations.archives.allArtifactFiles
depClasses = { deps.collect { it.isDirectory() ? it : zipTree(it) } }
from(depClasses) {
exclude 'META-INF/MANIFEST.MF'
}
}
task modelJar(type: Jar) {
from sourceSets.main.output
}
task jarWithDependency(type: Jar){
from android.sourceSets.main.classesDir
from {configurations.compile.collect {zipTree(it)}}
}
task androidJavadocs(type: Javadoc) {
source = android.sourceSets.main.allJava
}
Nothing has quite done the job yet. Any help would be greatly appreciated!!
Thanks in advance for taking the time to look at this.
I have the full functioning Sample Project if anyone would like it, but I don't see an option to upload here so is the link to the Demo project I built. It is very small and very easy to follow. One class or method basically per Project.
Demo Project
Using the application plugin, you can just call "distZip" to get a zip with all the libraries. By default you get a bin directory with a batch file and a shell script to run the program and a lib directory with all the jar files.
You probably want to update the Manifest to include all the necessary libraries like the following (I have additional stuff in mine).
EDIT I removed the references to "project" because it should not be necessary in this instance.
jar.doFirst
{
// aggregate all the jars needed at runtime into a local variable (array)
def manifestClasspath = configurations.runtime.collect { it.name }
// remove duplicate jar names, and join the array into a single string
manifestClasspath = manifestClasspath.unique().join(" ")
// set manifest attributes - mainClassName must be set before it is used here
manifest.attributes.put("Main-Class", mainClassName)
manifest.attributes.put("Class-Path", manifestClasspath)
}
I'm not an Android developer, so you would have to add some additional code for the AAR stuff.
Update from Author.
Ok as time has gone on, I have learned that the best practice is to allow dependency management tools to do their job and not try to package these files as such.
You can create fat jars and fat aar files, there are plugins to help, but it is hacky and doesn't allow the user to exclude transitives properly if they are nested in the compiled product. the exclude is intended for maven server pom files to include or exclude dependency files.
So using a Maven Repo Server is the best way to manage this instead as the FAT compiler plugins are unreliable and break with each gradle update and more importantly limit your user's ability to exclude "some and not all" when it comes to transitives.
So stay away from doing this if you can avoid it and do it the right way I recommend it. I'll leave this post up in case anyone else was heading down this bad path as well and hope you move to the right path of dependency management servers with transitive dependency managed by pom files.

Categories

Resources