Add sources manually for a dependency which lacks of them


(Ivan RF) #1

I have a case in which the sources for a dependency are not in jcenter/maven. How can I compile that dependency from a global repository but add the sources manually from a local file?

Specifically, this happens with Hibernate and the library antlr-2.7.7.jar. This library has no sources in jcenter or maven and I would like to add them manually. How can I do this?

Eclipse is my IDE.


(Shinya Mochida) #2

You can add dependencies manually with method files.

dependencies {
  compile files('path/to/antlr-2.7.7.jar')
}

(Ivan RF) #3

That’s not what I asked. I know how to add dependencies. I just want to add the sources for an already added dependecy.


(uklance) #4

You could use the whenMerged hook of the eclipse plugin to tweak the eclipse classpath model prior to writing to xml.

Another option is to tweak the xml using the withXml hook.


(Ivan RF) #5

The only thing that I found is this, but it is not working:

eclipse.classpath.file.whenMerged { cp ->
  // Add sources to a classpath entry
  def fileReferenceFactory = new org.gradle.plugins.ide.eclipse.model.internal.FileReferenceFactory()
  
  def entry = cp.entries.find { entry -> entry.path.endsWith('antlr-2.7.7.jar') }
  entry.sourcePath = fileReferenceFactory.fromFile(file('lib/sources/antlr-2.7.7-sources.jar'))
}

(Shinya Mochida) #6

You can add source path, with following script.


eclipse.classpath.file.withXml {x ->
  def n = x.asNode()
  n.classpathentry.find {
    it.@kind == 'lib' && it.@path.contains('antlr-2.7.7')
  }.@sourcepath = 'path/to/antlr-2.7.7-source.jar'
}

(Ivan RF) #7

@Shinya_Mochida I just tried that code, but it is still not working


(Shinya Mochida) #8

Did you try it with command?

$ gradle --daemon cleanEclipse eclipse

In my environment, I don’t have any antlr source code, so I try this script to modify…

  • output directory to be out directory instead of bin directory.
  • junit to have javadoc.
configurations {
  javadocDep (group: 'junit', name: 'junit', version: '4.12', classifier: 'javadoc') {
    exclude module: 'hamcrest-core'
  }
  testCompile 'junit:junit:4.12'
}
eclipse.classpath.file {
  withXml{xml ->
    def node = xml.asNode()
    node.classpathentry.find {it@kind == 'output'}.@path = 'out'
    node.classpathentry.find{
      it.@kind == 'lib' && it.@path.contains('junit')
    }.@javadocpath = configurations.javadocDep.asPath
  }
}

And a command gradle --daemon cleanEclipse eclipse generates .classpath file as follows.

<?xml version="1.0" encoding="UTF-8"?>
<classpath>
  <!-- eclipse task generates bin as output path, but it is changed to out -->
  <classpathentry kind="output" path="out"/>
  <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
  <!-- javadocpath attribute is not created by default, but it is added -->
  <classpathentry
      sourcepath="/Users/name/.gradle/caches/modules-2/files-2.1/junit/junit/4.12/a6c3/junit-4.12-sources.jar"
      kind="lib"
      path="/Users/name/.gradle/caches/modules-2/files-2.1/junit/junit/4.12/2973/junit-4.12.jar"
      javadocpath="/Users/name/.gradle/caches/modules-2/files-2.1/junit/junit/4.12/941a/junit-4.12-javadoc.jar"/>
  <classpathentry
      sourcepath="/Users/name/.gradle/caches/modules-2/files-2.1/org.hamcrest/hamcrest-core/1.3/1dc3/hamcrest-core-1.3-sources.jar"
      kind="lib"
      path="/Users/name/.gradle/caches/modules-2/files-2.1/org.hamcrest/hamcrest-core/1.3/42a2/hamcrest-core-1.3.jar"/>
</classpath>

(for making it to easy to read, I inserted indentation in each attributes, and shorten hash code.)


(Ivan RF) #9

I forgot to mention that I use the eclipse plugin “Buildship: Eclipse Plug-ins for Gradle” and I think my issue is there.

I just tried the first code that I posted with the gradle eclipse task and it works. That is, it adds the sourcepath for the classpathentry.

However, in Project and External Dependencies the library has no sources attached. So, I guess the problem is with the eclipse plugin.


(Sterling Greene) #10

@etiennestuder @donat Is there anything @IvanRF can tie into when importing with Buildship?


(Etienne Studer) #11

The Tooling API is decoupled from the XML files that are generated via ‘gradlew eclipse’. There is currently no way to attach custom sources such that the Tooling API picks them up. As consequences, Buildship does not see these sources neither.

This issue has been reported before and is likely to be tackled in the near future.


(Ivan RF) #12

I’m new to Gradle. So, if I’ve understood you correctly, this is an issue from Gradle core and not from Buildship?


(Etienne Studer) #13

It’s a feature we first need to implement in Gradle core, i.e. in its Tooling API. We can then make use of in Buildship.


(mauromol) #14

The following issues are related to this subject:
https://issues.gradle.org/browse/GRADLE-2046
https://issues.gradle.org/browse/GRADLE-2887
i.e.: the ability to supply artifacts (sources, javadocs, or even JARs when just the POM is published on a Maven repository) via an alternate repository (a flatDir repository, for instance).


#15

A year and half later It’s a little past the ‘near future’ that you mentioned. Any hope of getting this working? I am stuck with some local file dependencies and would really love to have the tooling properly support it. Thanks!


(js402882) #16

+1
I need to attach custom sources to dependencies too :wink:


(uklance) #17

I think gradle can reference a single dependecy from multiple repositories (ie jar from one repo and sources from another) but I’m not 100% sure… you could try:

repositories {
   maven {
      // get the main jars (classes) from here
      url 'http://main/maven/repo'
   }
   maven {
      // get the sources from here (local directory)
      url uri('localrepo')
   }
}

Then you could store the sources using maven directory conventions
eg: projectRoot/localrepo/${group}/${artifact}/${version}/${artifact}-${version}-sources.jar