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

Typesafe project accessors not working in root build script file #16636

Closed
elect86 opened this issue Mar 24, 2021 · 6 comments
Closed

Typesafe project accessors not working in root build script file #16636

elect86 opened this issue Mar 24, 2021 · 6 comments
Labels
a:investigation Issues requiring decision or investigation affects-version:7.0
Milestone

Comments

@elect86
Copy link

elect86 commented Mar 24, 2021

The new accessors do not work in my root build script file.

If I test them in the corresponding subproject script, then it's fine.

Current Behavior or error

The accessors are actually properly generated, but as soon as I try to use them, then the sync fails:

Extension with name 'projects' does not exist. Currently registered extension names: [ext, defaultArtifacts, sourceSets, reporting, java, javaToolchains, kotlin, kotlinTestRegistry, shadow, publishing]

Steps to Reproduce

Clone this branch and sync

Your Environment

7.0 rc1 bin
Build scan URL

@elect86 elect86 added a:investigation Issues requiring decision or investigation affects-version:7.0 labels Mar 24, 2021
@big-guy big-guy added this to the 7.0 RC2 milestone Mar 24, 2021
@tbroyer
Copy link
Contributor

tbroyer commented Mar 25, 2021

Looks to me like it's the same cause as for #16634, where the problem seems to not be the "root build script file" per se, but actually subprojects' blocks inside that file (either subprojects {} or project(":foo") {}). The Kotlin DSL extension property then applies to the subproject's Project instance that's this in the block, and not to the root project; so a workaround would be to use rootProject.projects.core.

@melix
Copy link
Contributor

melix commented Mar 25, 2021

Yes, @tbroyer is correct. Nowadays it's considered a bad pattern to reach out to other project's state using allprojects or subprojects. In particular here to declare dependencies. It's better to have the dependencies declared in each project separately. If it's to avoid repetition, you have 2 options:

  1. use a bundle and declare the bundle as a dependency, for dependencies which are declared on the same configuration
  2. use convention plugins to declare the dependencies (in which case, unfortunately, you wouldn't be able to use typesafe accessors)

@elect86
Copy link
Author

elect86 commented Mar 25, 2021

Uh, ok

but why is considered bad pattern?

@melix
Copy link
Contributor

melix commented Mar 25, 2021

There are different reasons. First it makes it difficult to decouple projects. Say you want to extract one project in a composite build, or even its own repository. If you apply cross-configuration like this, it's difficult to do.

Second, if you open a build script of a project, it's difficult to figure out what has already been configured. For example, if I open foo/build.gradle and that you see:

plugins {
   id 'java-library'
}

it's immediately obvious what the project is and what plugins are applied to it. We can reason about it. Except if you do cross-configuration, because then, any other project can mutate the state of this project, add more plugins, and you would never know. In the end the build breaks and it's super hard to figure out why. In other words: keeping the plugins {...} block sane is important as it provides insights about what is applied to a project.

Another reason is ordering. By applying cross-configuration, you can never really know when something is going to be configured, which often implies dirty workarounds like afterEvaluate. Worse, the behavior will be inconsistent if you use configure on demand or not.

Last, there's a performance and isolation aspect: by doing cross-configuration it prevents the engine from doing some optimizations. With the configuration cache we're moving away from this pattern, as it allows us to reason project per project and therefore enable optimizations like intra-project parallelism by default.

@melix
Copy link
Contributor

melix commented Mar 29, 2021

We don't plan to fix this short term. We discourage use of cross-configuration and there are 2 workarounds:

  1. use rootProject.projects to access the catalog
  2. use the Groovy DSL instead, in which case it doesn't matter if the extension exists or not

@TWiStErRob
Copy link
Contributor

@melix is this subprojects anti-pattern documented somewhere in detail? (even a blog)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a:investigation Issues requiring decision or investigation affects-version:7.0
Projects
None yet
Development

No branches or pull requests

5 participants