I'm building a Java desktop app using JavaCV.
When my app builds, it's supermassive (1.2GB which is almost all unused JavaCV dependencies). I'm trying to pare down the deps that get loaded, since all I need are some entry-level ffmpeg GPL functions.
Additionally, my test suite is failing with a slew of errors like
Error occurred during initialization of boot layer java.lang.LayerInstantiationException: Package lib.x86 in both module org.bytedeco.artoolkitplus.android.x86 and module org.bytedeco.tesseract.android.x86
build.gradle
plugins {
id 'java'
id 'application'
id 'distribution'
//
id 'de.undercouch.download' version "4.0.4"
id "org.beryx.jlink" version "2.24.1"
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
id 'org.openjfx.javafxplugin' version '0.0.14'
id 'org.springframework.boot' version '3.1.2' // must match springBootVersion below
}
ext {
javaFxVersion = '18.0.2'
junitVersion = '5.9.2'
logbackVersion = '1.4.11'
springBootVersion = '3.1.2'
}
group = 'io.xj'
sourceCompatibility = JavaVersion.VERSION_18
targetCompatibility = JavaVersion.VERSION_18
mainClassName = 'io.xj.gui.WorkstationGuiApplication'
tasks.withType(JavaCompile).tap {
configureEach {
options.encoding = 'UTF-8'
}
}
apply plugin: 'java'
configurations {
implementation {
exclude group: "commons-logging", module: "commons-logging"
exclude group: 'com.google.code.findbugs', module: 'jsr305'
}
}
repositories {
mavenCentral()
mavenLocal()
maven {
url = 'https://repo.maven.apache.org/maven2'
}
maven {
url = 'https://packages.confluent.io/maven/'
}
}
javafx {
version = "${rootProject.ext.javaFxVersion}"
modules = ['javafx.base', 'javafx.controls', 'javafx.fxml', 'javafx.graphics']
}
//noinspection GroovyAssignabilityCheck
ext.os = org.gradle.internal.os.OperatingSystem.current() as org.gradle.internal.os.OperatingSystem
jlink {
// imageZip = file("$buildDir/image-zip/javacv-example.zip")
// options = ['--bind-services', '--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
addExtraDependencies 'javafx'
launcher {
name = 'javacv-example'
noConsole = true
}
jpackage {
if (os.windows) {
// installerOptions = ['--win-per-user-install', '--win-dir-chooser', '--win-menu']
}
}
}
dependencies {
implementation "ch.qos.logback:logback-classic:${rootProject.ext.logbackVersion}"
implementation "ch.qos.logback:logback-core:${rootProject.ext.logbackVersion}"
implementation "org.openjfx:javafx-base:${rootProject.ext.javaFxVersion}"
implementation "org.openjfx:javafx-controls:${rootProject.ext.javaFxVersion}"
implementation "org.openjfx:javafx-fxml:${rootProject.ext.javaFxVersion}"
implementation "org.openjfx:javafx-graphics:${rootProject.ext.javaFxVersion}"
implementation "org.springframework.boot:spring-boot-starter-logging:${rootProject.ext.springBootVersion}"
implementation "org.springframework.boot:spring-boot-starter:${rootProject.ext.springBootVersion}"
implementation 'commons-codec:commons-codec:1.15'
implementation 'commons-io:commons-io:2.11.0'
implementation 'org.bytedeco:ffmpeg-platform-gpl:6.0-1.5.9' // Optional GPL builds with (almost) everything enabled
implementation 'org.bytedeco:flandmark-platform:1.07-1.5.8' // Required by org.bytedeco.javacv
implementation 'org.bytedeco:javacv-platform:1.5.9'
implementation 'org.reflections:reflections:0.10.2'
testImplementation "org.junit.jupiter:junit-jupiter-api:${rootProject.ext.junitVersion}"
testImplementation 'org.hamcrest:hamcrest-library:2.2'
testImplementation 'org.mockito:mockito-junit-jupiter'
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${rootProject.ext.junitVersion}"
}
//noinspection ConfigurationAvoidance
task 'bootJarZip'(type: Zip) {
dependsOn('bootJar')
from "build/libs/"
archiveBaseName = 'javacv-example'
include "javacv-example-${rootProject.version}.jar"
destinationDirectory = file("$buildDir/dist")
}
bootJar {
launchScript()
archiveBaseName = 'javacv-example'
}
test {
useJUnitPlatform()
}
module-info.java
module main {
requires ch.qos.logback.classic;
requires ch.qos.logback.core;
requires jakarta.annotation;
requires java.desktop;
requires javafx.base;
requires javafx.controls;
requires javafx.fxml;
requires javafx.graphics;
requires org.apache.commons.codec;
requires org.apache.commons.io;
requires org.bytedeco.ffmpeg;
requires org.bytedeco.flandmark.platform;
requires org.bytedeco.flandmark;
requires org.bytedeco.javacv.platform;
requires org.bytedeco.javacv;
requires org.slf4j;
requires spring.beans;
requires spring.boot.autoconfigure;
requires spring.boot;
requires spring.context;
requires spring.core;
requires spring.jcl;
opens io.xj.gui.controllers to javafx.graphics, javafx.base, javafx.fxml, javafx.controls, spring.beans;
opens io.xj.gui.events to javafx.base, javafx.controls, javafx.fxml, javafx.graphics, spring.beans, spring.context, spring.core;
opens io.xj.gui.listeners to javafx.base, javafx.controls, javafx.fxml, javafx.graphics, spring.beans, spring.context, spring.core, ch.qos.logback.core;
opens io.xj.gui.services to javafx.base, javafx.controls, javafx.fxml, javafx.graphics, spring.beans, spring.context, spring.core;
opens io.xj.gui to ch.qos.logback.core, javafx.base, javafx.controls, javafx.fxml, javafx.graphics, spring.beans, spring.context, spring.core;
}
Complete demonstration here
In brief: Gradle JavaCPP accomplishes this:
plugins {
id 'org.bytedeco.gradle-javacpp-platform' version "1.5.9"
}
// We can set this on the command line too this way: -PjavacppPlatform=linux-x86_64,macosx-x86_64,windows-x86_64,etc
ext {
javacppPlatform = 'linux-x86_64,macosx-x86_64,windows-x86_64,etc' // defaults to Loader.getPlatform()
}