Gradle nested projects setup - java

How do I set up such a project structure where I have the root project called "app", "frontend" and "backend" project inside and a count of library projects inside each. Then run a build task that would give me one backend jar and a swing (for example) jar application.
Like this:
root (App)
frontend
library
main
backend
library
main
then run: gradle build and have build/.../frontend.jar and build/.../backend.jar
I did try using include inside settings.gradle but that doesn't seem to work (at least gradle projects and intellij idea do not recognise the projects inside frontend and backend). I had:
root/settings.gradle with: include 'frontend', 'backend'
root/backend/settings.gradle with: include 'library', 'main'
and the same for frontend

There are multiple ways. one way at the root settings.gradle (gradle v7.1)
rootProject.name = 'test-prj-tree'
include 'backend'
include 'frontend'
include 'library'
include 'backend:library'
findProject(':backend:library')?.name = 'backend-lib'
include 'backend:main'
findProject(':backend:main')?.name = 'backend-main'
include 'frontend:library'
findProject(':frontend:library')?.name = 'frontend-lib'
include 'frontend:main'
findProject(':frontend:main')?.name = 'frontend-main'

In modern Gradle it's possible to includeBuild, which solves the problem perfeclty:
// root/settings.gradle.kts
rootProject.name = "root"
includeBuild("backend")
includeBuild("frontend")
// root/backend/settings.gradle.kts and root/frontend/settings.gradle.kts
include(":library")
include(":main")

Related

IntelliJ / Gradle - composite build project - how to import from different module?

I'm new to Java and am currently trying to build a cucumber / selenium project in IntelliJ that contains two modules: A library project containing page definitions, and a test project that contains the cucumber features and step definitions that talk to those page definitions. The idea is that the page definitions are a shared resource, and the tests are specific to different projects / groups. Both modules are at the same level underneath the parent project. The build is using Gradle, and the settings.gradle file for the parent looks as follows:
rootProject.name = 'composite-builds'
includeBuild 'libraryproject'
includeBuild 'testproject'
Using Gradle includeBuild on the parent project works fine and the whole project imports. However I am having no luck using the library project in my import statements in the test project. It consistently returns me these kinds of error: java: package libraryproject.pageFactory.examplePages does not exist and is clearly not seeing the library module.
What do I need to do / add in order for the test project to recognise the library project? I did try to also add the includeBuild statement in the settings.gradle for the test project but this made no difference.
The library can be found here
Update: the real reason that I cannot see the modules from the library project is that they were held in the test folder, not main.
Go to your build.gradle file
Instead of includeBuild use dependencies{compile{project(':libraryproject')}}
Inside the Root Project of libraryproject which is in your case the composite-builds. Change includeBuild to include in the settings.gradle
rootProject.name = 'composite-builds'
include ':libraryproject'
include ':testproject'
If it is in the same root:
dependencies {
compile(
project(':libraryproject')
)
}
Subfolder:
dependencies {
compile(
project(':myFolder1:myFolder2:libraryproject')
)
}

Gradle composite builds - can you have a dependency to a java sub-project from an included multi-project build?

Let's say you have 2 gradle projects. The first is a multi project with 2 java sub-projects:
rootProject
:my:subProject1
:myother:subProject2
The second gradle project is a single project that includeBuild's the root project:
secondProject
includeBuild '../rootProject'
I want to make a compile dependency of :my:subProject1 into secondProject.
So basically I want to add the following to secondProject's build.gradle file:
dependency {
compile(project(':my:subProject1'))
}
When I try to do that, it returns error: Project with path ':my:subProject1' could not be found in root project 'secondProject'
I seems like I can only resolve the dependency when I do the dependency as group:artifact:version. For example: my.root.project:subProject1:1.0.0. But why would it make me do that? Why not let me access the composite build's project hierarchy?
Only one settings.gradle should exist on the root, remove all setting.gradle files in any subfolders
Define the projects on the settings.gradle file of the root folder
include ':sub1', ':sub2', ':sub3'
Add compile project(":sub1") to your build.gradle under dependencies block:
dependencies{
compile project(":sub1")
}
This is just how these composite builds work. They basically act as if you published the other project to maven local prior to including it. so this means you need to depend on the version number of the split project.

Gradle multi project, how to deal with different rootDirs

