Skip to content

Reducing the Number of Dependencies

Samuel Audet edited this page Mar 18, 2022 · 7 revisions

Introduction

Native binaries are inherently large in size, and we need to use a different set of libraries for each supported platform. However, if your application does not depend on all these libraries or does not need to support all these platforms, there are a few ways to reduce easily the number of dependencies, apart from manually excluding artifacts one by one or removing files from uber JARs.

Include binaries only for one or more platforms

For applications depending on artifacts with names ending with -platform, to limit dependencies to a single platform, set the javacpp.platform system property of Maven to the desired platform, for example:

mvn -Djavacpp.platform=linux-x86_64 ...

To include binaries for 2 or more platforms, we can rely on a different set of profiles, but always starting by setting the javacpp.platform.custom system property to reset the default one from javacpp.platform. For example, in the case of the host platform, plus Mac and Windows, we can use commands starting with:

mvn -Djavacpp.platform.custom -Djavacpp.platform.host -Djavacpp.platform.macosx-x86_64 -Djavacpp.platform.windows-x86_64 ...

Note: This works only with Maven. It does not work with Gradle, sbt, or any other build system, but we can do something similar to that using Gradle JavaCPP, SBT-JavaCPP, or SBT-JavaCV.

Including binaries only for mobile platforms

Mobile platforms (Android and iOS) typically rely on Gradle for their build systems, so the trick mentioned above does not work. Although we can use Gradle JavaCPP, since the artifacts that are useful to a given mobile application are determined at build time, we can also directly specify only the desired artifacts in the build file--without relying on any -platform artifacts. For example, to include only binaries useful for FFmpeg on android-arm64 and android-x86_64 platforms, we can use entries such as the following inside the dependencies { } block of the app/build.gradle file:

implementation group: 'org.bytedeco', name: 'javacpp', version: '1.5.7'
implementation group: 'org.bytedeco', name: 'javacpp', version: '1.5.7', classifier: 'android-arm64'
implementation group: 'org.bytedeco', name: 'javacpp', version: '1.5.7', classifier: 'android-x86_64'
implementation group: 'org.bytedeco', name: 'ffmpeg', version: '5.0-1.5.7'
implementation group: 'org.bytedeco', name: 'ffmpeg', version: '5.0-1.5.7', classifier: 'android-arm64'
implementation group: 'org.bytedeco', name: 'ffmpeg', version: '5.0-1.5.7', classifier: 'android-x86_64'

Excluding all binaries via -platform artifacts

On the other hand, to remove all dependencies related to a given library for all platforms, the mechanisms already in place for the pom.xml file are most efficient. For example, if the application uses JavaCV but without anything related to OpenCV, we can add a dependency such as the following to avoid all of its large artifacts:

    <dependency>
        <groupId>org.bytedeco</groupId>
        <artifactId>javacv-platform</artifactId>
        <version>1.5.7</version>
        <exclusions>
            <exclusion>
                <groupId>org.bytedeco</groupId>
                <artifactId>opencv-platform</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

Note: This works the same with similar features in Gradle, sbt, and other build systems. We can use this method, and then re-add only the desired artifacts in the way mentioned above in the previous section.


For additional assistance, please feel free to post your questions on the mailing list or open new issues on GitHub.