Writing a buildSrc Gradle plugin that can be published - plugins

I'm writing a custom Gradle plugin for my company to assist with integration tests of our product. My team wants to have the plugin be built with and used in the main product build (like a 'buildSrc' plugin would), but also need the plugin to be published as an artifact for other teams to use in integration with our product.
If I try and include it as a standalone plugin in the settings.gradle file and then also include it in the buildscript as a dependency, it obviously does not work because the buildscript block is interpreted first.
I also tried running another build from within the buildscript like so:
buildscript {
def connection = GradleConnector.newConnector()
.forProjectDirectory(file("${project.projectDir}/theplugin"))
.connect()
try {
connection.newBuild()
.forTasks('clean', 'build', 'install')
.run()
} finally {
connection.close()
}
repositories {
mavenLocal()
...
}
dependencies {
classpath 'com.company.product.gradle.theplugin'
}
}
This causes the plugin to be built and placed in the local Maven repo, but then the initial Gradle build fails directly afterward because it can't resolve the newly built archive. If I run it again, it works. I don't understand this behavior.
I'm probably going down a rabbit hole with this approach. Is there a way to make this work and in a less 'hacky' way?

I discovered a hacky way to accomplish this: symlink the plugins to the buildSrc (on *nix at least).
project directory
project/
buildSrc/ -> gradle_plugins/
gradle_plugins/
pluginA/
pluginB/
...
build.gradle
settings.gradle
...
build.gradle
settings.gradle
project/settings.gradle
include 'gradle_plugins:pluginA'
include 'gradle_plugins:pluginB'
...
project/gradle_plugins/settings.gradle
include 'pluginA'
include 'pluginB'
...
project/gradle_plugins/build.gradle
...
rootProject.dependencies {
runtime project(path)
}
...

The way I'm solving this is the following:
Regular multi project build with buildSrc/myPlugin/.. Within my build process I call ./gradlew -b buildSrc/myPlugin/build.gradle uploadArchives (or whichever task you use to publish your maven artifact).
Due to the "official" hack of having to add the gradle plugin to the runtime dependencies of the root project this step would fail. So I surround it with a try catch. I feel that is not perfect but it seems to work.

Related

Flutter plugin that uses .aar modules builds and runs fine in the example app but fails to build in a different app

I've written a Flutter plugin to use an SDK that requires the inclusion of some .aar modules. It builds and runs perfectly in the example app for the plugin, but when I import the plugin in a different app and try to build it, the build immediately fails with a message saying that one of the .aar modules could not be found in the plugin. This makes no sense because the module is definitely there - the platform channels to use the SDK would fail in the example app if the module wasn't there.
Why would the example app build and run without any problems but a different app won't? The only thing I can think of is that I import the plugin from path in my pubspec but it seems unlikely to me that this is the culprit.
Any advice or assistance here would be appreciated. TIA!
I got it!!!!
The answer is as found here: How to add .aar dependency in library module?
The way this adapts to a Flutter plugin is as follows:
Add a libs folder at the root of the android project in the plugin. Add the .aar files there.
In the plugin's build.gradle file, update rootProject.allProjects to look as follows:
repositories {
google()
jcenter()
flatDir {
dirs 'libs'
dirs project(':your_plugin_name_here').file('libs')
}
}
}
Still in the same build.gradle, add your .aar file(s) as dependencies as follows:
implementation(name:'aar_name_here', ext:'aar')
In the Flutter app that you want to use the plugin for, open the app-level build.gradle file and add the plugin itself as a dependency, like so:
android {
...
dependencies {
implementation project(':your_flutter_plugin');
}
}
In the settings.gradle file for the app that us using the plugin, change
include ':app'
to
include ':app', ':your_flutter_plugin'
And this should do it!!

Gradle tasks are disabled in eclipse

