After upgrading to eclipse 2019-12 and buildship 3.1.3 I found that eclipse wouldn’t let me manually attach source code to its “Project and External Dependencies” node, hence no dependency source code for debugging.
After some buildship searching I found that I could replace the “compile files” dependencies with a “compile” dependency combined with a flatDir repository. Initially this worked as I was able to view the associated source code when debugging in eclipse.
However, after upgrading and rebuilding the dependencies and copying the jars and -source.jars to the flatDir (using the same name and version number), the source code is no longer available in eclipse. I even tried adding an eclipse.classpath.file.whenMerged override but that hasn’t helped.
I haven’t tried recently, but I suspect if I change the filename/versions of the dependent files the source file will be included but I’d prefer not to do that as I’d like all projects to share the latest patch for a specific major.minor version automatically when being rebuilt.
Also, I’d like to steer clear of maven so I presume I’m stuck with flatDir for these locally-managed dependencies.
Don’t use flatDir!! Instead, use the Maven repository directory layout for your jars, sources jars, javadoc jars and poms. You can then configure a local directory as a maven repository in Gradle and your IDE will automatically find the javadocs and sources.
I replaced my flatDir with a directory modeled after maven and I replaced the compile dependency with the appropriate format. However, the compile task fails because I have no corresponding .pom files. Is there a way to generate the .pom file without maven or can this problem be resolved by adding some data to the manifests?
Here’s the error I received…
Execution failed for task ‘:compileJava’.
Could not resolve all files for configuration ‘:compileClasspath’.
Could not find ToolboxCore:ToolboxCore:1.0.
Searched in the following locations:
- https://jcenter.bintray.com/ToolboxCore/ToolboxCore/1.0/ToolboxCore-1.0.pom
- file:/F:/java/lib/mavenrepo/ToolboxCore/ToolboxCore/1.0/ToolboxCore-1.0.pom
Required by:
project :
My updated repositories and dependencies look like this:
The jar wasn’t built by maven, but creating the minimal .pom manually worked! My build is picking up the latest binary jar and sources jar from my maven “repository” and I can now step through and set breakpoints on the libs in eclipse.
I assume that it should be possible to generate the pom in the future but that would require changes to automatically update the version number, which I’m not ready to tackle yet. I’d like to move from a major.minor version number to a full major.minor.patch version number and I don’t want to have to change the build.gradle every time I run a build.
I agree – seems odd that a pom is required since the group/artifact/version can all be derived from the compile statement. But since the poms were easy enough to create I tried that first. I’ll give this a try in the next few days.
It makes sense to me that gradle needs a pom for “ToolboxCore:ToolboxCore:1.0” since gradle wants to find the transitive dependencies. Did you try “ToolboxCore:ToolboxCore:1.0@jar”?
Not yet. I ended-up changing my build to use the maven-publish plugin to generate the .pom and to post the updated jars to my maven repo. That led me to replace the ‘java’ and ‘application’ plugins with ‘java-library’ and ‘java-library-distribution’. Oh, and I fixed some gradle deprecation warnings too. Definately a more heavyweight approach as compared to the @jar trick but it saves me the trouble of manually syncing the maven repo.
My build is picking up the latest binary jar and sources jar from my maven “repository” and I can now step through and set breakpoints on the libs in eclipse.
Great! Glad to hear
I ended-up changing my build to use the maven-publish plugin to generate the .pom
Even better! Now the pom should contain your artifact’s transitive dependencies. Much better than a minimal pom
it saves me the trouble of manually syncing the maven repo
I’m assuming this is just a hack for you to develop two dependent artifacts by yourself (a team of one) on your machine at home.
The normal “enterprise” solution to this problem is to host a private repository (eg artifactory or nexus) on your network and publish to the repository as part of your release (and possibly CI) process
You’re correct in that my work products are all managed by a “team of one”. However, some of the products are used by a group so the “team of one” is expected to become a team of a few, or a couple of teams of few. But the direction is not enterprise, it is open-source, or at least cooperatively-owned and managed.
this is the first I’ve heard of composite builds. But at first blush, it doesn’t look like the right approach
You are building ProjectA, publishing the artifact to a directory only to consume the dependency in ProjectB. This is exactly what a composite build is for. In a composite build the two builds are joined together as one and gradle is smart enough to use the local ProjectA artifact in ProjectB since group/artifact/version is the same (ie no publish step required)
the direction is not enterprise, it is open-source
Many (most?) open source projects publish to a repository. My usage of the word “enterprise” was probably incorrect. As you grow to more than one in your team, you should at least consider publishing to a repository that the team can share
If someone wants to stick with the flatDir simplicity, for me it worked just renaming the jar sources like:
$GRADLE_PROJECT/libs/library.jar
$GRADLE_PROJECT/libs/library-sources.jar
I still would be interested to know why adding the source jar to the library does not work in the first place.
I have a similar need to add a custom source jar to one of the entries of the gradleclasspathcontainer.
My code looks like this:
eclipse {
classpath {
if(!tools.isJeeUtilityProject(project)) {
containers 'org.eclipse.pde.core.requiredPlugins'
minusConfigurations += [configurations.runtimeClasspath]
}
/* If not added here it will be appended at the end of .classpath but we want to customize it below */
containers 'org.eclipse.buildship.core.gradleclasspathcontainer'
file.whenMerged {
/*
* The following entries are needed in case this plugin wants to export types from these JARs in MANIFEST.MF
*/
project.configurations.bundled.sort { it.name }.each { File jarFile ->
def lib = new Library(fileReference(file("lib/${jarFile.getName()}".toString())))
lib.exported = false
lib.sourcePath = fileReference(file("lib/${jarFile.getName().take(jarFile.name.lastIndexOf('.'))}-sources.jar".toString()))
println "lib.sourcePath $lib.sourcePath"
println "lib.library $lib.library"
entries += lib
}
project.configurations.bundledApi.sort { it.name }.each { File jarFile ->
def lib = new Library(fileReference(file("lib/${jarFile.getName()}".toString())))
lib.exported = true
entries += lib
}
if(project.configurations.bundledApi.size() > 0) {
def gradleclasspathcontainer = entries.find { it.path == 'org.eclipse.buildship.core.gradleclasspathcontainer' }
gradleclasspathcontainer.exported = true
}
// more code here
}
}
Yes, as I suggested earlier you should use the maven directory layout which has a convention for storing source jars with the binaries which IDE’s will use