Gradle 8 compileOnly does not work correctly with multiple module project

I have a project contains multiple modules(Java 17, Spring Boot 3.2.0, gradle 8.4 and java-library plugin).
And I’m using compileOnly in module A for depending on module B, because module B is not necessary in all cases.
I provide a function with multiple implementations in module A and only one of them depends on module B.
And the real application can choose the specific implementation by importing both module A and module B, or module A only in other cases.

So it’s like:

compileOnly project(":moduleB")

in module A’s build gradle.

Then I found that the classes defined in module B cannot be resolved in module A.
The problems occur when I’m using Eclipse or VSCode to import the project source code.
But it’s fine when I’m using Jetbrain IDEA.
And also the test and build tasks work well in command line.

And the transitive dependency seems OK. The modules which module B depends can be resolved in module A, only the module B itself cannot be resolved.

Hard to say from here, but as it works from Gradle and from IntelliJ, I would blame Eclipse and VSC and you should report errors to their Gradle integrations if it does not work.

Besides that, what you describe sounds like you should instead declare a feature variant instead of using compileOnly: Modeling feature variants and optional dependencies

For non-Gradle consumers there should not be a change, but Gradle consumers can more conveniently and more idiomatically use your library.

Thank you for you reply.
For the consumer part, I think using feature variant is a good idea to control the dependency relation.
But for the producer side, I think I should still use compileOnly. Am I correct?

No, you are not.
The producer declares the feature variants, the consumer requests them.
Have a look at the documentation I linked you to.

Thank you. I’ll re-check the document.
But I’m now running the tests in module A which do not depend on module B.
If I declare something like this:

java {
    registerFeature('redisSupport') {

redisSupportImplementation project(":module-redis")

The module redis would be active during runtime and tests. But sometimes I want to test the implementation without redis.
When using compileOnly, it works for me.
(Sorry if I still have some misunderstanding about this)

But using compileOnly can only support me for programming the source code related to redis.
When I want to run the tests, I can only import the dependency by declaring testImplementation or not. So it would be difficult for me to test both implementation of origin and redis.
So it might be better for me to use feature variants and turn off the redis in some test cases of module A.

I’ll give it a try. Thanks again.

Declaring the feature variant and only depending on the dependency in the feature variant makes sure a consumer does not get that dependency unless he explicitly depends on that feature variant.

For unit tests indeed all feature variants are automatically depended on, so you might want to add an additional test suite using the JVM test suite configuration to add an additional test suite where you test without that dependency.

Alternatively, you could also add a separate subproject for those tests where you do only depend on the main variant, but not on the additional feature variant, both would work fine.