I'm trying to create a .jar file for my eclipse project. Through export option, I am able to create .jar, but I want to use Gradle build task to do so. Problem is that, all tasks are disabled for this particular project only, as showing in the following image...
For another project, these Gradle tasks are working fine. See its build.gradle file...
apply plugin : 'eclipse'
apply plugin: 'java-library'
repositories {
jcenter()
mavenCentral()
}
dependencies {
compile group:"org.apache.pdfbox", name:"pdfbox", version:"2.0.6"
compile group:"org.apache.pdfbox", name:"pdfbox-tools", version:"2.0.6"
compile 'com.google.code.gson:gson:2.8.2'
compile 'org.json:json:20180130'
api 'org.apache.commons:commons-math3:3.6.1'
implementation 'com.google.guava:guava:21.0'
testImplementation 'junit:junit:4.12'
}
It's settings.gradle file contains a single line that is...
rootProject.name = 'schedule-extractor'
Can anybody suggest what I am missing here?
Have you check this buildship's issue:
https://github.com/eclipse/buildship/issues/511
The following comment resolved it for me (I was having the same problem) :
https://github.com/eclipse/buildship/issues/511#issuecomment-367392031
For those who had a similar problem in include builds - Check the file
.setting/org.eclipse.buildship.core.prefs whether the
connection.project.dir property is empty. If not, make it empty. In
my case the grayed tasks become green again.
In my case, It happened when I was using composite build concept of Gradle. According to this approach, One build could be dependent on another build. In this case, the projects may behave like this.
For example, have a look on my composite build setup in settings.gradle...
rootProject.name = 'BackendRESTServices'
includeBuild ('../Algorithms')
includeBuild ('../Utilities')
Now I won't be able to build Algorithms & Utilities projects from Gradle Tasks tab as shown in the attached image of question.

How to setup JUnit testing in Gluon Project with Gradle

I am trying to setup JUnit testing in my Gluon JavaFX Application. I am using the Gluon Eclipse Plugin with Gradle and Java 8.
My build.gradle file looks like this:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.javafxports:jfxmobile-plugin:1.0.0-b10'
}
}
apply plugin: 'org.javafxports.jfxmobile'
repositories {
jcenter()
}
dependencies {
compile 'com.gluonhq:ignite-dagger:1.0.0'
compile 'org.elasticsearch:elasticsearch:1.6.0'
compile 'ch.qos.logback:logback-classic:1.1.5'
testCompile 'junit:junit:4.12'
}
mainClassName = 'com.me.MyApplication'
jfxmobile {
android {
manifest = 'src/android/AndroidManifest.xml'
}
ios {
infoPList = file('src/ios/Default-Info.plist')
}
}
Resolving the dependency is no problem, but when running the 'test' task, gradle throws an error like this:
When running gradle with java 8, you must set the path to the old jdk, either with property retrolambda.oldJdk or environment variable JAVA6_HOME/JAVA7_HOME
Could not execute build using Gradle distribution 'https://services.gradle.org/distributions/gradle-2.2.1-all.zip'.
I already tried to add the retrolambda plugin to gradle according to the plugin's README on GitHub, but it doesn't work so far. Could someone tell me what to do to configure my Gluon project so that I am able to run my JUnit tests with Gradle?
Some important addidtions:
For the plugin version it says: Gluon Tools 1.0.0.201508201514
I think I fogot to mention that I want to use Dagger dependency injection with Gluon Ignite which might be the real problem in my case as it requires Java 8 and might conflict with javafxports or something else. However, I'm not able to make full sense of the various error messages I've seen.
My tests are empty, but they aren't even run, because it fails before.
Your problem seems like a retroLambda configuration issue. If you go through the configuration page for the plugin, it states that if you don't have an environment variable set for JAVA6_HOME or JAVA7_HOME than you need to explicitly define oldJdk for the plugin to work properly.

Building library project in Android Studio that has been imported from Eclipse