My company is currently switching from Ant to Gradle for its Java projects, but I am stuck with a nice clean setup. Let's say I work for a company that builds websites for clients which generally use the same root libraries (core project), but have some specific code, which is put in the sub-project. Per client, we build a new sub-project, that depends on the core project. Number of clients will increase in the future.
Currently we have three projects:
A core project. This should run individually, as we want to be able to do the unit testing seperately for this.
Two sub-projects that depend on the core project, but have some own projects that are specific to the project.
I was sucessful in converting the whole ant build into a gradle build for the core project. My idea is to have all functionality and project structure in the core, and only the extra for what is actually needed in the sub-projects.
Here is a short sample of our folder structure:
-- core
- build.gradle
- settings.gradle
-- repository (our external jars used)
-- Implementation
-- source_code
-- all the core project folders
-- Projects
-- Client A
- build.gradle
- settings.gradle
-- more project specific folders
-- Client B
- build.gradle
- settings.gradle
-- more project specific folders
I use the $rootDir variable a lot. A fraction of the core's settings.gradle looks as such:
project(':CoreProjectA').projectDir = new File(rootDir, 'Implementation/Source_code/Core/coreA')
project(':CoreProjectB').projectDir = new File(rootDir, 'Implementation/Source_code/Core/CoreB')
But with many more. Also, in the core build.gradle, I refer to our repository as such:
repositories {
//All sub-projects will now refer to the same 'libs' directory
flatDir {
dirs "$rootDir/repository/lib/jaxb"
//many more dirs here
}
}
Now this all works great when I do a gradle build from the core project.
I was planning to put the next piece of code in every client's subproject build.gradle:
apply from: '../../../build.gradle'
When I run a gradle build from Client A folder, my rootDir obviously has changed, and now, all my paths cannot be found anywhere.
Is there any way to set this up in a nice clean way? So that every future sub project added can always use the same structure? Or will I have to give each sub-project its own build.gradle and settings.gradle entirely?
I know the last option could work, but it is a lot of overhead, and just doesn't seem nice and clean to me at all..
Thanks in advance!
I recently worked on a similar configuration, so let me explain me how I build the Gradle infrastructure. Since you mentioned a lot of requirements, I hope that I'll miss any of them and you can apply my scheme to your problem.
General
We actually use build systems (like Gradle) to let them take care of any dependencies (projects, modules, tasks). So why should we define a depedency in something like a filesystem hierarchy, if we can simply define it in Gradle?
I would avoid using paths as much as possible (convention over configuration) and try to stick to Gradle projects for both the build scripts and the dependencies.
Also, if you define dependencies in your core gradle.build, you should just call this gradle file, even if you only want to build a subproject. Your apply from: '../../../build.gradle' destroys the whole Gradle logic. Instead you should use something like gradle :sub1:build to only build the first subproject.
First approach (with core as root project)
Filesystem structure:
core/
build.gradle
settings.gradle
src/
...
sub1/
src/
...
build.gradle [optional]
sub2/
src/
...
build.gradle [optional]
Core settings.gradle:
include 'sub1'
include 'sub2'
Core build.gradle:
allprojects {
apply plugin: 'java'
repositories {
// define repos for all projects
}
}
subprojects {
dependencies {
// let subprojects depend on core
compile rootProject
}
}
project(':sub1') {
// define anything you want (e.g. dependencies) just for this subproject
// alternative: use build.gradle in subproject folder
}
Second approach (all projects independent)
Filesystem structure:
core/
src/
...
build.gradle [optional]
sub1/
src/
...
build.gradle [optional]
sub2/
src/
...
build.gradle [optional]
build.gradle
settings.gradle
Root settings.gradle:
include 'core'
include 'sub1'
include 'sub2'
Root 'build.gradle'
subprojects {
apply plugin: 'java'
repositories {
// define repos for all projects
}
}
configure(subprojects.findAll {it.name != 'core'}) {
dependencies {
// Add dependency on core for sub1 and sub2
compile project(':core')
}
}
project(':sub1') {
// define anything you want (e.g. dependencies) just for this subproject
// alternative: use build.gradle in subproject folder
}
This approach provides great flexibility, since every dependency logic is handled by Gradle and you'll never have to copy anything to another position. Simply change the dependency and you are fine.
Sources
Gradle Tutorial on Multi-project Builds
Question in Gradle Forum
It looks like you have extra settings.gradle inside subprojects. That makes Gradle think the sub-project is a standalone one. If you remove settings.gradle from subprojects, Gradle will look for it up the filesystem hierarchy, will find one in core project, will create correct multimodule project and all the paths should work properly.
So, just remove extra settings.gradle files and your build will work fine. Having build.gradle in subprojects is perfectly fine.
I want to thank Nikita and especially lukegv for his detailed answer, but I went with a different approach ultimately.
I didn't want to have one main gradle build and extend it each time we have a new project. Also, I wanted to keep it simple and logical for my colleagues if they want to create a build for one of the projects.
Therefor, I kept the structure I had as described above. In the root gradle.settings but changed the
project(':CoreProjectA').projectDir = new File(rootDir, 'Implementation/Source_code/Core/coreA')
project(':CoreProjectB').projectDir = new File(rootDir, 'Implementation/Source_code/Core/CoreB')
into:
project(':CoreProjectA').projectDir = new File(customRootDir, 'Implementation/Source_code/Core/coreA')
project(':CoreProjectB').projectDir = new File(customRootDir, 'Implementation/Source_code/Core/CoreB')
In each project I have a properties.gradle with the customRootDir filled in (relatively to the projects directory).
It all works like a charm. I can go into any project folder and produce builds, while using the functionality of the root's build.gradle.

