Gradle - Custom task classes in a custom folder within the same project - gradle

I have a custom Gradle Task in my project under /buildSrc/src/main/groovy. Since this folder is in parallel to the main project's /src/main/groovy folder, my IDE considers /buildSrc as a sub-project.
From the documentation, I understand the custom tasks can reside either under /buildSrc or under a separate project.
I don't want to create a new project, so I am thinking of keeping it somewhere other than /buildSrc. Is it possible to achieve this?

No, it isn't possible. The IDE likely considers buildSrc a subproject in order to offer IDE support for developing custom tasks and plugins (not because the directory is "parallel" to anything).

Related

Gradle monobuild and map of jar files for all gradle composite builds

We have a directory structure like so
java
build/build.gradle (This does NOT exist yet, but we want this)
servers
server1/build.gradle
server2/build.gradle
libraries
lib1/build.gradle
lib2/build.gradle
We have 11 servers and 14 libraries with varying uses of dependencies. EACH server is a composite build ONLY depending on libraries (we don’t allow servers to depend on each other). In this way, as our mono-repo grows, opening up server1 does NOT get slower and slower as more and more gradle code is added(ie. gradle only loads server1 and all it’s libraries and none of the other libraries OR servers are loaded keeping things FAST).
Ok, so one problem we are running into is duplication now which is why we need build/build.gradle file AND we want EVERY module in our mono repo to include that somehow for a few goals(each goal may need a different solution)
GOAL 1: To have an ext { … } section containing a Map of Strings to gradle dependencies much like so
deps = [
'web-webserver': "org.webpieces:http-webserver:${webpiecesVersion}",
'web-webserver-test': "org.webpieces:http-webserver-test:${webpiecesVersion}",
'web-devrouter': "org.webpieces:http-router-dev:${webpiecesVersion}"
]
In this way, we want ALL our projects to them import dependencies like so
compile deps['web-webserver']
GOAL 2: We want to 'include' a standard list of plugins so we are versioning all gradle plugins the same across the repo. While the above configures all jars to avoid jar hell in a mono-repo, we would like to do the same with just this section
plugins {
id 'com.github.sherter.google-java-format' version '0.9'
}
Of course, it each project may also want to add a few more plugins OR even not depend on this section(in case of an emergency and trying to just get the job done).
GOAL 3: We want checkstyle configuration (or any plugin config) to be defined the SAME for all projects (eventually!!!). We would like the checkstyle gradle to live in a common area but have all libraries somehow pull it in. Again, it would be nice for it to be optional in that, I can pull the gradle section into my build.gradle OR can create a new one in case of emergencies so I don't have to fix all projects in the monorepo right away.
IDEALLY, perhaps I kind of want configuration injection where when I run server1/build.gradle, it actually runs java/build/build.grade as it’s parent somehow but with overrides (IF I declare 'extends xxx.gradle' maybe) then all libraries it uses also use java/build/build.gradle as their parent. I am not sure this is possible or feasible. I am pretty sure 'extends xxx' doesn't exist in gradle.
Are any of these GOALS possible?
thanks,
Dean
I have been working on a monorepo with the exact same requirement as you, using gradle composite builds as well. The way we have solved this problem is by using pre compiled plugins
You need to do a new gradle project with only the code you want to share. This will create a plugin, that you can just add as a composite build and apply to the other projects.
I'm a bit confused by why you don't just use a "standard" gradle top level build file and compose the others as subprojects.
This solves all 3 of your goals
If you are concerned by build speed, you can target each server individually simply by running
./gradlew :server1:build
But if you are not able to do this for some reason you can use the apply from: syntax as described here

Identifying the list of projects that have been invoked in gradle