I have an Android library project in Eclipse that I am trying to build with Android Studio so I can generate an .aar file for my users.
The project seems to have been imported cleanly into Android Studio using the "Import Project" option in the welcome screen.
How do I now build the module? The instructions on the dev site say that I need to change:
apply plugin: 'android'
to
apply plugin: 'android-studio'
However my build.gradle file doesn't have that line (I would have assumed that the importer would have added it(?)).
If I insert the line apply plugin: 'android-library', and try to 'Sync Project with Gradle Files', I get the error:
Gradle 'MyProject' project refresh failed
Error:C:\Users\Fred\AndroidStudioProjects\MyProject\src\main\AndroidManifest.xml
(The system cannot find the path specified)
The same happens if I try to make the project anyway.
Here's what my build.gradle looks like:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.9.+'
}
}
allprojects {
repositories {
mavenCentral()
}
}
apply plugin: 'android-library'
My searches to find a solution have failed. Anyone know what is going on?
I'm using the latest Android Studio (0.5.8)
Don't put the apply plugin: 'android-library' statement in the top-level build file. You should find an apply plugin statement in your module-level build file, and you can modify it there as necessary.
Okay. After some head scratching and more searching, I resolved all my problems I think. For the record:
I think my first import broke somehow. Partly because of the problem highlighted by Scott Barta and possibly because my project directory had spaces in it? Not totally sure.
A later import went more smoothly and I was able to sync and build without errors. However, apart from the build output in the Gradle Console, there was no evidence anything had actually happned. The artifact (ie. the .aar file) doesn't show up in the UI.
After finding this question: How to export library to Jar in Android Studio? I realised that the aar file is in fact built. It is just hidden from you. You have to root around in the file system to find the .aar. It is in:
<Library module>/build/libs/
Something that the docs don't tell you anywhere. Sigh.
Hope this helps someone else..

Eclipse workspace setup and packaging an independent jar

I have 5 regular java projects inside an eclipse workspace that have inter-dependencies and external jar-dependencies both
on libraries that exists as maven repositories and libraries that don't.
Everything is working fine inside eclipse but I have two tasks that I need to perform:
1)
Package everything into a runnable jar that I can upload to another computer and run without having to setup
the same eclipse environment there. I've been looking at gradle/maven but don't know if I need something as "complex" as that
and it seems quite alot of my setup has to workspace setup has to change to use those tools, but I may be wrong.
2)
I soon want to host the code of two of the java projects on google code so the workspace should be structured in a way
that makes that task smooth.
I'm mentioning both tasks since I don't know if they interact in some manner.
How do I solve this in a good way?
Thanks in advance.
Your description sounds like a perfect fit for Gradle's multi-project support and it's eclipse and application plug-ins. Here's a quick example of how I would approach it.
Your projects might be in the same eclipse workspace but not necessarily under the same folder, so keep in mind the following directory structure assumes you are free to move them around.
|-- component1
|-- component2
`-- myRunnableApp
The first step is to create your top-level build.gradle file and settings.gradle.
|-- build.gradle
|-- settings.gradle
|-- component1
|-- component2
`-- myRunnableApp
Your settings.gradle will instruct gradle to treat the subdirectories as subprojects.
include ':component1', ':component2', ':myRunnableApp'
Your build.gradle will contain settings that are common to all your subprojects, in this particular case we want to apply the java and eclipse plugins:
subprojects {
apply plugin: 'eclipse'
apply plugin: 'java'
repositories {
mavenCentral()
}
}
This should be enough to get you to generate eclipse projects by issuing gradle eclipse. Next you'll want to declare the dependencies between the projects thusly:
component1/build.gradle
dependencies {
// declare your 3rd party jar dependencies as needed
compile 'group:artifact:version'
}
Now you can declare dependencies between projects - this will be reflected in your eclipse project files when you generate them.
component2/build.gradle
dependencies {
compile project(':component1')
}
And finally, you'll want to apply the applications plugin to your runnable project. It will generate your jar file along with wrapper sh / bat files for unix and windows.
myRunnableApp/build.gradle
apply plugin: 'application'
mainClassName = 'my.custom.app.Main'
dependencies {
// component 1 is a transitive dependency of component 2
compile project(':component2')
}
And that's it! I expect this should be a good starting point for rolling out your own build. Check out the gradle documentation for multi-project builds, the java plugin, the applications plugin and dependency management.
Hope that helps!