Unable to build OpenCV with Java bindings

Hello all,

I need java bindings for opencv to be able to use nix in a java/scala project at work. I tried many things and none of them work. Here is the nix flake I am using:

{
  description = "A template that shows all standard flake outputs";

  inputs.nixpkgs.url = "github:NixOS/nixpkgs";

  outputs = {
    self,
    nixpkgs,
    ...
  }: let
    system = "x86_64-linux";
    pkgs = import nixpkgs {inherit system;};
  in {
    packages.${system}.default = (
      pkgs.opencv4.overrideAttrs
      (oldAttr: {
        buildInputs = oldAttr.buildInputs ++ (with pkgs; [ant jdk jre]);
        cmakeFlags = oldAttr.cmakeFlags ++ ["-DWITH_JAVA=ON"];
      })
    );
  };
}

In the package definition in nixpkgs there is no option like enableJava. Also, I didn’t find the java bindings in the default build (cached on cache.nixos.org) version of the package.

Can anyone tell me how to get a opencv build with java bindings? I also would appreciate any tips which would push me in the right direction. Thank you!

Doing a quick search on the nixpkgs repo, I see this: nixpkgs/pkgs/by-name/li/libjpeg_turbo/package.nix at 35f9b4c165413eb1f419b3d46889194ec82eda4f Ā· NixOS/nixpkgs Ā· GitHub. Looks like the flag enableJava adds openjdk as part of nativeBuildInputs. You can give that a try.

Hey @aos , thanks you for helping me out!

Can you tell me how you found this option? I did not find this option in package definition for the opencv derivation.

I tried it with enableJava, but unfortunately it did not build the java bindings. I am not sure what is happening there. I also added openjdk and ant to the buildInputs, however it still did not do the trick. I also created a nix shell with all the dependencies and tried doing it manually, however the cmake output says, that it does not find Java, although ant and JNI are found. I am not sure if it is an issue is here … Do you have any further tips? I really appreciate your help!

I just did a search on the nixpkgs repo: Code search results Ā· GitHub

This is a good way to figure out what other packages are doing. Chances are usually pretty good that others have run into similar problems.

By this - I mean that you should see what that package is doing, and how it’s setting and using the enableJava option. It uses it to add openjdk into nativeBuildInputs ← native is important, it makes the dependency available during build time.

It would also be helpful to see what the most recent version of your code is now.

1 Like

I see, that actually is quite helpful. Thanks @aos !

Here is the latest version of my flake.nix file for building OpenCV, the devShell is just for testing and debugging, but so far I haven’t figured out how to build with java bindings:

