0

TLDR:

How do I find the source files mentioned in a gradlew someTask --stacktrace?

Details:

I'm trying to build a javadoc for an Android library I made using gradle. I see no official documentation on how to do this, but there are some very dated examples here on SO. I tried the popular answers, but no luck. So I'm trying to debug why these answers no longer work.

So here is my task (from the previously linked SO question's answer)

task javadoc(type: Javadoc) { source = android.sourceSets.main.java.srcDirs classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) destinationDir = file("../javadoc/") failOnError false } 

located in ./libs/abcvlib/build.gradle where ./ is my project root directory.

I run ./gradlew javadoc from the project root directory and get:

 Task :abcvlib:javadoc FAILED FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':abcvlib:javadoc'. > path may not be null or empty string. path='' 

Now, the purpose of this question is not just to answer "What path=''"?, but also, how would I find the answer to this question myself.

If I use --stacktrace I see

* Exception is: org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':abcvlib:javadoc'. at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:38) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52) at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204) at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:199) at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66) at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59) at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157) at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59) at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53) at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:73) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52) at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:42) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:338) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:325) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:318) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:304) at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:463) at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:380) at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64) at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:49) Caused by: java.lang.IllegalArgumentException: path may not be null or empty string. path='' at org.gradle.api.internal.file.AbstractBaseDirFileResolver.doResolve(AbstractBaseDirFileResolver.java:59) at org.gradle.api.internal.file.AbstractFileResolver.resolve(AbstractFileResolver.java:74) at org.gradle.api.internal.file.AbstractFileResolver.resolve(AbstractFileResolver.java:48) ... 

Ok, so what do I do now? Where can I find the source for the .java files mentioned above such that I can find where this empty path parameter is causing an issue? If I can't find the source, I'm at a roadblock for helping myself.

Furthermore, where can I find the API, or source for the code used in the task itself? For example, what does android in android.sourceSets.main.java.srcDirs resolve to? I assume this means the Gradle plugin for Android, but I honestly have no idea how to verify this. In any other language I'd have some editor that would have tooltips or some quickkey showing me where the definition for this is located. I could go inspect the source code for it, find all possible variables or whatever you call sourceSets as it pertains to android, and how main pertains to sourceSets and so on.

Yes, I can read through the entire gradle documentation, and become a gradle expert, but this is not something I will be doing regularly, so hoping you can point me to some specific documentation regarding this topic.

Thanks in advance!

1 Answer 1

1

I would say that debugging a Gradle script is essentially the same as debugging any program executing on the JVM.

Gradle executes a JVM program which is your build script, plus the Gradle dependencies, plus whatever you have added to the build classpath via dependencies and plugins. All the usual tools and rules apply.

Where can I find the source for the .java files mentioned above such that I can find where this empty path parameter is causing an issue?

You can use the package directives to find the associated source. This is saved somewhere in the Gradle cache directory, but more easily you can find it in the "External Libraries" section of an IntelliJ IDE or you probably can find it on GitHub without too much trouble.

For example the Gradle code is on GitHub and if you do a search for the package and class where your error occurred, you can quickly find the associated source code. You may have to do that a few more times with different files before you figure out what's going on, of course.

If you find it in your IDE you can try setting breakpoints and debugging, if that's useful.

where can I find the API, or source for the code used in the task itself?

Gradle publishes full documentation for each of its public classes and also extensive guidance. You are creating a task of type Javadoc, which we can find API documentation for. You can find the actual source code in the same way as described above.

Note the Gradle Javadocs are written with pure Java in mind, so you need to bear in mind how your chosen Gradle DSL language (Groovy or Kotlin) will call the Java code. Eg to find out about the source field you need to look under getSource() and setSource().

Yes, I can read through the entire gradle documentation, and become a gradle expert

For good or for ill, you do need to obtain some knowledge of how Gradle works in order to use it effectively.

One thing you can consider to make Gradle a bit easier is to use Kotlin as your DSL language rather than Groovy. Kotlin is statically typed, which allows the IDE to give you more hints as to available methods and properties as you are writing code. Also, if you are writing an Android app, it may well be that you are using Kotlin in your main program as well, increasing the likelihood you are familiar with it. To change, you use a build file called build.gradle.kts instead of build.gradle (and migrate all your code to the new language, of course).

Sign up to request clarification or add additional context in comments.

14 Comments

Thank you for your kind summary of all things considered! So the source for gradle is on Github, but how can I verify the version being used? Otherwise I might be looking at the wrong source/docs. I guess I can eventually understand what source needs to be to fit the gradle API, but how can I verify this android.sourceSets.main.java.srcDirs meets what is expected by source? I managed to set up an inline debugger with the gradle build in Android Studio, but cannot evaluate any variables while at a breakpoint, so I really don't see how to verify what android is, nor where it is defined
Kotlin sounds much easier, but I don't have the budget/time to convert this whole project atm, and just need to finish this one-off for now. I'll propose the conversion for future work though! :)
I'd look first to the source through your IDE, then you don't have an issue with the version. Then, also if you are using a recent version you are unlikely to find what's on GitHub to be different. As for what source expects, then you can read the docs. If you keep going, you'll find Javadoc inherits this method from SourceTask. This tells us it's the same rules as Project.files() which broadly accepts a file path, not a package. This is the path where the source code is you're documenting
Thank you for the detailed walkthrough. In Android Studio, if I GoTo->Declarations and Usage, I see a decompiled class file. Ideally there's a way to link the source in Android Studio such that I can see the actual source rather than just the decompiled version which only tells me source should be of type Object which is somewhat useless. With the gradle online API docs though, I think I can now help myself with the built in gradle API.
I still cannot seem to locate anything on the android object. Android Studio shows nothing for Declarations and Usage, though it somehow has autocomplete for android. so it surely has some internal reference to the API/source. The closest thing I can find similar to the gradle docs on this android object is developer.android.com/reference/tools/gradle-api/8.1/classes, but I see no logical way to find which class this particular android is defined within.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.