I have a settings plugin that is multi-project aware. It currently applies itself to every project identified in settings.gradle. However, this is a problem because each subproject doesn't have the same configuration, and I control some plugin behavior through project properties set on the command-line via -P.
The problem is that this fails on projects that don't have the configuration necessary to use that property, and I know of know way to apply a property to a specific subproject via the command-line.
Instead of iterating over settings.gradle.allprojects, is there a way to know what projects have actually been included as part of the build? For example when I do:
gradle :subproject-name:build :other-subproject-name:build -PsomeProperty
I would like to know that only subproject-name and other-subproject-name were called so that I can apply the settings plugin to only those projects.
Or is there a way to "scope" project properties somehow, to only a particular project?
... is there a way to know what projects have actually been included as part of the build?
This is a misconception. All projects are part of the build when settings.gradle includes them, and they'll all get configured so they have an associated Project.
What you're ultimately looking for is, given the tasks that will execute, what are the subprojects who own those tasks? To do that, you can grab Gradle's task graph, and for all of the tasks that will execute, find the project that owns each task.
gradle.taskGraph.whenReady { graph ->
def projects = graph.allTasks.collect { it.project }.toSet()
projects.each {
println "Project is being used in this build: " + it
}
}

How to load gradle properties from central storage

I have multiple projects that are build with gradle. All projects are basically using the same build logic and many common properties, only certain variables are different between projects.
I'd like to centralize all common parts and "include" that in every gradle project, so I don't have to touch every gradle project when some commonly used properties change. I'd also like to have the ability to override properties for special cases.
What's the gradle way to do this?
What's the gradle way to do this?
Simple answer: Initialization scripts
Properties are the best way to set user-/system-specific (using the gradle.properties file in the Gradle user home directory) or project-specific (using the gradle.properties file in the project directory) parameters. If you want to setup a consistent environment across development systems (local machines, CI, ...) and even multiple users (different credentials), you can develop one or more initialization scripts.
You can place them at your Gradle user home directory (this way they will be used by all Gradle installations) or at your Gradle install directory (for one specific installed Gradle version).
Project and system properties can be set from an initialization script via a StartParameter object:
startParameter.with {
projectProperties['key'] = 'value'
systemPropertiesArgs['key'] = 'value'
}
Both projectProperties and systemPropertiesArgs are simple maps.

How to copy file from buildSrc into main build

I have a custom task in buildSrc that, among other things, I want to copy a file from buildSrc into the main build. However, when actually running the custom task, the buildSrc project appears to be pretty much invisible, e.g. I can't reference it as a project. How does one refer to and copy a file from the buildSrc project to the main project?
You are correct that the main projects can not see buildSrc. buildSrc is run as a separate project.
The outputs of buildSrc project are put onto the classpath of the main Gradle projects.
One solution then is to generate a Jar artifact with all of your resources, and then use the classpath resource loader in the main projects to access the files you need.
A second option might be to just manually hard code the buildSrc path into your main projects. Of course you can not access it as project(:buildSrc') because it is not valid. The better option is to use file("${rootProject}/buildSrc/") (Not tested).

Eclipse Plugin project: manage external files

I'm developing a plugin for Eclipse (4.2 on windows) that uses a bunch of external files (batch scripts, xml files, ecc).
I'm asking if there is a good method to manage those files inside the project in order to:
keep all the plugin resources inside the project for version control in SVN
possibly have an automated plugin installation (including those files outside the plugin jar)
Edit: Can an additional "Feature Project" be a solution?
Instead of having a project I would manage two: one for the plugin and one for the "feature" that references the plugin and gathers the non-plugin data.
In that case, I see that eclipse "Features" have an "installation" section (in "feature.xml"). How could I specify for each "non-plugin" file the install path location?
I'm using nested projects for this.
Create a parent project that will contain everything. For each sub-project, deactivate the default location when you create it and select the parent project's root folder instead.
Here is an example: http://git.eclipse.org/c/tmf/org.eclipse.xtext.git/tree/
It doesn't have a .project file in the root but having one doesn't hurt.
Just remember to import the sub-projects before you start working on them. Otherwise, you and Eclipse might get confused.

Resources