{
  description = "OpenCV test flake";

  inputs.nixpkgs.url = "github:NixOS/nixpkgs";

  outputs = {
    self,
    nixpkgs,
    ...
  }: let
    system = "x86_64-linux";
    pkgs = import nixpkgs {
      inherit system;
    };
    cmakePackage = (
      pkgs.cmake.overrideAttrs
      (oldAttr: {
        postPatch =
          oldAttr.postPatch
          or ""
          + ''
            substituteInPlace Modules/FindJNI.cmake \
            --replace "/usr/lib64/jvm/jre" "/usr/lib64/jvm/jre\n${pkgs.corretto21}"
          '';

        # patches = [
        #   (pkgs.writeText "add-custom-jvm.patch" ''
        #     --- a/Modules/FindJNI.cmake
        #     +++ b/Modules/FindJNI.cmake
        #     @@ -312,7 +312,8 @@
        #        # SuSE specific paths for default JVM
        #        /usr/lib64/jvm/java
        #        /usr/lib64/jvm/jre
        #        /usr/lib/corretto
        #        /usr/lib/openjdk
        #        /usr/lib/corretto
        #     -  )
        #     +  )
        #     +set(_JNI_JAVA_AWT_LIBRARY_TRIES)
        #   '')
        # ];
      })
    );
  in {
    devShells.${system}.default =
      (pkgs.buildFHSEnv {
        name = "opencv-fhs";
        targetPkgs = pkgs: (with pkgs;
          [
            ant
            corretto21
            gcc
            jre_minimal
            libgcc
            openblas
            vtk
          ]
          ++ [cmakePackage]);
        profile = ''
          export JAVA_HOME=${pkgs.corretto21}
          export PATH=$JAVA_HOME/bin:$PATH

          echo  "cmake \\" > a.sh
          echo  "-DBUILD_JAVA=ON \\" >> a.sh
          echo  "-DBUILD_SHARED_LIBS=OFF \\" >> a.sh
          echo  "-DBUILD_opencv_core=ON \\" >> a.sh
          echo  "-DBUILD_opencv_imgcodecs=ON \\" >> a.sh
          echo  "-DBUILD_opencv_imgproc=ON \\" >> a.sh
          echo  "-DBUILD_opencv_java=ON \\" >> a.sh
          echo  "-DBUILD_opencv_java_bindings_gen=ON \\" >> a.sh
          echo  "-DJAVA_AWT_INCLUDE_PATH=${pkgs.corretto21}/include \\" >> a.sh
          echo  "-DJAVA_AWT_LIBRARY=${pkgs.corretto21}/lib/libjawt.so \\" >> a.sh
          echo  "-DJAVA_INCLUDE_PATH2=${pkgs.corretto21}/include/linux \\" >> a.sh
          echo  "-DJAVA_INCLUDE_PATH=${pkgs.corretto21}/include \\" >> a.sh
          echo  "-DJAVA_JVM_LIBRARY=${pkgs.corretto21}/lib/server/libjvm.so \\" >> a.sh
          echo  "-DJava_JARSIGNER_EXECUTABLE=${pkgs.corretto21}/bin/jarsigner \\" >> a.sh
          echo  "-DJava_JAR_EXECUTABLE=${pkgs.corretto21}/bin/jar \\" >> a.sh
          echo  "-DJava_JAVAC_EXECUTABLE=${pkgs.corretto21}/bin/javac \\" >> a.sh
          echo  "-DJava_JAVADOC_EXECUTABLE=${pkgs.corretto21}/bin/javadoc \\" >> a.sh
          echo  "-DJava_JAVA_EXECUTABLE=${pkgs.corretto21}/bin/java \\" >> a.sh
          echo  "-D_JNI_JAVA_DIRECTORIES_BASE=${pkgs.corretto21}/bin/java \\" >> a.sh
        '';
      })
      .env;

    packages.${system} = {
      cmake = cmakePackage;

      default = (
        pkgs.opencv4.overrideAttrs
        (oldAttr: {
          buildInputs =
            oldAttr.buildInputs
            ++ (with pkgs; [
              ant
              corretto21
              gcc
              jre_minimal
              libgcc
            ]);
          cmakeFlags =
            oldAttr.cmakeFlags
            ++ [
              "-DBUILD_JAVA=ON"
              "-DBUILD_SHARED_LIBS=OFF"
              "-DBUILD_opencv_core=ON"
              "-DBUILD_opencv_imgcodecs=ON"
              "-DBUILD_opencv_imgproc=ON"
              "-DBUILD_opencv_java=ON"
              "-DBUILD_opencv_java_bindings_gen=ON"
              "-DJAVA_AWT_INCLUDE_PATH=${pkgs.corretto21}/include"
              "-DJAVA_AWT_LIBRARY=${pkgs.corretto21}/lib/libjawt.so"
              "-DJAVA_INCLUDE_PATH2=${pkgs.corretto21}/include/linux"
              "-DJAVA_INCLUDE_PATH=${pkgs.corretto21}/include"
              "-DJAVA_JVM_LIBRARY=${pkgs.corretto21}/lib/server/libjvm.so"
              "-DJava_JARSIGNER_EXECUTABLE=${pkgs.corretto21}/bin/jarsigner"
              "-DJava_JAR_EXECUTABLE=${pkgs.corretto21}/bin/jar"
              "-DJava_JAVAC_EXECUTABLE=${pkgs.corretto21}/bin/javac"
              "-DJava_JAVADOC_EXECUTABLE=${pkgs.corretto21}/bin/javadoc"
              "-DJava_JAVA_EXECUTABLE=${pkgs.corretto21}/bin/java"
              "-D_JNI_JAVA_DIRECTORIES_BASE=${pkgs.corretto21}/bin/java"
            ];
        })
      );
    };
  };
}

