Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide alternative for flat project structure #18644

Closed
donat opened this issue Oct 14, 2021 · 23 comments · Fixed by #19135
Closed

Provide alternative for flat project structure #18644

donat opened this issue Oct 14, 2021 · 23 comments · Fixed by #19135
Assignees
Labels
a:feature A new functionality
Milestone

Comments

@donat
Copy link
Member

donat commented Oct 14, 2021

In Gradle 7.1 Gradle deprecated the includeFlat statements in the settings file: #13891. When the decision was made, the team did not consider how widespread is the usage of these features. There are several reports on the deprecation issue explaining the usefulness when working with a large codebase, especially when the Eclipse IDE is being used.

The intended replacement for includeFlat is composite builds. We should revisit why composite builds don't work for those users and whether we can improve that feature to cover the missing use-cases.

@donat donat added the a:feature A new functionality label Oct 14, 2021
@donat donat added this to the 7.4 RC1 milestone Oct 14, 2021
@donat donat self-assigned this Oct 14, 2021
@ingokegel
Copy link
Contributor

Would it be an option to make the planned optimizations with respect to file watching dependent on the condition that no such projects are included? I'm happy with the performance that Gradle offers today, but I have a big problem if this feature goes away.

The general use case that I outlined in #13891 was this: I have projects A and B and a common project C. All of these projects live side by side in the same VCS repository. A and B include C in their settings files. In this way, C becomes a fully integrated part of both A and B.

This allows me, for example, to traverse the tree of project dependencies and collect output directories for a fat JAR file. Also, I can depend on different configurations of a project. Many other similar use cases for tightly integrating with a project are not possible with a composite build.

@danielvalore
Copy link

danielvalore commented Oct 14, 2021

I just see one option for me.... I will not update gradle version to 8. My projects will stuck in version 7.

@donat
Copy link
Member Author

donat commented Oct 19, 2021

The general use case that I outlined in #13891 was this: I have projects A and B and a common project C. All of these projects live side by side in the same VCS repository. A and B include C in their settings files. In this way, C becomes a fully integrated part of both A and B.

@ingokegel Based on your #13891 (comment), the source of the problem is that project C is not an independent build, but rather a common submodule of project A and B, and that's why you need to be able to configure it via the Project API. Is that correct?

@ingokegel
Copy link
Contributor

the source of the problem is that project C is not an independent build, but rather a common submodule of project A and B, and that's why you need to be able to configure it via the Project API.

@donat Yes, that is entirely correct.

@donat
Copy link
Member Author

donat commented Oct 21, 2021

Apart from the duplicate resource problem Stefan mentioned, can somebody give me concrete examples of how Eclipse handles flat project structures better?

@mauromol
Copy link

What I see in a project I sometimes contribute too, which uses Maven and git in a hierarchical project structure, is that, apart from the duplicate resource problem, SCM decorations are inherited by the root project.
I mean, if the root project has a subproject named A, and A has some local modifications, the root project also shows outgoing changes decorations in its icon, although there are no changes directly into that root project (or in any of its subfolders which do not contain nested projects).
I'm pretty sure the same applies to Subversion, too (at least it applied when I stopped using hierarchical projects structures for these reasons a long time ago).

If you have the flat structure, instead, the master project only shows outgoing changes if there are indeed changes in master or in any of its subfolders, of course.

@donat
Copy link
Member Author

donat commented Oct 25, 2021

A little FYI. The problem with duplicate entries in the resources dialog seems to be fixed in Eclipse 4.18: https://bugs.eclipse.org/bugs/show_bug.cgi?id=568780

@mauromol
Copy link

@donat I tried to follow the "duplicate" chain for that bug, I think the most relevant is https://bugs.eclipse.org/bugs/show_bug.cgi?id=490899, which is however marked as a duplicate of the one you're pointing to. But I'm a bit confused on how a releng bug for ECF could fix this? :-\ I'm clearly missing something.

Also, I find the following bugs are still open:
https://bugs.eclipse.org/bugs/show_bug.cgi?id=491085
https://bugs.eclipse.org/bugs/show_bug.cgi?id=568790
and I suspect they come into play in this scenario...

