gradle: best way to encapsulate custom dsl - java

my screencast, i hope my aExtFunc can work in build.gradle in any projects, but intellij idea raise
Cannot resolve symbol 'gradleExt'
my question is: how to fix it.

Defining dependency on the project
dependencies{
compile project(':gradleExt')
}
Doesn't mean that you can work with the content of the project in your build script:
task ATask() {
new gradleExt.Ext().aExtFunc()
}
You probably need to create new groovy class directly in the build.gradle file implementing desired behaviour. Or if you really want to have the implementation in different place you need to add the classpath dependecy into the buildScript{} block. See the documentation on implementing custom tasks:
http://www.gradle.org/docs/current/userguide/custom_tasks.html
If you want custom dsl, then custom gradle plugin is probably what you are looking for
http://www.gradle.org/docs/current/userguide/custom_plugins.html
And also please double check the documentation on multi-project builds if that might be of any use to you, it is not clear from the "my screencast" what your overall gradle setup is. I would post the link, but I don't have enough reputation.

Related

How do you use Maven-Publish Android Gradle Plugin's generated components in Kotlin DSL (build.gradle.kts)?

Currently I'm working with an old Kotlin DSL build script that publishes an Android AAR library to a Maven repository. The dependencies are added to the pom-default.xml via simplistic iteration through the implementation configurations. Similar to this:
withXml {
val dependenciesNode = asNode().appendNode("dependencies")
configurations.getByName("implementation") {
dependencies.forEach {
val dependencyNode = dependenciesNode.appendNode("dependency")
dependencyNode.appendNode("groupId", it.group)
dependencyNode.appendNode("artifactId", it.name)
dependencyNode.appendNode("version", it.version)
}
}
}
This doesn't translate the exclusion statements, and so now publishes useless broken libraries with conflicting classes. I'd like to be able to use the Android Gradle Plugin's generated build artifact components instead, because I understand that by using these, the pom file will be automatically generated with the right list of dependencies (presumably with the exclusion clauses).
The documentation to do this is given here:
https://developer.android.com/studio/build/maven-publish-plugin
Unfortunately, as always, the example given is Groovy, and I cannot find any example of the syntax you would use in a Kotlin Gradle script.
from(components["release"])
...didn't work.
Okay, turns out...
from(components["release"])
...does work, I just didn't put in the...
afterEvaluate {
...clause, recklessly assuming this was just a Groovy thing.
Remember kids, stay away from drugs, work hard at school and follow the documentation faithfully, to a tee.

Accessing classes from separate modules

I have a project with the following basic setup:
Root Project
- employee-service
- nomination-service
I need to access classes from employee-service in nomination-service, but am not able to get the dependencies down for some reason.
Here's the root project's settings.gradle:
rootProject.name = 'pair-project'
include 'applications/employee-service'
include 'applications/nomination-service'
Inside of the nomination-service build.gradle I have tried all the following (each dependency denotes one thing I've tried, they're not all present at the same time):
dependencies {
project(':employee-service')
project(':../../applications/employee-service')
compile(':../employee-service')
compile(':employee-service')
compile('./applications/employee-service')
compile('/employee-service')
}
All of these doesn't work for some reason or the other.The project ones generally tell me it can't find a project at that location. When I use compile it will usually build fine, but then can't find the import for the class I'm trying to use.
Any help would be greatly appreciated here, everything I've read online has generally suggested taking this approach, so I'm not sure what I'm doing wrong.
The applications/nominations-service/build.gradle should be:
apply plugin: 'java'
dependencies {
compile project(':applications/employee-service')
}
Generally, from here dependencies require a configuration and one or more items with a dependency notation. In this case, compile is the configuration and we are using a project dependency. All of your examples only had one, but not both.

Adding PubNub AnnotationProcessor in Android Studio

I'm trying to set up the PubNub jar as a library in my Android Studio project. The project is something I am porting over from another computer, so I'm mostly copying things in.
It appears between then and now that I now have to configure the AnnotationProcessor of this jar, but I'm really not sure what that requires, nor have I been able to find an example that fits my issue.
When I try to compile my project, I am left with this message:
Error:FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:javaPreCompileDebug'.
Annotation processors must be explicitly declared now.
The following dependencies on the compile classpath are found to contain annotation processor.
Please add them to the annotationProcessor configuration- pubnub-gson-4.19.0-all.jar (pubnub-gson-4.19.0-all.jar).
Alternatively, set android.defaultConfig.javaCompileOptions.annotationProcessorOptions.includeCompileClasspath = true to continue with previous behavior.
Note that this option is deprecated and will be removed in the future.
See https://developer.android.com/r/tools/annotation-processor-error- message.html for more details.
I'm really not sure at all what this is telling me to do, and the examples I can find of annotationprocessor on the internet (none for PubNub) all are pointing to packages and classes, which I don't see what I am suppose to do with.
Can someone lead me down the correct path?
I apologize for the formatting of the error, but the site wouldn't let me submit it in blockquotes because it was "improperly formatted code."
Try to add this line in your dependencies{} block:
annotationProcessor files('libs/pubnub-gson-4.19.0-all.jar')
(along with the implementation files('libs/pubnub-gson-4.19.0-all.jar'))
It works in my case.

In Buildship: how can I substitute a Gradle project with a built jar?

I would like to be a able to get Eclipse to ignore one Gradle project, and instead use a pre-built version of it.
Background
I have a project "parser" written in Scala, and a dozen others written in Java. The weakest link in my tool-set is Scala IDE. I use this plugin to edit & compile Scala code, but unfortunately it breaks the Java (JDT) tooling quite badly in mixed-language projects*.
Specifically: Call-hierarchy is missing results, searches crash and so on. Also Scala IDE appears to have lost funding and the issues sound fairly fundamental, so I'm not holding my breath for these issues to be fixed.
With Maven (m2e) I had a workaround I was quite happy with:
Build as a .jar put into my local .m2 repository:
cd parser; mvn install
In Eclipse, close the "parser" project
"Like magic", m2e simply picked up the most recent 'installed' .jar and used it in place of the closed project.
An awesome answer would be how to get Gradle to do that!
However all I wish for is any solution that meets these...
Requirements
That I can open Project parser when necessary (which is seldom),
to edit and build changes via the Gradle command-line.
I will close it when done.
Other projects use the built .jar from my local .m2 repo.
(It's fine if they always do so.)
The change must not affect others who don't use Eclipse
(ideally) the change can be used by other Eclipse users
Approaches
A similar question had this good answer by #lance-java with a number of general suggestions. I think I can rule out these ideas:
composite build support / multiple repos. Other team members wouldn't think it makes sense to build this project separately, as it is quite closely integrated with the others.
dependency substitution rules - doesn't appear to meet requirement 3.
Something along the lines of lance-java's idea #4 sounds viable. Paraphrasing...
"use the eclipse plugin [in conjunction with] Buildship, e.g. using the whenMerged hook to tweak the generated .classpath [of all the Java projects]."
UPDATE: [18 Apr]: I had hit a brick wall in this approach. Buildship was not putting the built .jar onto the runtime classpath. (UPDATE 2: Now resolved - see my answer.)
Questions
The main question: How can I structure a solution to this, that will actually work & avoid any major pitfalls?
Note that the project itself has a few dependencies, specifically:
dependencies {
compile 'org.scala-lang:scala-library:2.12.4'
compileOnly 'com.google.code.findbugs:jsr305:1.3.9'
antlr 'org.antlr:antlr4:4.5.3'
}
So a sub-question may be: How to pull these in into the other projects without duplicating the definition? (If that doesn't work automatically.)
So the solution was a bit involved. After adding 'maven-publish' to create the library, I then implemented the following to force Eclipse to use the prebuilt library:
subprojects {
// Additional configuration to manipulate the Eclipse classpaths
configurations {
parserSubstitution
}
dependencies {
parserSubstitution module("com.example:parser:${project.version}")
}
apply plugin: 'eclipse'
eclipse {
classpath {
plusConfigurations += [ configurations.pseLangSubstitution ]
file {
whenMerged { cp ->
// Get Gradle to add the depedency upon
// parser-xxx.jar via 'plusConfigurations' above.
// Then this here if we have a dependency on Project(':parser')
// - If so, remove it (completing the project -> jar substitution).
// - If not, remove the .jar dependency: it wasn't needed.
def usesParser = entries.removeAll {
it instanceof ProjectDependency && it.path.startsWith('/parser')
}
def parserJar =
cp.entries.find { it instanceof Library && it.path.contains('parser-') }
if (usesParser) {
// This trick stops Buildship deleting it from the runtime classpath
parserJar ?. entryAttributes ?. remove("gradle_used_by_scope")
} else {
cp.entries.remove { parserJar }
}
}
}
}
So there are 2 parts to this:
Using 'plusConfigurations' felt a bit round-about. I ended up doing this because I could not see how to construct class Library classpath entries directly. However it could well be that this is required to implement the 'transient dependencies' correctly anyway. (See the end of the question.)
The trick to stop Buildship removing the .jar from the runtime classpath (thus deviating from a Gradle command-line launch) was provided to me by a Gradle developer in this discussion.
Usage
The solution works just as I hoped. Every time some code in this library is modified, I execute the following task of mine on the command line (which also does some other code & resource generation steps, in addition to building the parser jar):
./gradlew generateEclipse
Then in Eclipse I press keyboard shortcuts for "Gradle -> Refresh Gradle Projects", Build.
And harmony is restored. :-)
Navigating to the (prebuilt) source of parser works.
If I need to edit the source, I can open the parser project and edit it. Scala-IDE still does a good job for this.
When I'm done I execute the command, close the project and my Java tools are happy.
In parser project
You shoud use the maven-publish plugin with the publishToMavenLocal task
apply plugin: 'maven-publish'
group = 'your.company'
version = '1.0.0'
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
pom.withXml {
def root = asNode()
root.appendNode('name', 'Your parser project name')
root.appendNode('description', 'Your parser project description')
}
}
}
}
Everytime you make a modification, just change the version number if necessary and go with gradle publishToMavenLocal
In other java project using parser
Just use parser as a regular dependency :
repositories {
mavenLocal()
...
}
compile 'your.company:parser:1.0.0'
If my understanding of your situation is good, it should do the trick.

What's the best way to define a BOM in gradle without involving XML?

XML being one of the reasons people move to Gradle, our project defines several pom packaged items. I assume that these are BOM's since they just used to pull in dependencies. So... how do you define a BOM in Gradle from a "best practices" / no XML perspective? I know that you can create a configuration that has dependencies and then just include it but I don't, for example, want "gradle build" to create a jar file for this sub-project as it would be pointless and slow down my build for no good reason. Am I on the right track or is there a better way and if so, what is it? Do I just turn off the jar creation somehow?
I think this is what I need. It's from right out of the Gradle User Guild in Chapter 52. Specifically it's Example 52.16. "Collections and arrays of dependencies".
List groovy = ["org.codehaus.groovy:groovy-all:2.4.4#jar",
"commons-cli:commons-cli:1.0#jar",
"org.apache.ant:ant:1.9.4#jar"]
List hibernate = ['org.hibernate:hibernate:3.0.5#jar',
'somegroup:someorg:1.0#jar']
dependencies {
runtime groovy, hibernate
}

Categories

Resources