How to copy gradle dependencies from a subproject in a multi-project build? - gradle

I have a Java library built with gradle for which I would like to modify the repositories it reads from and publishes to, without changing it the original library files.
So, I created a new project library (lib-internal) which is just overriding the repositories and publishing options of the library that I don't want to modify (lib-open-source).
I could force lib-internal to use the source from lib-open-source, BUT I failed to copy its dependencies.
In my build.gradle of lib-internal, I have something like this copy the sources:
sourceSets.main.java.srcDirs = [project(':lib-open-source').projectDir.toString() + '/src/main/java']
But I am looking for something similar for its dependencies.
In short, I'm looking for the correct syntax of something like:
dependencies = project(':lib-open-source').getDependencies()
I also tried something with the configurations, as suggested by the help of the getDependencies() method but can't find the correct syntax.
configurations.add(project(':lib-open-source').configurations.compileClasspath)
If I copy the dependencies block of lib-open-source into lib-internal, it works as I want to, but I want to avoid this copy-paste.
Thank you!

Related

How to create a build.gradle file that allows me to debug into my dependency

I've got a kotlin module that takes in a core dependency. I also own that dependency. I'm unique in that I own this dependency, and everyone else in my company just uses this dependency. I'd like to make a build.gradle file that will allow me to open the user module in intellij, but allow me to debug all the way down into the dependency I own. Nobody else needs to do this, so I can't just change things so they affect everybody. But I still feel there's a way I can stick both projects into one folder and have an extra build.gradle file in that parent folder that will only work for me.
Let me try and outline how I would like things to look
Module that everyone uses = MOD_A
Module that is a dependency but only I use it = MOD_B
Parent folder:
|> private build.gradle.kts file that only I use
|> MOD_A:
|> build.gradle
|> MOD_B:
|> build.gradle
How do I achieve this?
Stretch goal: how would I create gradle tasks in MOD_B that automatically become available in MOD_A?
I did try and create my own build.gradle.kts file in the parent folder, and pointed intellij at that. This did not work :(
plugins {
id("application")
}
dependencies {
implementation("MOD_A")
implementation("MOD_B")
}
I don't use IntelliJ, but this is how I would do it in general. (It works for NetBeans.)
On your system edit the settings.gradle file to add the "owned" module as an included build. You could also use a property to have this done dynamically, so the settings file can be the same for everyone, but your user gradle.properties file will define a property to enable this. See https://docs.gradle.org/current/userguide/composite_builds.html
This will automatically cause the dependency to come from your own local build and you should be able to step into the code.
e.g. settings.gradle
if (System.getProperty('USE_LOCAL_MOD_A') != null) {
includeBuild '../MOD_A'
}
then in ~/.gradle/gradle.properties you can add
systemProp.USE_LOCAL_MOD_A=true

Gradle: Project dependencies from file

I'm fairly new to Gradle, and am enamored by its task-driven approach and customizability. So I have a question that hopefully helps me understand how to do something beyond the basics.
Suppose I have a simple text file that contains information about a project's dependencies. For example, something like
- dependency1
from: 'foobar'
version: '1'
- dependency2
from: 'foobaz'
version: '1'
Note that these are not I have some code that would, from this file, generate a file along the lines as follows:
compile 'commons-lang:commons-lang 2.6'
testCompile 'org.spockframework:spock-core:1.1-groovy-2.4'
Is there a way to configure my project so that my project's dependencies are taken from this file (not exclusively)?
Do note that the text file is also used to generate other artifacts that are used by other tasks (for example, a file to be added to a Docker container), so while it may be possible to, say, declare the dependencies normally and generate the text file instead, it is not a trivial process to do so at this time.
Yes, you can write your own groovy function that parses the file and creates a List. Then you can pass this map to the dependencies closures:
List<String> compileLibraries() {
// ... parse yaml and return list
}
dependencies {
compile compileLibraries()
}
Also, to use a yaml-parsing library, consider setting up a custom gradle subproject in the special buildSrc subfolder and writing your helper function there.
See this old post for more details: https://discuss.gradle.org/t/programmatically-adding-dependencies/7575/12
And here for buildSrc projects:
https://docs.gradle.org/current/userguide/organizing_build_logic.html#sec:build_sources

Gradle: Unable to get plugin class in scope in build script

I've been creating my own gradle plugin for the last few days (partly for learning, and partly to clean up some gradle build scripts I have laying around), however I've run into a problem that I can't figure out how to fix. In my plugin jar there is an interface named me.alxandr.gradle.bintray.maven.MavenPackage, yet when I try to import it I get an error saying that it can't be found. This is really weird, because the plugin is obviously running (I'm seeing output from it, and it's tasks are registering).
Currently I've done a hack to get around this as following:
project.ext.MavenPackage = MavenPackage
This just makes MavenPackage an available name in the buildscript, which works, but I loose any editor support for it cause it's entirely dynamic. Is there any way I can (from my plugin) get the buildscript to import a package when it's applied? Like how MavenPublication is in scope without me needing to import it. If not, why can I not import classes from my plugin package?
The entire source code is available at https://github.com/Alxandr/gradle-utils. You can see an attempted here: https://github.com/Alxandr/gradle-utils/blob/master/gradle/publish.gradle#L1. The current code works as is (with the hack explained above), but I'm just looking for a better way to do this.
In order to use a class from your plugin in your Gradle script, you must add the plugin JAR to the buildscript classpath.
Here's how to do just that:
buildscript {
repositories { /* where to get your plugin jar from, e.g. mavenLocal() */ }
dependencies {
classpath 'some_group:me.alxandr.plugin:1.0.0'
}
}
import me.alxandr.gradle.bintray.maven.MavenPackage
You can find more information in the Gradle User Guide about using external dependencies in your build script

How to use Afterburner.fx with Gradle instaed of Maven 3, while leaving the original project structure of afterburner.fx

afterburner.fx for JavaFX 8 is a minimalistic (3 classes) JavaFX MVP framework based on Convention over Configuration and Dependency Injection created by Adam Bien.
afterburner.fx use Maven 3.
I would like to use it with Gradle.
How to use Afterburner.fx with Gradle instaed of Maven 3, while leaving the original project structure of afterburner.fx ?
In the build.gradle File add dependencies
dependencies {
compile group: 'com.airhacks', name:'afterburner.fx', version: afterburnerfxVersion
}
In the build.gradle File add the additional Resources (.fxml , .css , .properties)
sourceSets.main.resources.srcDirs("src/main/java").includes.addAll(["**/*.fxml", "**/*.css", "**/*.properties"])
and (re-)add all the standard Resources (in the resources folder)
sourceSets.main.resources.srcDirs("src/main/resources").includes.addAll(["**/*.*"])
Update for Gradle Version 6.8.1 : if you run gradlew with --warning-mode all there is a deprecated Message:
Copying or archiving duplicate paths with the default duplicates strategy has been deprecated. This is scheduled to be removed in Gradle 7.0.
Solution
add this line:
// from https://docs.gradle.org/6.8.1/userguide/upgrading_version_5.html#implicit_duplicate_strategy_for_copy_or_archive_tasks_has_been_deprecated
// and https://docs.gradle.org/current/userguide/java_plugin.html
// Java Plugin Task processResources(type: Copy)
processResources.duplicatesStrategy = DuplicatesStrategy.INCLUDE // allow duplicates
Thanks, this helped me a lot. I added the short form of it to dependencies:
compile 'com.airhacks:afterburner.fx:1.6.0'
Additionally I added a second line to include the files from the resources folder and not only from /java. I also added **/*.png to include png files because new Image("filename.png") wasn't working anymore.
sourceSets.main.resources.srcDirs("src/main/java").includes.addAll(["**/*.fxml", "**/*.css", "**/*.properties", "**/*.png"])
sourceSets.main.resources.srcDirs("src/main/resources").includes.addAll(["**/*.fxml", "**/*.css", "**/*.properties", "**/*.png"])
I don't know why the above two lines broke the default behavior - seems like I have to add every new file type to the above lines. :/ If anyone has a better solution please tell me.

Gradle: how does one modify a dynamically created task?

I am building an Android Library project using the Android Gradle plugin (version 0.9.2) and it appears to have a bug (reported) in that while a "provided" dependency is correctly handled (not included) in the generated aar artifact, that dependency is incorrectly included in the generated debug test apk file.
It strikes me that a reasonable workaround is to remove the dependency jar file that is added by the :preDexDebugTest task as the last step for that task. But this task is dynamically generated so getting a handle to it is eluding me at the moment, hence the question.
In your app's build.gradle file, add
afterEvaluate {
def preDexDebugTest = tasks['preDexDebugTest']
// Do something with preDexDebugTest ...
}
That way it should be possible to operate on the preDexDebugTest task.

Resources