Merge pull request #23724 from dkurt:java_without_ant

Build Java without ANT #23724

### Pull Request Readiness Checklist

Enables a path of building Java bindings without ANT

* Able to build OpenCV JAR and Docs without ANT
  ```
  --   Java:
  --     ant:                         NO
  --     JNI:                         /usr/lib/jvm/default-java/include /usr/lib/jvm/default-java/include/linux /usr/lib/jvm/default-java/include
  --     Java wrappers:               YES
  --     Java tests:                  NO
  ```
* Possible to build OpenCV JAR without ANT but tests still require ANT

**Merge with**: https://github.com/opencv/opencv_contrib/pull/3502

Notes:
- Use `OPENCV_JAVA_IGNORE_ANT=1` to force "Java" flow for building Java bindings
- Java tests still require Apache ANT
- JAR doesn't include `.java` source code files.


See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

- [x] I agree to contribute to the project under Apache 2 License.
- [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
- [x] The PR is proposed to the proper branch
- [ ] There is a reference to the original bug report and related work
- [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [x] The feature is well documented and sample code can be built with the project CMake
pull/23821/head
Dmitry Kurtaev 1 year ago committed by GitHub
parent ec95efca10
commit 433c364456
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 12
      CMakeLists.txt
  2. 3
      modules/core/misc/java/src/java/core+Mat.java
  3. 1
      modules/dnn/include/opencv2/dnn/dnn.hpp
  4. 4
      modules/java/CMakeLists.txt
  5. 117
      modules/java/jar/CMakeLists.txt
  6. 5
      modules/java/jar/MANIFEST.MF.in
  7. 19
      modules/java/jar/list_java_sources.cmake

@ -777,6 +777,15 @@ if(BUILD_JAVA)
include(cmake/android/OpenCVDetectAndroidSDK.cmake) include(cmake/android/OpenCVDetectAndroidSDK.cmake)
else() else()
include(cmake/OpenCVDetectApacheAnt.cmake) include(cmake/OpenCVDetectApacheAnt.cmake)
if(ANT_EXECUTABLE AND NOT OPENCV_JAVA_IGNORE_ANT)
ocv_update(OPENCV_JAVA_SDK_BUILD_TYPE "ANT")
elseif(NOT ANDROID)
find_package(Java)
if(Java_FOUND)
include(UseJava)
ocv_update(OPENCV_JAVA_SDK_BUILD_TYPE "JAVA")
endif()
endif()
find_package(JNI) find_package(JNI)
endif() endif()
endif() endif()
@ -1802,9 +1811,10 @@ if(BUILD_JAVA)
status(" Java:" BUILD_FAT_JAVA_LIB THEN "export all functions" ELSE "") status(" Java:" BUILD_FAT_JAVA_LIB THEN "export all functions" ELSE "")
status(" ant:" ANT_EXECUTABLE THEN "${ANT_EXECUTABLE} (ver ${ANT_VERSION})" ELSE NO) status(" ant:" ANT_EXECUTABLE THEN "${ANT_EXECUTABLE} (ver ${ANT_VERSION})" ELSE NO)
if(NOT ANDROID) if(NOT ANDROID)
status(" Java:" Java_FOUND THEN "YES (ver ${Java_VERSION})" ELSE NO)
status(" JNI:" JNI_INCLUDE_DIRS THEN "${JNI_INCLUDE_DIRS}" ELSE NO) status(" JNI:" JNI_INCLUDE_DIRS THEN "${JNI_INCLUDE_DIRS}" ELSE NO)
endif() endif()
status(" Java wrappers:" HAVE_opencv_java THEN YES ELSE NO) status(" Java wrappers:" HAVE_opencv_java THEN "YES (${OPENCV_JAVA_SDK_BUILD_TYPE})" ELSE NO)
status(" Java tests:" BUILD_TESTS AND opencv_test_java_BINARY_DIR THEN YES ELSE NO) status(" Java tests:" BUILD_TESTS AND opencv_test_java_BINARY_DIR THEN YES ELSE NO)
endif() endif()

@ -470,6 +470,7 @@ public class Mat {
* Element-wise multiplication with scale factor * Element-wise multiplication with scale factor
* @param m operand with with which to perform element-wise multiplication * @param m operand with with which to perform element-wise multiplication
* @param scale scale factor * @param scale scale factor
* @return reference to a new Mat object
*/ */
public Mat mul(Mat m, double scale) { public Mat mul(Mat m, double scale) {
return new Mat(n_mul(nativeObj, m.nativeObj, scale)); return new Mat(n_mul(nativeObj, m.nativeObj, scale));
@ -478,6 +479,7 @@ public class Mat {
/** /**
* Element-wise multiplication * Element-wise multiplication
* @param m operand with with which to perform element-wise multiplication * @param m operand with with which to perform element-wise multiplication
* @return reference to a new Mat object
*/ */
public Mat mul(Mat m) { public Mat mul(Mat m) {
return new Mat(n_mul(nativeObj, m.nativeObj)); return new Mat(n_mul(nativeObj, m.nativeObj));
@ -487,6 +489,7 @@ public class Mat {
* Matrix multiplication * Matrix multiplication
* @param m operand with with which to perform matrix multiplication * @param m operand with with which to perform matrix multiplication
* @see Core#gemm(Mat, Mat, double, Mat, double, Mat, int) * @see Core#gemm(Mat, Mat, double, Mat, double, Mat, int)
* @return reference to a new Mat object
*/ */
public Mat matMul(Mat m) { public Mat matMul(Mat m) {
return new Mat(n_matMul(nativeObj, m.nativeObj)); return new Mat(n_matMul(nativeObj, m.nativeObj));

@ -894,7 +894,6 @@ CV__DNN_INLINE_NS_BEGIN
* @param cfgFile path to the .cfg file with text description of the network architecture. * @param cfgFile path to the .cfg file with text description of the network architecture.
* @param darknetModel path to the .weights file with learned network. * @param darknetModel path to the .weights file with learned network.
* @returns Network object that ready to do forward, throw an exception in failure cases. * @returns Network object that ready to do forward, throw an exception in failure cases.
* @returns Net object.
*/ */
CV_EXPORTS_W Net readNetFromDarknet(const String &cfgFile, const String &darknetModel = String()); CV_EXPORTS_W Net readNetFromDarknet(const String &cfgFile, const String &darknetModel = String());

@ -3,7 +3,9 @@ if(OPENCV_INITIAL_PASS)
add_subdirectory(generator) add_subdirectory(generator)
endif() endif()
if(APPLE_FRAMEWORK OR WINRT OR NOT PYTHON_DEFAULT_AVAILABLE OR NOT (ANT_EXECUTABLE OR ANDROID_PROJECTS_BUILD_TYPE STREQUAL "GRADLE") if(APPLE_FRAMEWORK OR WINRT
OR NOT PYTHON_DEFAULT_AVAILABLE
OR NOT (ANT_EXECUTABLE OR Java_FOUND OR ANDROID_PROJECTS_BUILD_TYPE STREQUAL "GRADLE")
OR NOT (JNI_FOUND OR (ANDROID AND (NOT DEFINED ANDROID_NATIVE_API_LEVEL OR ANDROID_NATIVE_API_LEVEL GREATER 7))) OR NOT (JNI_FOUND OR (ANDROID AND (NOT DEFINED ANDROID_NATIVE_API_LEVEL OR ANDROID_NATIVE_API_LEVEL GREATER 7)))
OR BUILD_opencv_world OR BUILD_opencv_world
) )

@ -5,12 +5,13 @@ set(OPENCV_JAVA_DIR "${CMAKE_CURRENT_BINARY_DIR}/opencv" CACHE INTERNAL "")
file(REMOVE_RECURSE "${OPENCV_JAVA_DIR}") file(REMOVE_RECURSE "${OPENCV_JAVA_DIR}")
file(REMOVE "${OPENCV_DEPHELPER}/${the_module}_jar_source_copy") file(REMOVE "${OPENCV_DEPHELPER}/${the_module}_jar_source_copy")
file(MAKE_DIRECTORY "${OPENCV_JAVA_DIR}/build/classes")
set(java_src_dir "${OPENCV_JAVA_DIR}/java") set(java_src_dir "${OPENCV_JAVA_DIR}/java")
file(MAKE_DIRECTORY "${java_src_dir}") file(MAKE_DIRECTORY "${java_src_dir}")
set(JAR_NAME opencv-${OPENCV_JAVA_LIB_NAME_SUFFIX}.jar) set(JAR_NAME_WE opencv-${OPENCV_JAVA_LIB_NAME_SUFFIX})
set(OPENCV_JAR_FILE "${OpenCV_BINARY_DIR}/bin/${JAR_NAME}" CACHE INTERNAL "") set(JAR_NAME ${JAR_NAME_WE}.jar)
set(OPENCV_JAR_DIR "${OpenCV_BINARY_DIR}/bin/" CACHE INTERNAL "")
set(OPENCV_JAR_FILE "${OPENCV_JAR_DIR}${JAR_NAME}" CACHE INTERNAL "")
ocv_copyfiles_append_dir(JAVA_SRC_COPY "${OPENCV_JAVA_BINDINGS_DIR}/gen/java" "${java_src_dir}") ocv_copyfiles_append_dir(JAVA_SRC_COPY "${OPENCV_JAVA_BINDINGS_DIR}/gen/java" "${java_src_dir}")
@ -34,38 +35,98 @@ if(OPENCV_JAVADOC_LINK_URL)
set(CMAKE_CONFIG_OPENCV_JAVADOC_LINK "link=\"${OPENCV_JAVADOC_LINK_URL}\"") set(CMAKE_CONFIG_OPENCV_JAVADOC_LINK "link=\"${OPENCV_JAVADOC_LINK_URL}\"")
endif() endif()
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/build.xml.in" "${OPENCV_JAVA_DIR}/build.xml" @ONLY) if(OPENCV_JAVA_SDK_BUILD_TYPE STREQUAL "ANT")
list(APPEND depends "${OPENCV_JAVA_DIR}/build.xml") file(MAKE_DIRECTORY "${OPENCV_JAVA_DIR}/build/classes")
ocv_cmake_byproducts(__byproducts BYPRODUCTS "${OPENCV_JAR_FILE}") configure_file("${CMAKE_CURRENT_SOURCE_DIR}/build.xml.in" "${OPENCV_JAVA_DIR}/build.xml" @ONLY)
add_custom_command(OUTPUT "${OPENCV_DEPHELPER}/${the_module}_jar" list(APPEND depends "${OPENCV_JAVA_DIR}/build.xml")
${__byproducts} # required for add_custom_target() by ninja
COMMAND ${ANT_EXECUTABLE} -noinput -k jar ocv_cmake_byproducts(__byproducts BYPRODUCTS "${OPENCV_JAR_FILE}")
COMMAND ${CMAKE_COMMAND} -E touch "${OPENCV_DEPHELPER}/${the_module}_jar" add_custom_command(OUTPUT "${OPENCV_DEPHELPER}/${the_module}_jar"
WORKING_DIRECTORY "${OPENCV_JAVA_DIR}" ${__byproducts} # required for add_custom_target() by ninja
DEPENDS ${depends} COMMAND ${ANT_EXECUTABLE} -noinput -k jar
COMMENT "Generating ${JAR_NAME}" COMMAND ${CMAKE_COMMAND} -E touch "${OPENCV_DEPHELPER}/${the_module}_jar"
) WORKING_DIRECTORY "${OPENCV_JAVA_DIR}"
add_custom_target(${the_module}_jar DEPENDS "${OPENCV_DEPHELPER}/${the_module}_jar") DEPENDS ${depends}
COMMENT "Generating ${JAR_NAME}"
)
add_custom_target(${the_module}_jar DEPENDS "${OPENCV_DEPHELPER}/${the_module}_jar")
elseif(OPENCV_JAVA_SDK_BUILD_TYPE STREQUAL "JAVA")
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/MANIFEST.MF.in" "${OPENCV_JAVA_DIR}/MANIFEST.MF" @ONLY)
list(APPEND depends "${OPENCV_JAVA_DIR}/MANIFEST.MF")
ocv_cmake_byproducts(__byproducts BYPRODUCTS "${OPENCV_JAVA_DIR}/java_sources")
add_custom_command(OUTPUT "${OPENCV_DEPHELPER}/${the_module}_jar"
BYPRODUCTS ${__byproducts} # required for add_custom_target() by ninja
DEPENDS ${depends}
COMMAND ${CMAKE_COMMAND} -E touch "${OPENCV_DEPHELPER}/${the_module}_jar"
COMMAND ${CMAKE_COMMAND}
-D OPENCV_JAVA_DIR="${OPENCV_JAVA_DIR}/java"
-D OUTPUT="${OPENCV_JAVA_DIR}/java_sources"
-P "${CMAKE_CURRENT_SOURCE_DIR}/list_java_sources.cmake"
)
add_custom_target(${the_module}_jar_sources
DEPENDS "${OPENCV_DEPHELPER}/${the_module}_jar"
)
list(APPEND CMAKE_JAVA_COMPILE_FLAGS -encoding utf-8 ${OPENCV_EXTRA_JAVA_COMPILE_FLAGS})
add_jar(${the_module}_jar
SOURCES "@${OPENCV_JAVA_DIR}/java_sources"
MANIFEST "${OPENCV_JAVA_DIR}/MANIFEST.MF"
OUTPUT_NAME "${JAR_NAME_WE}"
OUTPUT_DIR "${OPENCV_JAR_DIR}")
add_dependencies(${the_module}_jar ${the_module}_jar_sources)
else()
ocv_assert(0)
endif()
install(FILES ${OPENCV_JAR_FILE} OPTIONAL DESTINATION ${OPENCV_JAR_INSTALL_PATH} COMPONENT java) install(FILES ${OPENCV_JAR_FILE} OPTIONAL DESTINATION ${OPENCV_JAR_INSTALL_PATH} COMPONENT java)
add_dependencies(${the_module} ${the_module}_jar) add_dependencies(${the_module} ${the_module}_jar)
if(BUILD_DOCS) if(BUILD_DOCS)
add_custom_command(OUTPUT "${OPENCV_DEPHELPER}/${the_module}doc" if(OPENCV_JAVA_SDK_BUILD_TYPE STREQUAL "ANT")
COMMAND ${ANT_EXECUTABLE} -noinput -k javadoc add_custom_command(OUTPUT "${OPENCV_DEPHELPER}/${the_module}doc"
COMMAND ${CMAKE_COMMAND} -E touch "${OPENCV_DEPHELPER}/${the_module}doc" COMMAND ${ANT_EXECUTABLE} -noinput -k javadoc
WORKING_DIRECTORY "${OPENCV_JAVA_DIR}" COMMAND ${CMAKE_COMMAND} -E touch "${OPENCV_DEPHELPER}/${the_module}doc"
DEPENDS ${depends} WORKING_DIRECTORY "${OPENCV_JAVA_DIR}"
COMMENT "Generating Javadoc" DEPENDS ${depends}
) COMMENT "Generating Javadoc"
add_custom_target(${the_module}doc DEPENDS "${OPENCV_DEPHELPER}/${the_module}doc") )
install(DIRECTORY ${OpenCV_BINARY_DIR}/doc/doxygen/html/javadoc add_custom_target(${the_module}doc DEPENDS "${OPENCV_DEPHELPER}/${the_module}doc")
DESTINATION "${OPENCV_DOC_INSTALL_PATH}/html"
COMPONENT "docs" OPTIONAL install(DIRECTORY ${OpenCV_BINARY_DIR}/doc/doxygen/html/javadoc
${compatible_MESSAGE_NEVER} DESTINATION "${OPENCV_DOC_INSTALL_PATH}/html"
) COMPONENT "docs" OPTIONAL
${compatible_MESSAGE_NEVER}
)
elseif(OPENCV_JAVA_SDK_BUILD_TYPE STREQUAL "JAVA")
set(Java_JAVADOC_EXECUTABLE ${Java_JAVADOC_EXECUTABLE} -encoding utf-8)
# create_javadoc produces target ${_target}_javadoc
create_javadoc(${the_module}
FILES "@${OPENCV_JAVA_DIR}/java_sources"
SOURCEPATH "${OPENCV_JAVA_DIR}/java"
INSTALLPATH "${OPENCV_JAVADOC_DESTINATION}"
WINDOWTITLE "OpenCV ${OPENCV_VERSION_PLAIN} Java documentation"
DOCTITLE "OpenCV Java documentation (${OPENCV_VERSION})"
VERSION TRUE
)
add_dependencies(${the_module}_javadoc ${the_module}_jar_sources)
add_custom_target(${the_module}doc DEPENDS ${the_module}_javadoc)
install(DIRECTORY ${OpenCV_BINARY_DIR}/doc/doxygen/html/javadoc/${the_module}/
DESTINATION "${OPENCV_DOC_INSTALL_PATH}/html/javadoc"
COMPONENT "docs" OPTIONAL
${compatible_MESSAGE_NEVER}
)
else()
ocv_assert(0)
endif()
set(CMAKE_DOXYGEN_JAVADOC_NODE set(CMAKE_DOXYGEN_JAVADOC_NODE
"<tab type=\"user\" url=\"./javadoc/index.html\" title=\"Java documentation\"/>" "<tab type=\"user\" url=\"./javadoc/index.html\" title=\"Java documentation\"/>"
CACHE INTERNAL "Link to the Java documentation") # set to the cache to make it global CACHE INTERNAL "Link to the Java documentation") # set to the cache to make it global

@ -0,0 +1,5 @@
Specification-Title: OpenCV
Specification-Version: @OPENCV_VERSION@
Implementation-Title: OpenCV
Implementation-Version: @OPENCV_VCSVERSION@
Implementation-Date: @OPENCV_TIMESTAMP@

@ -0,0 +1,19 @@
file(GLOB_RECURSE java_sources "${OPENCV_JAVA_DIR}/*.java")
set(__sources "")
foreach(dst ${java_sources})
set(__sources "${__sources}${dst}\n")
endforeach()
function(ocv_update_file filepath content)
if(EXISTS "${filepath}")
file(READ "${filepath}" actual_content)
else()
set(actual_content "")
endif()
if(NOT ("${actual_content}" STREQUAL "${content}"))
file(WRITE "${filepath}" "${content}")
endif()
endfunction()
ocv_update_file("${OUTPUT}" "${__sources}")
Loading…
Cancel
Save