I followed you advice and added java and ant to the build inputs. Here I added corretto21 instead of openjdk, but it does not work with openjdk either.

In the devShell, I did some testing and found out that the issue most likely comes from CMake. OpenCV uses the two modules FindJNI and FindJava from CMake. As I understand, the CMake modules define some base directories to search, however this is a collection for different Linux distributions such as Ubuntu, OpenSUSE, etc. The patches I tried haven’t worked. I also, did not find anything in nixpkgs which has done this before.

Do you have any other suggestions or hints to get this to work? I really do appreciate you taking the time to help me out!

Hi, have you solved this problem?

Hi @ufo5260987423 ,

no unfortunately I haven’t. I tried patching CMake, as I think it is a CMake module which cannot find the java binary, but I have not had any success there.

Have you tried anything in this regard?

Any more luck with the packaging? if not is the flake in 5th message still accurate or is there some where i can find the up to date version?

@me-it-is Yes, I managed to solve the issue, but have not had any time to make a pull request for nixpkgs. It was really difficult to find the problem. I had to dig deep into the source code. But fortunately the solution is really easy!

OpenCV needs python to build the java bindings, so just adding python, ant, and openjdk to the nativeBuildInputs makes the java bindings build! This is a minimal working flake.nix example with numpy. You probably dont’ even need numpy, but here it is:

{
  description = "A template that shows all standard flake outputs";

  inputs.nixpkgs.url = "github:NixOS/nixpkgs";

  outputs = {
    self,
    nixpkgs,
    ...
  }: let
    system = "x86_64-linux";
    pkgs = import nixpkgs {
      inherit system;
    };
  in {
    packages.${system}.default = (
      pkgs.opencv4.overrideAttrs
      (oldAttr: {
        nativeBuildInputs =
          oldAttr.nativeBuildInputs
          ++ (with pkgs; [
            ant
            openjdk  # or corretto21, or ... 
            python3
            python3Packages.numpy
          ]);
        cmakeFlags =
          oldAttr.cmakeFlags
          ++ [
            "-DBUILD_JAVA=ON"
          ];
      })
    );
  };
}

After doing a nix build -L -vvv you should get an output like this, which indicates the java bindings are building:

opencv> --
opencv> --   Python 3:
opencv> --     Interpreter:                 /nix/store/26yi95240650jxp5dj78xzch70i1kzlz-python3-3.12.9/bin/python3 (ver 3.12.9)
opencv> --     Libraries:                   /nix/store/26yi95240650jxp5dj78xzch70i1kzlz-python3-3.12.9/lib/libpython3.12.so (ver 3.12.9)
opencv> --     Limited API:                 NO
opencv> --     numpy:                       /nix/store/q4x83jxjxzp5nbng9n4659pxnjygni69-python3.12-numpy-2.2.2/lib/python3.12/site-packages/numpy/_core/include (ver 2.2.2)
opencv> --     install path:                lib/python3.12/site-packages/cv2/python-3.12
opencv> --
opencv> --   Python (for build):            /nix/store/26yi95240650jxp5dj78xzch70i1kzlz-python3-3.12.9/bin/python3
opencv> --
opencv> --   Java:
opencv> --     ant:                         /nix/store/ynys15slrijkshpkz2hxbdi71i124i1r-ant-1.10.15/bin/ant (ver 1.10.15)
opencv> --     Java:                        NO
opencv> --     JNI:                         /nix/store/jv0jb1aa5ldvlja8lc1fymzn378imyad-corretto-21.0.5.11.1/include /nix/store/jv0jb1aa5ldvlja8lc1fymzn378imyad-corretto-21.0.5.11.1/include
opencv> --     Java wrappers:               YES (ANT)
opencv> --     Java tests:                  YES
opencv> --
opencv> --   Install to:                    /nix/store/zik34ilvmz1lfcc0xg9dlchbcq2hwmy9-opencv-4.11.0
opencv> -- -----------------------------------------------------------------
opencv> --

If you or anyone else have any comments please let me know. Hope this helps!

That will be quite helpful i hope you have time to pr it into nixpkgs soon. Thank you.