From aa6b399b5a0428e259d1ac854f59feb2e589e890 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Fri, 17 Nov 2023 15:15:04 +0300 Subject: [PATCH] AAR package build and test with CI - Use the same tools and plugins for SDK build and AAR build - Added script to test Gradle-based samples against local maven repo - Various local fixes and debug prints --- cmake/android/android_gradle_projects.cmake | 10 ++-- platforms/android/aar-template/build.gradle | 4 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- platforms/android/build-tests/test_gradle.sh | 6 ++- .../android/build-tests/test_gradle_aar.sh | 47 +++++++++++++++++++ platforms/android/build_java_shared_aar.py | 14 +++++- platforms/android/build_static_aar.py | 12 +++++ samples/android/15-puzzle/build.gradle.in | 6 ++- .../camera-calibration/build.gradle.in | 2 + .../color-blob-detection/build.gradle.in | 2 + .../android/face-detection/build.gradle.in | 2 + .../android/face-detection/jni/CMakeLists.txt | 2 + .../image-manipulations/build.gradle.in | 2 + .../mobilenet-objdetect/build.gradle.in | 2 + .../tutorial-1-camerapreview/build.gradle.in | 2 + .../build.gradle.in | 2 + .../jni/CMakeLists.txt | 2 + .../tutorial-3-cameracontrol/build.gradle.in | 2 + 18 files changed, 107 insertions(+), 14 deletions(-) create mode 100755 platforms/android/build-tests/test_gradle_aar.sh diff --git a/cmake/android/android_gradle_projects.cmake b/cmake/android/android_gradle_projects.cmake index a3f4ba2c65..796d3aea5a 100644 --- a/cmake/android/android_gradle_projects.cmake +++ b/cmake/android/android_gradle_projects.cmake @@ -114,8 +114,7 @@ endif() file(WRITE "${ANDROID_BUILD_BASE_DIR}/settings.gradle" " gradle.ext { - //opencv_source = 'maven_central' - //opencv_source = 'maven_local' + // possible options: 'maven_central', 'maven_local', 'sdk_path' opencv_source = 'sdk_path' } @@ -126,19 +125,18 @@ file(WRITE "${ANDROID_TMP_INSTALL_BASE_DIR}/settings.gradle" " rootProject.name = 'opencv_samples' gradle.ext { - //opencv_source = 'maven_central' - //opencv_source = 'maven_local' + // possible options: 'maven_central', 'maven_local', 'sdk_path' opencv_source = 'sdk_path' } if (gradle.opencv_source == 'maven_local') { gradle.ext { - opencv_maven_path = '/' + opencv_maven_path = '' } } if (gradle.opencv_source == 'sdk_path') { - def opencvsdk='../' + def opencvsdk = '../' //def opencvsdk='/' //println opencvsdk include ':opencv' diff --git a/platforms/android/aar-template/build.gradle b/platforms/android/aar-template/build.gradle index b7a22c372c..decab5bc55 100644 --- a/platforms/android/aar-template/build.gradle +++ b/platforms/android/aar-template/build.gradle @@ -1,4 +1,4 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { - id 'com.android.library' version '8.0.2' apply false -} \ No newline at end of file + id 'com.android.library' version '7.3.0' apply false +} diff --git a/platforms/android/aar-template/gradle/wrapper/gradle-wrapper.properties b/platforms/android/aar-template/gradle/wrapper/gradle-wrapper.properties index 9e6a7833f8..c4f47b9a2e 100644 --- a/platforms/android/aar-template/gradle/wrapper/gradle-wrapper.properties +++ b/platforms/android/aar-template/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Mon Jul 10 11:57:38 SGT 2023 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/platforms/android/build-tests/test_gradle.sh b/platforms/android/build-tests/test_gradle.sh index bb6bc91a8e..129d1480bc 100755 --- a/platforms/android/build-tests/test_gradle.sh +++ b/platforms/android/build-tests/test_gradle.sh @@ -1,5 +1,6 @@ #!/bin/bash -e SDK_DIR=$1 + echo "OpenCV Android SDK path: ${SDK_DIR}" ANDROID_HOME=${ANDROID_HOME:-${ANDROID_SDK_ROOT:-${ANDROID_SDK?Required ANDROID_HOME/ANDROID_SDK/ANDROID_SDK_ROOT}}} @@ -29,9 +30,10 @@ rm -rf "test-gradle" cp -rp "${SDK_DIR}" "test-gradle" echo "Cloning OpenCV Android SDK ... Done!" -echo "Force Current CMake for Gradle project" # drop cmake bin name and "bin" folder from path -echo "cmake.dir=$(dirname $(dirname $(which cmake)))" > "test-gradle/samples/local.properties" +echo "ndk.dir=${ANDROID_NDK}" > "test-gradle/samples/local.properties" +echo "cmake.dir=$(dirname $(dirname $(which cmake)))" >> "test-gradle/samples/local.properties" + echo "Run gradle ..." (cd "test-gradle/samples"; ./gradlew -i assemble) diff --git a/platforms/android/build-tests/test_gradle_aar.sh b/platforms/android/build-tests/test_gradle_aar.sh new file mode 100755 index 0000000000..63f34514b1 --- /dev/null +++ b/platforms/android/build-tests/test_gradle_aar.sh @@ -0,0 +1,47 @@ +#!/bin/bash -e +SDK_DIR=$1 +LOCAL_MAVEN_REPO=$2 +echo "OpenCV Android SDK path: ${SDK_DIR}" +echo "Use local maven repo from $LOCAL_MAVEN_REPO" + +ANDROID_HOME=${ANDROID_HOME:-${ANDROID_SDK_ROOT:-${ANDROID_SDK?Required ANDROID_HOME/ANDROID_SDK/ANDROID_SDK_ROOT}}} +ANDROID_NDK=${ANDROID_NDK_HOME-${ANDROID_NDK:-${NDKROOT?Required ANDROID_NDK_HOME/ANDROID_NDK/NDKROOT}}} + +echo "Android SDK: ${ANDROID_HOME}" +echo "Android NDK: ${ANDROID_NDK}" + +if [ ! -d "${ANDROID_HOME}" ]; then + echo "FATAL: Missing Android SDK directory" + exit 1 +fi +if [ ! -d "${ANDROID_NDK}" ]; then + echo "FATAL: Missing Android NDK directory" + exit 1 +fi + +export ANDROID_HOME=${ANDROID_HOME} +export ANDROID_SDK=${ANDROID_HOME} +export ANDROID_SDK_ROOT=${ANDROID_HOME} + +export ANDROID_NDK=${ANDROID_NDK} +export ANDROID_NDK_HOME=${ANDROID_NDK} + +echo "Cloning OpenCV Android SDK ..." +rm -rf "test-gradle-aar" +mkdir test-gradle-aar +cp -rp ${SDK_DIR}/samples/* test-gradle-aar/ +echo "Cloning OpenCV Android SDK ... Done!" + +# drop cmake bin name and "bin" folder from path +echo "ndk.dir=${ANDROID_NDK}" > "test-gradle-aar/local.properties" +echo "cmake.dir=$(dirname $(dirname $(which cmake)))" >> "test-gradle-aar/local.properties" + +sed -i "s/opencv_source = 'sdk_path'/opencv_source = 'maven_local'/g" test-gradle-aar/settings.gradle +sed -i "s+opencv_maven_path = ''+opencv_maven_path = 'file\\://$LOCAL_MAVEN_REPO'+g" test-gradle-aar/settings.gradle + +echo "Run gradle ..." +(cd "test-gradle-aar"; ./gradlew -i assemble) + +echo "#" +echo "# Done!" +echo "#" diff --git a/platforms/android/build_java_shared_aar.py b/platforms/android/build_java_shared_aar.py index ea59bad839..2a7768a2d4 100755 --- a/platforms/android/build_java_shared_aar.py +++ b/platforms/android/build_java_shared_aar.py @@ -100,6 +100,16 @@ def main(args): path.join(ANDROID_PROJECT_DIR, "OpenCV/src/main/cpp/CMakeLists.txt"), {"LIB_NAME": lib_name, "LIB_TYPE": "SHARED"}) + local_props = "" + if args.ndk_location: + local_props += "ndk.dir=" + args.ndk_location + "\n" + if args.cmake_location: + local_props += "cmake.dir=" + args.cmake_location + "\n" + + if local_props: + with open(path.join(ANDROID_PROJECT_DIR, "local.properties"), "wt") as f: + f.write(local_props) + # Copying Java code and C++ public headers from SDK to the Android project for src, dst in COPY_FROM_SDK_TO_ANDROID_PROJECT: shutil.copytree(path.join(args.opencv_sdk_path, src), @@ -149,8 +159,10 @@ if __name__ == "__main__": parser.add_argument('opencv_sdk_path') parser.add_argument('--android_compile_sdk', default="26") parser.add_argument('--android_min_sdk', default="21") - parser.add_argument('--android_target_sdk', default="26") + parser.add_argument('--android_target_sdk', default="31") parser.add_argument('--java_version', default="1_8") + parser.add_argument('--ndk_location', default="") + parser.add_argument('--cmake_location', default="") args = parser.parse_args() main(args) diff --git a/platforms/android/build_static_aar.py b/platforms/android/build_static_aar.py index df6d55a6fd..b5dc680081 100755 --- a/platforms/android/build_static_aar.py +++ b/platforms/android/build_static_aar.py @@ -131,6 +131,16 @@ def main(args): path.join(ANDROID_PROJECT_DIR, "OpenCV/src/main/cpp/CMakeLists.txt"), {"LIB_NAME": "templib", "LIB_TYPE": "STATIC"}) + local_props = "" + if args.ndk_location: + local_props += "ndk.dir=" + args.ndk_location + "\n" + if args.cmake_location: + local_props += "cmake.dir=" + args.cmake_location + "\n" + + if local_props: + with open(path.join(ANDROID_PROJECT_DIR, "local.properties"), "wt") as f: + f.write(local_props) + opencv_libs = get_list_of_opencv_libs(sdk_dir) external_libs = get_list_of_3rdparty_libs(sdk_dir, abis) @@ -224,6 +234,8 @@ if __name__ == "__main__": parser.add_argument('--android_min_sdk', default="21") parser.add_argument('--android_target_sdk', default="26") parser.add_argument('--java_version', default="1_8") + parser.add_argument('--ndk_location', default="") + parser.add_argument('--cmake_location', default="") args = parser.parse_args() main(args) diff --git a/samples/android/15-puzzle/build.gradle.in b/samples/android/15-puzzle/build.gradle.in index b1808d3892..bf8921b98d 100644 --- a/samples/android/15-puzzle/build.gradle.in +++ b/samples/android/15-puzzle/build.gradle.in @@ -28,9 +28,11 @@ android { dependencies { //implementation fileTree(dir: 'libs', include: ['*.jar']) - if (gradle.opencv_source == "sdk_path") { + if (gradle.opencv_source == 'sdk_path') { + println 'Using OpenCV from SDK' implementation project(':opencv') - } else if (gradle.opencv_source == "maven_local" || gradle.opencv_source == "maven_cenral") { + } else if (gradle.opencv_source == 'maven_local' || gradle.opencv_source == 'maven_cenral') { + println 'Using OpenCV from Maven repo' implementation 'org.opencv:opencv:@OPENCV_VERSION_PLAIN@' } } diff --git a/samples/android/camera-calibration/build.gradle.in b/samples/android/camera-calibration/build.gradle.in index 69c5b5bbee..d79df7777e 100644 --- a/samples/android/camera-calibration/build.gradle.in +++ b/samples/android/camera-calibration/build.gradle.in @@ -29,8 +29,10 @@ android { dependencies { //implementation fileTree(dir: 'libs', include: ['*.jar']) if (gradle.opencv_source == "sdk_path") { + println 'Using OpenCV from SDK' implementation project(':opencv') } else if (gradle.opencv_source == "maven_local" || gradle.opencv_source == "maven_cenral") { + println 'Using OpenCV from Maven repo' implementation 'org.opencv:opencv:@OPENCV_VERSION_PLAIN@' } } diff --git a/samples/android/color-blob-detection/build.gradle.in b/samples/android/color-blob-detection/build.gradle.in index 82cbfe79f6..6d544592a4 100644 --- a/samples/android/color-blob-detection/build.gradle.in +++ b/samples/android/color-blob-detection/build.gradle.in @@ -29,8 +29,10 @@ android { dependencies { //implementation fileTree(dir: 'libs', include: ['*.jar']) if (gradle.opencv_source == "sdk_path") { + println 'Using OpenCV from from SDK' implementation project(':opencv') } else if (gradle.opencv_source == "maven_local" || gradle.opencv_source == "maven_cenral") { + println 'Using OpenCV from Maven repo' implementation 'org.opencv:opencv:@OPENCV_VERSION_PLAIN@' } } diff --git a/samples/android/face-detection/build.gradle.in b/samples/android/face-detection/build.gradle.in index 87fdbbf533..5ebf231291 100644 --- a/samples/android/face-detection/build.gradle.in +++ b/samples/android/face-detection/build.gradle.in @@ -53,8 +53,10 @@ android { dependencies { //implementation fileTree(dir: 'libs', include: ['*.jar']) if (gradle.opencv_source == "sdk_path") { + println 'Using OpenCV from from SDK' implementation project(':opencv') } else if (gradle.opencv_source == "maven_local" || gradle.opencv_source == "maven_cenral") { + println 'Using OpenCV from Maven repo' implementation 'org.opencv:opencv:@OPENCV_VERSION_PLAIN@' } } diff --git a/samples/android/face-detection/jni/CMakeLists.txt b/samples/android/face-detection/jni/CMakeLists.txt index 4c18a0bca3..4da6e0e00e 100644 --- a/samples/android/face-detection/jni/CMakeLists.txt +++ b/samples/android/face-detection/jni/CMakeLists.txt @@ -4,8 +4,10 @@ set(target detection_based_tracker) project(${target} CXX) if (OPENCV_FROM_SDK) + message(STATUS "Using OpenCV from local SDK") set(ANDROID_OPENCV_COMPONENTS "opencv_java" CACHE STRING "") else() + message(STATUS "Using OpenCV from AAR (Maven repo)") set(ANDROID_OPENCV_COMPONENTS "OpenCV::opencv_java${OPENCV_VERSION_MAJOR}" CACHE STRING "") endif() diff --git a/samples/android/image-manipulations/build.gradle.in b/samples/android/image-manipulations/build.gradle.in index d36d270a19..a227d548cf 100644 --- a/samples/android/image-manipulations/build.gradle.in +++ b/samples/android/image-manipulations/build.gradle.in @@ -29,8 +29,10 @@ android { dependencies { //implementation fileTree(dir: 'libs', include: ['*.jar']) if (gradle.opencv_source == "sdk_path") { + println 'Using OpenCV from from SDK' implementation project(':opencv') } else if (gradle.opencv_source == "maven_local" || gradle.opencv_source == "maven_cenral") { + println 'Using OpenCV from Maven repo' implementation 'org.opencv:opencv:@OPENCV_VERSION_PLAIN@' } } diff --git a/samples/android/mobilenet-objdetect/build.gradle.in b/samples/android/mobilenet-objdetect/build.gradle.in index e1ac8b503e..4cb1789e19 100644 --- a/samples/android/mobilenet-objdetect/build.gradle.in +++ b/samples/android/mobilenet-objdetect/build.gradle.in @@ -29,8 +29,10 @@ android { dependencies { //implementation fileTree(dir: 'libs', include: ['*.jar']) if (gradle.opencv_source == "sdk_path") { + println 'Using OpenCV from SDK' implementation project(':opencv') } else if (gradle.opencv_source == "maven_local" || gradle.opencv_source == "maven_cenral") { + println 'Using OpenCV from Maven repo' implementation 'org.opencv:opencv:@OPENCV_VERSION_PLAIN@' } } diff --git a/samples/android/tutorial-1-camerapreview/build.gradle.in b/samples/android/tutorial-1-camerapreview/build.gradle.in index 9de83844ab..a0d44eaf9a 100644 --- a/samples/android/tutorial-1-camerapreview/build.gradle.in +++ b/samples/android/tutorial-1-camerapreview/build.gradle.in @@ -29,8 +29,10 @@ android { dependencies { //implementation fileTree(dir: 'libs', include: ['*.jar']) if (gradle.opencv_source == "sdk_path") { + println 'Using OpenCV from SDK' implementation project(':opencv') } else if (gradle.opencv_source == "maven_local" || gradle.opencv_source == "maven_cenral") { + println 'Using OpenCV from Maven repo' implementation 'org.opencv:opencv:@OPENCV_VERSION_PLAIN@' } } diff --git a/samples/android/tutorial-2-mixedprocessing/build.gradle.in b/samples/android/tutorial-2-mixedprocessing/build.gradle.in index 601f946797..4125d65a38 100644 --- a/samples/android/tutorial-2-mixedprocessing/build.gradle.in +++ b/samples/android/tutorial-2-mixedprocessing/build.gradle.in @@ -53,8 +53,10 @@ android { dependencies { //implementation fileTree(dir: 'libs', include: ['*.jar']) if (gradle.opencv_source == "sdk_path") { + println 'Using OpenCV from SDK' implementation project(':opencv') } else if (gradle.opencv_source == "maven_local" || gradle.opencv_source == "maven_cenral") { + println 'Using OpenCV from Maven repo' implementation 'org.opencv:opencv:@OPENCV_VERSION_PLAIN@' } } diff --git a/samples/android/tutorial-2-mixedprocessing/jni/CMakeLists.txt b/samples/android/tutorial-2-mixedprocessing/jni/CMakeLists.txt index ff2a8a48f7..37e9a698bb 100644 --- a/samples/android/tutorial-2-mixedprocessing/jni/CMakeLists.txt +++ b/samples/android/tutorial-2-mixedprocessing/jni/CMakeLists.txt @@ -4,8 +4,10 @@ set(target mixed_sample) project(${target} CXX) if (OPENCV_FROM_SDK) + message(STATUS "Using OpenCV from local SDK") set(ANDROID_OPENCV_COMPONENTS "opencv_java" CACHE STRING "") else() + message(STATUS "Using OpenCV from AAR (Maven repo)") set(ANDROID_OPENCV_COMPONENTS "OpenCV::opencv_java${OPENCV_VERSION_MAJOR}" CACHE STRING "") endif() diff --git a/samples/android/tutorial-3-cameracontrol/build.gradle.in b/samples/android/tutorial-3-cameracontrol/build.gradle.in index a577cb6984..b7dffe86c5 100644 --- a/samples/android/tutorial-3-cameracontrol/build.gradle.in +++ b/samples/android/tutorial-3-cameracontrol/build.gradle.in @@ -29,8 +29,10 @@ android { dependencies { //implementation fileTree(dir: 'libs', include: ['*.jar']) if (gradle.opencv_source == "sdk_path") { + println 'Using OpenCV from SDK' implementation project(':opencv') } else if (gradle.opencv_source == "maven_local" || gradle.opencv_source == "maven_cenral") { + println 'Using OpenCV from Maven repo' implementation 'org.opencv:opencv:@OPENCV_VERSION_PLAIN@' } }