# Implicit project dependencies

**URL:** <https://discuss.gradle.org/t/implicit-project-dependencies/40207>\
**Category:** Help/Discuss\
**Created:** [June 11, 2021, 3:02pm UTC](https://discuss.gradle.org/t/implicit-project-dependencies/40207 "2021-06-11T15:02:34Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![Steve\_Ebersole](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/steve_ebersole/32/9763_2.png) [@Steve\_Ebersole](https://discuss.gradle.org/u/Steve_Ebersole)\
**Post date:** [June 11, 2021, 3:02pm UTC](https://discuss.gradle.org/t/implicit-project-dependencies/40207/1 "2021-06-11T15:02:35Z")

</div>

TLDR; Best way to express “implicit” project dependency?

I am working on a plugin which implies dependency (`Project#evaluationDependsOn` sense) between 2 projects. I am having difficulty getting the ordering to work properly.

Long story short, this dependency is defined by the application of a plugin and then the configuration of that plugin’s DSL extension. Not to get too crazy, a simple build example would look like this:

```gradle
plugins {
    id 'jakarta-transformer'
}

jakartaTransformation {
    shadow( project( ':hibernate-core' ) ) {
        ...
    }
}

```

The project applying the plugin needs the evaluation of `:hibernate-core` to happen first.

I started playing around with `afterEvaluate` to achieve this, so I could e.g. delay “fully” applying the plugin until after `:hibernate-core` is evaluated. The trouble I ran into is that `afterEvaluate` calls are completely ignored when the project is already evaluated (which seems utterly wrong to me, but that’s a different discussion[1]). And, as far as I could tell, there is no way to actually ask the Project if it is already evaluated.

To better understand how evaluating projects and applying plugins works timing-wise I wrote a simple project with 3 java sub-projects and a `buildSrc` plugin.

The root project looks like:

```gradle
plugins {
    id 'the-plugin'
}

allprojects {
    ...
    afterEvaluate {
        getLogger().lifecycle( "Finished evaluation: `{}`", path )
    }
}

subprojects {
    beforeEvaluate {
        getLogger().lifecycle( "Before evaluation: `{}` (from root)", path )
    }
}

```

All of the sub-projects are basically the same:

```gradle
plugins {
    id 'java-library'
    id 'the-plugin'
}

rootProject.afterEvaluate {
    getLogger().lifecycle( "Finished root-project evaluation (callback from `{}`)", path )
}

```

Which produces the output:

```gradle
> Configure project :
Applying plugin to `:`
Finished evaluation: `:`

> Configure project :hibernate-core
Before evaluation: `:hibernate-core` (from root)
Applying plugin to `:hibernate-core`
Finished evaluation: `:hibernate-core`

> Configure project :hibernate-envers
Before evaluation: `:hibernate-envers` (from root)
Applying plugin to `:hibernate-envers`
Finished evaluation: `:hibernate-envers`

> Configure project :hibernate-testing
Before evaluation: `:hibernate-testing` (from root)
Applying plugin to `:hibernate-testing`
Finished evaluation: `:hibernate-testing`

```

You can see the problem with `afterEvaluate` in the fact that the callbacks in the sub-projects to the root-project’s `afterEvaluate` never happen.

There are a few “work arounds” I can think of, but both seems hacky…

The first would be to use normal project-dependency to express the dependency:

```gradle
plugins {
    id 'jakarta-transformer'
}

dependencies {
    implementation project( ':hibernate-core' )
}

jakartaTransformation {
    shadow( project( ':hibernate-core' ) ) {
        ...
    }
}

```

This one is hacky imo, due the nature of the plugin functionality, because it allows the possibility that the user might add multiple dependencies to this Configuration while shadowing is a one-to-one thing. Also internally these shadows define dependency (Configuration sense) substitutions - here we’d always want to substitute references to `:hibernate-core` to the project applying the plugin, which here would be a circularity.

The other approach I considered was to instead force / expect the plugin to be applied to a root project and define the shadowing config for all “shadow” projects:

```gradle
plugins {
    id 'jakarta-transformer'
}

jakartaTransformation {
    shadow( ':hibernate-core-shadowed' ) {
        from project( ':hibernate-core' ) 
        ...
    }
    shadow( ':yet-another-shadowed' ) {
        from 'some.external:project:1.2.3'
        ...
    }
}

```

Not a fan of this one just because it does not “feel as nice” as each shadow project defining what it shadows and configuring that shadowing.

But really, making it work is obviously the main priority so if one of these hack-options is the only option that’s what I’ll do.

A lot of information to read through here, so big thanks in advance…

[1] Is there an explicit reason `afterEvaluate` cannot simply immediately execute the passed block when the project is already evaluated? Or at least a way to ask if the Project has been evaluated?