@donat
Copy link
Member Author

donat commented Oct 25, 2021

I've done some testing and indeed, the de-duplication is now available in Eclipse. You can filter duplicated resources with a new option in the open resource dialog:

image

image

@MikeStovallZebra
Copy link

I need some advice on how to prepare for Gradle 8 with these changes.. Our project structure looks something like this:
/code
/code/libs/libA/build.gradle
/code/libs/libB/build.gradle
/code/services
/code/services/group1/settings.gradle
/code/services/group1/serviceA/build.gradle
/code/services/group1/serviceB/build.gradle
/code/services/group2/settings.gradle
/code/services/group2/serviceA/build.gradle
/code/services/group2/serviceB/build.gradle

Right now I use a reference in our settings.gradle for something in group1 or group2 to access the libs in /libs/, like:
.projectDir = new File('../../libs/libA')

and this works fine and imports great into Eclipse/VSCode. How exactly do I get this working with a composite build? Do I need to do something with symlinks (is that even possible?). The group1 and group2 of code is a separate group of services from each other, but they use code in our shared libraries and we use local references. Some help would be appreciated since this is a bad enough issue we won't be able to move to Gradle 8.

@mauromol
Copy link

mauromol commented Nov 5, 2021

I've done some testing and indeed, the de-duplication is now available in Eclipse. You can filter duplicated resources with a new option in the open resource dialog:

Quick Search however still has the duplicated resource problem: https://bugs.eclipse.org/bugs/show_bug.cgi?id=559340

@NHendricks
Copy link

Please do NOT remove the flat project structures.
We are using only flat project structures since several years and have a lot of processes that rely on this. Losing the flat layout might also force us to stay at Gradle 7.

@danielvalore
Copy link

At least, not so fast!!!! Please reconsider doing that in a further version!!!

@slycrel
Copy link

slycrel commented Nov 23, 2021

tl;dr -- this breaks multiple repository support.

I became aware of this today. Sorry for the long post.

We have a couple of large projects that revolve around this functionality. Removing this would be a nightmare for us and require a re-architecture of our project build structure. We're using gradle 6 currently.

Let me try and describe our setup. Our build system and developers are using the same gradle files. We use individual gradle projects for the CI build system and then "umbrella" gradle projects set up as multi-project builds for development, using dependency substitution for source replacement. We also have a common standard set of custom utility jars and 3rd party things that both of these segments use as dependencies. Importantly, our source code is in multiple repositories, which I think is the biggest miss here.

My concerns... First, as of last summer IntelliJ didn't yet have good enough support for composite builds -- we couldn't get our projects to compile properly this way due to I think the way IntelliJ imported gradle. While a bit of a tangent, it is ominous that current functionality is already deprecated in 7.x and slated for removal in 8.0 before we've been able to get composite builds even working in our more advanced setup. It's on our list to revisit because this seems to be the way things are progressing.

Second, multiple repository support. Using a project with multiple repositories all under a single root means you are forced to integrate your version control system into your gradle project setup. For example, something like this is an issue:

  • ProjectA
  • ProjectB
  • ProjectC
  • Umbrella root build
    If the umbrella folder contains the above 3 projects from 3 separate repositories, how would you do that with the new setup without also using something like git submodules within the separate umbrella repo? Assuming your VCS solution even had something like that, I suspect not all do... This seems more tightly coupled than it should be.

Another multi-repo example (that we also do) is an independent, but also in-house, set of libraries. These are versioned and maintained independently, yet may be needed for debugging or need related source changes within the same project for new features or fixes. Our current developer builds can optionally include source or artifacts for these depending on their local setup. This change breaks that ability as the file hierarchy is now forced.

Finally, let me try and give you an overview of the folder hierarchy we are pulling all together in our core project. It's not an ideal setup but it's been fine. Here is the basic directory structure:

// dev/group/mainGroup/*
// dev/group/services/*
// dev/applications/*
// dev/common-libs/*

