How to have multiple filesystems in a single gradle build? - gradle

First off, I'm a total noob with both Gradle and Groovy. :-)
I'm trying to port an existing project from an ant-based build to using Gradle. The problem I'm having is that my source code is stored in two different filesystems (both git repos). I've managed to get the Gradle subproject configuration working for modules that are in the same filesystem, but I can't seem to link subprojects across the two different filesystems. I have a need for projects in filesystem 'A' (my application repo) to depend on projects in filesystem 'B' (my library repo).
Is there any way to get Gradle to handle dependencies across fileystem boundaries?
Any help would be greatly appreciated...

When you say filesystem I'm guessing you mean they are in two different folders once checked out.
There's 2 ways to achieve what you want:
One is to build project B and publish the Jars into a 'repository' that project A has access to. I achieve this by copying the jars from projectB/build/libs to a projectA/lib folder and adding that lib folder as a repository in the project A's build file like so:
repositories {
flatDir {
dirs 'lib'
}
}
It's a little manual but it does the trick.
The other way is to use Gradle's new Composite Build feature. It allows you to configure Project A to include Project B. This avoids the manual copying of jars. I haven't used this approach myself because it is very new so I can't vouch for how well it works.

Related

When working on a project and one of it's dependency in parallel how to load it from the file system

I'm working on a java dependency that I publish on GitLab via gradle. In parallel I also work on some projects dependent of it.
When I need to do a change in the parent I have to wait for my CI/CD to be over before I can keep developing the childs. There is most certainly a way to tell gradle 'check there before online' but all I've found until now is to do that with local jar but not raw source files.
I tried most of the things in How to make Gradle repository point to local directory but without success as gradle is excepting a maven repo structure with some pom.xml files.
So how could I achieve something like this ?
After rethinking the problem and studying a bit more gradle/maven I found the solution.
Just execute the task gradle publishToMavenLocal in the parent project. Then in the dependent project add mavenLocal() to your list of repo. That's all you have to do.
I'm still looking for a way to make gradle build and publish the parent automatically on the child's build. But it's already much more practical like this?

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

Do I need the the Maven wrapper for submodules?

If I have a parent Maven project that contains the Maven wrapper files, is there any reason to also including the wrappers in the submodules of this project? Does it really matter? Any possible side effects of doing this I need to look out for? I only plan on running Maven commands from the parent project, but some day I may want to break the submodules up into their own separate projects.
Edit: To be clear, I'm talking about mvnw, mvnw.cmd, and the .mvn directory
The Maven Wrapper is only needed on the root level the project. The intention is to define a the version which will be used for building the project by downloading it automatically.
If you later decide to split up the project this would result in creating separated repositories (Git) and this means you have for each of such projects an other root which mean there it would make sense to have the maven wrapper.

Gradle search local maven or gradle repository

I am using gradle and its local repository is at \.gradle\caches\modules-2\files-2.1 which has all the downloaded jar but not my modules.Is there any specific place I should be searching it for ?
I need it as is in settings.gradle I am having a dependency path specified like :
include ':model'
project (':model').projectDir = new File(settingsDir, './model')
in a new project. Also I don't want to give path in that way because if I have a dependency from multiple projects on this project then mentioning path will be difficult and weird.
How can I make gradle search it from local maven or gradle repositories.
I'm still not sure what is being asked here, and I suspect there is some confusion over how multi-project builds work. So I'm going to attempt to provide a general-purpose answer.
The first question you need to answer is whether you're interested in dependencies between projects that are part of the same build — as in part of a multi-project build — or in separate builds.
Project dependencies (multi-project builds)
Project dependencies are covered in the user manual and only apply to multi-project builds. They use a logical path, using colons as 'path' separators, to specify the location of the target module, like so:
dependencies {
implementation project(":model")
}
At this point, Gradle needs to know where ":model" exists on the file system. There's no getting around that. You have a few options:
Follow the convention of directory structure matching the logical path structure, i.e. have a MyBigProject/model directory containing the ":model" child project
Specify the file path of ":model" in settings.gradle, e.g. with project(":model").projectDir = new File(rootDir, "unusual/path/to/model")
Automate the discovery of projects
The most common approach is the first one. The second is not unusual, particularly if you want to put child projects into a separate directory, like subprojects — something the build of Gradle itself does. I haven't seen the last option done, and I don't know whether it runs into problems.
For the sake of completeness, and at your own risk if you use something like it, here's an example of automatic discovery of projects in the settings.gradle file:
rootDir.eachDir { File dir ->
if ("build.gradle" in dir.listFiles()*.name) {
include dir.name
}
}
This fragment basically looks for directories within the root project folder that have a build.gradle file in them and adds them as child projects. The child projects' directory names become the projects' names.
It's not particularly clever, and you should really use different names for the build files, but it may give you some ideas to work with.
Non-project dependencies
As with project dependencies, Gradle needs to know where to get the corresponding JAR or other form of artifact for a specified module. You normally specify Maven Central or something similar for this, but there are other useful, but less common, options:
Copy a project's artifacts into the local Maven repository — both the Maven Plugin and Maven Publish Plugin support this
Publish to a Maven-compatible repository using a file:// URL rather than an HTTP/HTTPS one, which protects your projects from corruption of Maven Local
Worth noting is that Gradle supports composite builds that allow you to substitute a normal dependency with (effectively) a project dependency from another build. So if model were part of a separate build but you had the source code and build locally, you could make changes and immediately test them in another build's project without going through the whole "install" intermediate step that's common in the Maven world (and Gradle pre-composite-builds).
Hope all this makes sense.

How to make IntelliJ reference a local project for a dependency?

Working in a multi-module Maven project, call it "app." I need to work on the source of one of the dependencies, call it "lib", and be able to easily test/debug "app" against my changes in "lib."
In Eclipse this is an option for its Maven and Gradle plug-ins, and is obvious since Eclipse doesn't bind the concepts of "workspace" and "project" as tightly as IntelliJ does. When I cloned the repo for "lib", IntelliJ offered to create a new project for it, but how do I force "app" to use the local working copy of "lib" for compilation and runtime?
To put it another way, can IntelliJ basically encapsulate doing build install on "lib" behind the scenes so that "app" uses the updated (snapshot) of it?
The obvious, cleanest choice would be to combine the two projects into a common Maven multi-pom project. If that is something you can't do (perhaps the projects belong to different teams etc.), then I could imagine you could fake it by using symlinks.
Create a wrapper project with just a pom file and two modules. Instead of folders for the modules, use symbolic links to the actual file locations. Obviously the reactor root pom would not be the parent pom.
Now open the wrapper pom as IntelliJ project.
I don't know if this works, but it's worth a try.

Resources