IntelliJ and Android Gradle dependencies - unable to find module

I have following directory structure:
D:\PROJECT
+---javaGradleProject1
+---javaGradleProject2
+---javaGradleProject3
\---AndroidProject
| build.gradle
| settings.gradle
\---AndroidModule
build.gradle
Android module depends on all of java gradle projects that are at the same level in root directory as AndroidProject.
In AndroidProject/settings.gradle I have:
include ':AndroidModule'
include 'javaGradleProject1'
project(':javaGradleProject1').projectDir = new File(rootDir, '../javaGradleProject1')
include 'javaGradleProject2'
project(':javaGradleProject2').projectDir = new File(rootDir, '../javaGradleProject2')
include 'javaGradleProject2'
project(':javaGradleProject2').projectDir = new File(rootDir, '../javaGradleProject2')
And then in AndroidProject/AndroidModule/build.gradle I have dependencies set like this:
compile project(':javaGradleProject1')
compile project(':javaGradleProject2')
compile project(':javaGradleProject3')
This structure of dependency perfectly works and project builds when I invoke
gradle build
on AndroidProject/build.gradle.
But when I try to synchronize my IntelliJ with current gradle dependency settings I receive
Error: Unable to find module with Gradle path ':javaGradleProject1'
Error: Unable to find module with Gradle path ':javaGradleProject2'
Error: Unable to find module with Gradle path ':javaGradleProject3'
and because of that my project cannot be run from Run Configurations (it does not compile at all in IDE). I was trying to add these dependencies manually by hitting F4 and module dependencies but after synchronization all of my changes are overwritten (actually, IntelliJ just removes it).
Is there anything wrong in my gradle structure?
I have tested it on IntelliJ IDEA 14.1.4 and Android Studio 1.3.
I was able to solve this by deleting the settings.gradle file from every Gradle project that I wanted to use as dependency (clearing the contents of this file was not enough).
NOTE: As I have little knowledge of Gradle and Android Studio, I cannot provide information about why the presence of this file does not allow Android Studio to include the Gradle project as a module.
Add a colon (:) before the names of your modules when you add it in settings.gradle, e.g. for the first one, change this:
include 'javaGradleProject1'
project(':javaGradleProject1').projectDir = new File(rootDir, '../javaGradleProject1')
to this:
include ':javaGradleProject1'
project(':javaGradleProject1').projectDir = new File(rootDir, '../javaGradleProject1')
Now in addition to compiling, IntelliJ / Android Studio should give you code completion.
In my case I had to change the external module name to lowercase only.
Right click project, Select
"Configure Project Subset ..."
and select your module, rebuild your project.
Tried all the available solutions, and in last I have commented the include ':app' in settings.gradle and this resolved the issue in my case
In my case non of the answers above resolved it.
Finally, I went to settings.gradle file and inside the dependencyResolutionManagement block, I changed the repositoriesMode to "PREFER_PROJECT"
repositoriesMode.set(RepositoriesMode.PREFER_PROJECT)
That was all I did and it worked like magic, maybe such can help you too, you can try it out.

How to create Android library in Android Studio [duplicate]