our "umbrella" root project is in the mainGroup folder. It looks for source in the other folders, each of these having one or more repositories which themselves possibly have multiple projects in them. Some of the root build dependencies are within it's own repository, as subfolders, which is great. However it also reaches into the other folders in many cases, replacing artifact dependencies as source when configured to do so. Depending on the job of a developer, using artifacts can greatly increase compilation and build times. Without the common libraries included, I count 19 sub-projects in that main project as of today.

This change seems to lean away from more complex enterprise-like setups and towards small projects. It seems unnecessarily restrictive.

I don't understand why sub-project roots can't be watched via the FS watchers in the same way the root project gets watched. I don't see an immediate reason this needs to be forced into a hierarchy other than it's easier to write that way for gradle's internals. What am I missing?

@donat
Copy link
Member Author

donat commented Nov 26, 2021

Thanks to everyone for proving us feedback and explaining all the use-cases how the flat project is used. We decided to roll back and remove the deprecation from the flat project structure.

@vladp
Copy link

vladp commented Nov 28, 2021

@donat Thank you listening for feedback and rolling back the flat project depreciation! Huge relief.

@ElvenSpellmaker
Copy link

ElvenSpellmaker commented Apr 4, 2022

@donat It seems it's still removed from Gradle 8, so what's the recommended solution for future proofing?

Currently we use a monorepo set-up and there's lots of shared code between domains so this is used heavily by us, for example testing frameworks which are used by all tests in a domain within the repo.

EDIT: It seems we're still somehow using 7.3 and so this message is still here.

Non-hierarchical project layouts
Gradle 7.1 deprecated project layouts where subprojects were located outside of the project root. However, based on community feedback we decided to roll back in Gradle 7.4 and removed the deprecation. As a consequence, the Settings.includeFlat() method is deprecated in Gradle 7.1, 7.2, and 7.3 only.

EDIT2: For anyone else having this problem update your gradle, or if using gradlew, something like this (check for the latest version): ./gradlew wrapper --gradle-version=<version>

@donat
Copy link
Member Author

donat commented Apr 5, 2022

FYI the latest version of the upgrade guide contains up-to-date information: https://docs.gradle.org/current/userguide/upgrading_version_7.html#non_hierarchical_project_structures

@ElvenSpellmaker
Copy link

@donat Hey, thanks for that, the older version documentation of course still says it's deprecated.
https://docs.gradle.org/7.3/userguide/upgrading_version_7.html#deprecated_flat_project_structure

It'd be really useful if 7.1, 7.2, and 7.3 documents could be updated to have a warning box or the like saying that from 7.4 this is no longer deprecated and people should upgrade. Otherwise the messages are quite cryptic and without coming here you don't know this has been reversed.

@donat
Copy link
Member Author

donat commented Apr 5, 2022

I understand, but the general policy is that we don't modify any resources - binaries or documentation - for previous releases.

@chiara-jm
Copy link

Hi @donat on our company, we have a structure like this for mobile apps:

roor-repository
   /apps
        /app1
        /app2
        /app3
   /modules
        /lib1
        /lib2

Where lib1 lib2, etc are submodules shared by many apps.

Then, within /apps/app1/settings.gradle.kts we have for example:

    project(":lib1").projectDir = file("../../modules/lib1/")

This is not exactly the same case as the includeFlat but quite similar.

We are still seeing a warning:

Subproject lib1 has location ‘....’ which is outside of the project root.	
This behaviour has been deprecated and is scheduled to be removed in Gradle 8.0.

We are still on gradle 7.3.3, is this deprecation also being removed on gradle 7.4?

I would also like to know if this structure makes compilation time slower, and if there is any hierarchical structure that you would recommend to improve performance on compilation time of app1 app2 etc

thanks in advance 🙏

@donat
Copy link
Member Author

donat commented Jul 21, 2022

The deprecation message should disappear after you upgrade to Gradle 7.4.

There can be performance implications of using a flat project structure. If not all files are located under the project root, the filesystem watching module needs to monitor more folders.

@hannah23280
Copy link

After reading the above, i am still confused. So is includeFlat not recommended to be used? What should the alternative recommendation then, if i still wanted to have "flat project structure"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a:feature A new functionality
Projects
None yet
Development

Successfully merging a pull request may close this issue.