deephaven / deephaven-core

Deephaven Community Core
Other
256 stars 80 forks source link

Break up dagger components in a way that lets gradle use implementation instead of api #1722

Open niloc132 opened 2 years ago

niloc132 commented 2 years ago

This might not be something we actually fix, but will for now at least serve as a marker for questionable gradle dependency configuration.

See https://github.com/google/dagger/issues/970.

In general, if a given gradle project has no part of its api which exposes some dependency's types to consumers, that dependency can be marked as part of the implementation configuration rather than api. However, from the perspective of the dagger2-compiler, even components/modules are part of the api, so any dependency used in dagger declarations must always be marked as api instead. This limits gradle somewhat in how it can avoid recompiles, build with smaller classpaths, etc.

According to the linked dagger issue, it is possible to support this if we also disable dagger's detection of cycles in components.

It might also be possible to add some gradle wiring to pick up implementation dependencies (recursively) that declare dagger components/modules, and only add them to the classpath when the dagger compiler is running. If we take this approach, it will be important to make sure that the information is exported when we publish to maven central, so that downstream projects correctly pick this up as well.

devinrsmith commented 2 months ago

I just sketched through something that might work.

The setup:

  1. project flightsql has FlightSqlModule
  2. project server-jetty has an implementation dependency on flightsql, and wants to have a way to source it through dagger without exposing it:
    @Module(includes = {
        FlightSqlModule.class
    })
    public interface JettyServerOptionalModule {
    }
  3. project py-embedded-server-java-runtime wants to depend on server-jetty JettyServerOptionalModule

This produces the error

> Task :py-embedded-server-java-runtime:compileJava FAILED
error: ComponentProcessingStep was unable to process 'io.deephaven.python.server.EmbeddedServer.PythonServerComponent' because 'io.deephaven.server.flightsql.FlightSqlModule' could not be resolved.

  Dependency trace:
      => element (INTERFACE): io.deephaven.server.jetty.JettyServerOptionalModule
      => annotation type: dagger.Module
      => annotation: @dagger.Module(includes={io.deephaven.server.flightsql.FlightSqlModule}, subcomponents={})
      => annotation value (TYPE_ARRAY): includes={io.deephaven.server.flightsql.FlightSqlModule}
      => annotation value (TYPE): includes=io.deephaven.server.flightsql.FlightSqlModule

  If type 'io.deephaven.server.flightsql.FlightSqlModule' is a generated type, check above for compilation errors that may have prevented the type from being generated. Otherwise, ensure that type 'io.deephaven.server.flightsql.FlightSqlModule' is on your classpath.
1 error

which I believe is similar to, or the same as, this issue is describing.

In this case, from the server-jetty project, I was able to further declare the dependency as a compileOnlyApi dependency, which solved the error:

    implementation project(':flightsql')
    compileOnlyApi project(':flightsql')