How do I create an Android Library Project (e.g. com.myapp.lib1) and the application project (e.g. com.myapp.app) and make the build system include com.myapp.lib1 on the application project?
I went to the Project Structure -> Modules -> My App project and added a dependency to the lib project. IntelliJ now can recognize classes from the lib project when used in the app project, but when I run the app project, there are errors like:
Gradle: error: package com.myapp.lib1 does not exist
I wonder why there is no example of stand alone jar project.
In eclipse, we just check "Is Library" box in project setting dialog.
In Android studio, I followed this steps and got a jar file.
Create a project.
open file in the left project menu.(app/build.gradle): Gradle Scripts > build.gradle(Module: XXX)
change one line: apply plugin: 'com.android.application' -> 'apply plugin: com.android.library'
remove applicationId in the file: applicationId "com.mycompany.testproject"
build project: Build > Rebuild Project
then you can get aar file: app > build > outputs > aar folder
change aar file extension name into zip
unzip, and you can see classes.jar in the folder.
rename and use it!
Anyway, I don't know why google makes jar creation so troublesome in android studio.
To create a library:
File > New Module
select Android Library
To use the library add it as a dependancy:
File > Project Structure > Modules > Dependencies
Then add the module (android library) as a module dependency.
Run your project. It will work.
Google’s Gradle Plugin recommended way for configuring your gradle files to build multiple projects has some shortcomings If you have multiple projects depending upon one library project, this post briefly explain Google’s recommended configuration, its shortcomings, and recommend a different way to configure your gradle files to support multi-project setups in Android Studio:
An alternative multiproject setup for android studio
A Different Way :
It turns out there’s a better way to manage multiple projects in Android Studio. The trick is to create separate Android Studio projects for your libraries and to tell gradle that the module for the library that your app depends on is located in the library’s project directory. If you wanted to use this method with the project structure I’ve described above, you would do the following:
Create an Android Studio project for the StickyListHeaders library
Create an Android Studio project for App2
Create an Android Studio project for App1
Configure App1 and App2 to build the modules in the StickyListHeaders project.
The 4th step is the hard part, so that’s the only step that I’ll describe in detail. You can reference modules that are external to your project’s directory by adding a project statement in your settings.gradle file and by setting the projectDir property on the ProjectDescriptor object that’s returned by that project statement:
The code one has to put in settings.gradle:
include ':library1'
project(':library1').projectDir = new File('../StickyListHeader/library1')
If you’ve done this correctly, you’ll notice that the modules referenced by your project will show up in the project navigator, even if those modules are external to the project directory:
This allows you to work on library code and app code simultaneously. Version control integration also works just fine when you reference modules externally this way. You can commit and push your modifications to the library code just like you can commit and push modifications to your app code.
This way of setting up multiple projects avoids the difficulties that plague Google’s recommended configuration. Because we are referencing a module that is outside of the project directory we don’t have to make extra copies of the library module for every app that depends on it and we can version our libraries without any sort of git submodule nonsense.
Unfortunately, this other way of setting up multiple projects is very difficult to find. Obviously, its not something you’ll figure out from looking at Google’s guide, and at this point, there’s no way to configure your projects in this way by using the UI of Android Studio.
Check out this link about multi project setups.
Some things to point out, make sure you have your settings.gradle updated to reference both the app and library modules.
settings.gradle: include ':app', ':libraries:lib1', ':libraries:lib2'
Also make sure that the app's build.gradle has the followng:
dependencies {
compile project(':libraries:lib1')
}
You should have the following structure:
MyProject/
| settings.gradle
+ app/
| build.gradle
+ libraries/
+ lib1/
| build.gradle
+ lib2/
| build.gradle
The app's build.gradle should use the com.android.application plugin while any libraries' build.gradle should use the com.android.library plugin.
The Android Studio IDE should update if you're able to build from the command line with this setup.
For Intellij IDEA (and Android Studio) each library is a Module. Think of a Module in Android Studio as an equivalent to project in Eclipse. Project in Android Studio is a collection of modules. Modules can be runnable applications or library modules.
So, in order to add a new android library project to you need to create a module of type "Android library". Then add this library module to the dependency list of your main module (Application module).
The simplest way for me to create and reuse a library project:
On an opened project file > new > new module (and answer the UI questions)
check/or add if in the file settings.gradle: include ':myLibrary'
check/or add if in the file build.gradle:
dependencies {
...
compile project(':myLibrary')
}
To reuse this library module in another project, copy it's folder in the project instead of step 1 and do the steps 2 and 3.
You can also create a new studio application project
You can easily change an existing application module to a library module by changing the plugin assignment in the build.gradle file to com.android.library.
apply plugin: 'com.android.application'
android {...}
to
apply plugin: 'com.android.library'
android {...}
more here
You can add a new module to any application as Blundell says on his answer and then reference it from any other application.
If you want to move the module to any place on your computer just move the module folder (modules are completely independent), then you will have to reference the module.
To reference this module you should:
On build.gradle file of your app add:
dependencies {
...
compile project(':myandroidlib')
}
On settings.gradle file add the following:
include ':app', ':myandroidlib'
project(':myandroidlib').projectDir = new File(PATH_TO_YOUR_MODULE)
Don't forget to use apply plugin: 'com.android.library' in your build.gradle instead of apply plugin: 'com.android.application'
Documentation Way
This is the recommended way as per the advice given in the Android Studio documentation.
Create a library module
Create a new project to make your library in. Click File > New > New Module > Android Library > Next > (choose name) > Finish. Then add whatever classes and resourced you want to your library.
When you build the module an AAR file will be created. You can find it in project-name/module-name/build/outputs/aar/.
Add your library as a dependency
You can add your library as a dependency to another project like this:
Import your library AAR file with File > New Module > Import .JAR/.AAR Package > Next > (choose file location) > Finish. (Don't import the code, otherwise it will be editable in too many places.)
In the settings.gradle file, make sure your library name is there.
include ':app', ':my-library-module'
In the app's build.gradle file, add the compile line to the dependencies section:
dependencies {
compile project(":my-library-module")
}
You will be prompted to sync your project with gradle. Do it.
That's it. You should be able to use your library now.
Notes
If you want to make your library easily available to a larger audience, consider using JitPac or JCenter.
Had the same question and solved it the following way:
Start situation:
FrigoShare (root)
|-Modules: frigoshare, frigoShare-backend
Target: want to add a module named dataformats
Add a new module (e.g.: Java Library)
Make sure your settings.gradle look like this (normally automatically):
include ':frigoshare', ':frigoShare-backend', ':dataformats'
Make sure (manually) that the build.gradle files of the modules that need to use your library have the following dependency:
dependencies {
...
compile project(':dataformats')
}
Purpose: Android library at single place - Share across multiple projects
http://raevilman.blogspot.com/2016/02/android-library-project-using-android.html
As theczechsensation comment above I try to search about Gradle Build Varians and I found this link: http://code.tutsplus.com/tutorials/using-gradle-build-variants--cms-25005
This is a very simple solution. This is what I did:
- In build.gradle:
flavorDimensions "version"
productFlavors {
trial{
applicationId "org.de_studio.recentappswitcher.trial"
flavorDimension "version"
}
pro{
applicationId "org.de_studio.recentappswitcher.pro"
flavorDimension "version"
}
}
Then I have 2 more version of my app: pro and trial with 2 diffrent packageName which is 2 applicationId in above code so I can upload both to Google Play. I still just code in the "main" section and use the getpackageName to switch between to version. Just go to the link I gave for detail.
There are two simplest ways if one does not work please try the other one.
Add dependency of the library inside dependency inside build.gradle file of the library u r using, and paste ur library in External Libraries.
OR
Just Go to your libs folder inside app folder and paste all your .jar e.g Library files there Now the trick here is that now go inside settings.gradle file now add this line "include ':app:libs'" after "include ':app'" It will definitely work...........:)
In my case, using MAC OS X 10.11 and Android 2.0, and by doing exactly what Aqib Mumtaz has explained.
But, each time, I had this message : "A problem occurred configuring project ':app'. > Cannot evaluate module xxx : Configuration with name 'default' not found."
I found that the reason of this message is that Android 2.0 doesn't allow to create a library directly. So, I have decided first to create an app projet and then to modify the build.gradle in order to transform it as a library.
This solution doesn't work, because a Library project is very different than an app project.
So, I have resolved my problem like this :
First create an standard app (if needed) ;
Then choose 'File/Create Module'
Go to the finder and move the folder of the module freshly created in your framework directory
Then continue with the solution proposed by Aqib Mumtaz.
As a result, your library source will be shared without needing to duplicate source files each time (it was an heresy for me!)
Hoping that this help you.

Categories

Resources