bytedeco / gradle-javacpp

Gradle plugins to automate the build process of JavaCPP and JavaCV
Other
56 stars 20 forks source link

Gradle Multi-module support #29

Closed krislefeber closed 1 year ago

krislefeber commented 1 year ago

In an effort to separate our main business logic from javacpp, I've setup our project using gradle's multi-module support with a structure like so

src/
   business-logic/ # rest controllers and other business logic that call the interface
   javacpp-interface/ # Single class with interface methods
   javacpp-implementation # implements the interface

Both the business-logic and javacpp-implementation modules have a dependency on javacpp-interface. This will allow us to write unit tests in the business-logic layer without relying on javacpp code(We develop on windows but the C++ library is targeting linux in a docker image).

What I'm running into issues with is that the implementation class fails to compile as it cannot see the interface class in the javacpp-interface. We end up receiving class loader issues like such:

[ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] Execution failed for task ':javacpp-implementation:javacppBuildParser'.
[ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] > com/my-org/ndi/javacpp/impl/INativeNdiService
Unable to load class 'com.my-org.ndi.javacpp.impl.INativeNdiService'.

Both the interface and the implementation are in the same package structure, but different modules.

My gradle file looks something like this(Note we are using the latest version 1.5.8 that's stored in a gradle catalog):

plugins {
    id 'java-library'

    alias(libs.plugins.bytedeco.javacpp.build)
    alias(libs.plugins.bytedeco.javacpp.platform)
    alias(libs.plugins.springboot)
    alias(libs.plugins.dependencyManagement)
}

javacppCompileJava {
    include 'com/my-org/ndi/javacpp/impl/*'
} 

dependencies {
    implementation project(":javacpp-interface")
    implementation libs.bytedeco
}
saudet commented 1 year ago

I don't think that's related to multi-module support. The class path of the plugins isn't related to the one of your project. You'll need to add the required dependencies to the buildscript block, manually: https://docs.gradle.org/current/userguide/tutorial_using_tasks.html#sec:build_script_external_dependencies

krislefeber commented 1 year ago

For anyone else that ends up here, we found that adding the javacppBuildParser and javacppBuildCompiler to the build.gradle of the sub-module with javacpp fixed it for us. This allowed that sub-module to see the other module's interfaces at build time:

javacppCompileJava {
    include 'myorg/app/ndi/javacpp/impl/'
}
javacppBuildParser {
    classPath = [ "${project(":NdiJavaCppAPI").buildDir}/classes/java/main", *classPath]
}

javacppBuildCompiler {
    classPath = [ "${project(":NdiJavaCppAPI").buildDir}/classes/java/main", *classPath]
}
saudet commented 1 year ago

Running JavaCPP as part of the parent project after building all the modules and adding them manually to the class path works too :)