From 95415ac3a586207cd89b43c91078bf5a0a038de2 Mon Sep 17 00:00:00 2001
From: Alexander Alekhin <alexander.a.alekhin@gmail.com>
Date: Thu, 11 Jul 2019 20:04:05 +0000
Subject: [PATCH] android: change ANDROID_STL='c++_shared'

- fixes crashes in face-detector application
- libc++_shared.so is bundled automatically via CMake helper project
---
 modules/java/android_sdk/CMakeLists.txt             | 10 ++++++++++
 .../android_sdk/android_gradle_lib/build.gradle     | 13 +++++++++++++
 modules/java/android_sdk/build.gradle.in            | 13 +++++++++++++
 .../java/android_sdk/libcxx_helper/CMakeLists.txt   |  4 ++++
 modules/java/android_sdk/libcxx_helper/dummy.cpp    |  1 +
 platforms/android/build-tests/test_cmake_build.py   |  8 ++++----
 platforms/android/build_sdk.py                      |  2 +-
 7 files changed, 46 insertions(+), 5 deletions(-)
 create mode 100644 modules/java/android_sdk/libcxx_helper/CMakeLists.txt
 create mode 100644 modules/java/android_sdk/libcxx_helper/dummy.cpp

diff --git a/modules/java/android_sdk/CMakeLists.txt b/modules/java/android_sdk/CMakeLists.txt
index c45251bd68..fef286afbb 100644
--- a/modules/java/android_sdk/CMakeLists.txt
+++ b/modules/java/android_sdk/CMakeLists.txt
@@ -123,6 +123,16 @@ foreach(file ${seed_project_files_rel})
   endif()
 endforeach()
 
+# copy libcxx_helper
+set(__base_dir "${CMAKE_CURRENT_SOURCE_DIR}/")
+file(GLOB_RECURSE __files_rel RELATIVE "${__base_dir}/" "${__base_dir}/libcxx_helper/*")
+foreach(file ${__files_rel})
+  configure_file("${__base_dir}/${file}" "${OPENCV_JAVA_DIR}/${file}" @ONLY)
+  list(APPEND depends "${__base_dir}/${file}")
+  get_filename_component(install_subdir "${file}" PATH)
+  install(FILES "${OPENCV_JAVA_DIR}/${file}" DESTINATION "${JAVA_INSTALL_ROOT}/../${install_subdir}" COMPONENT java)
+endforeach()
+
 list(APPEND depends gen_opencv_java_source "${OPENCV_DEPHELPER}/gen_opencv_java_source")
 ocv_copyfiles_add_target(${the_module}_android_source_copy JAVA_SRC_COPY "Copy Java(Andoid SDK) source files" ${depends})
 file(REMOVE "${OPENCV_DEPHELPER}/${the_module}_android_source_copy")  # force rebuild after CMake run
diff --git a/modules/java/android_sdk/android_gradle_lib/build.gradle b/modules/java/android_sdk/android_gradle_lib/build.gradle
index eea2fd4dea..a272fd9822 100644
--- a/modules/java/android_sdk/android_gradle_lib/build.gradle
+++ b/modules/java/android_sdk/android_gradle_lib/build.gradle
@@ -7,6 +7,13 @@ android {
     defaultConfig {
         minSdkVersion @ANDROID_MIN_SDK_VERSION@
         targetSdkVersion @ANDROID_TARGET_SDK_VERSION@
+
+        externalNativeBuild {
+            cmake {
+                arguments "-DANDROID_STL=@ANDROID_STL@"
+                targets "opencv_jni_shared"
+            }
+        }
     }
 
     buildTypes {
@@ -37,6 +44,12 @@ android {
             manifest.srcFile 'AndroidManifest.xml'
         }
     }
+
+    externalNativeBuild {
+        cmake {
+            path (project.projectDir.toString() + '/libcxx_helper/CMakeLists.txt')
+        }
+    }
 }
 
 dependencies {
diff --git a/modules/java/android_sdk/build.gradle.in b/modules/java/android_sdk/build.gradle.in
index a69719e8a3..4335e5a4ea 100644
--- a/modules/java/android_sdk/build.gradle.in
+++ b/modules/java/android_sdk/build.gradle.in
@@ -99,6 +99,13 @@ android {
     defaultConfig {
         minSdkVersion @ANDROID_MIN_SDK_VERSION@
         targetSdkVersion @ANDROID_TARGET_SDK_VERSION@
+
+        externalNativeBuild {
+            cmake {
+                arguments "-DANDROID_STL=@ANDROID_STL@"
+                targets "opencv_jni_shared"
+            }
+        }
     }
 
     buildTypes {
@@ -129,6 +136,12 @@ android {
             manifest.srcFile 'java/AndroidManifest.xml'
         }
     }
+
+    externalNativeBuild {
+        cmake {
+            path (project.projectDir.toString() + '/libcxx_helper/CMakeLists.txt')
+        }
+    }
 }
 
 dependencies {
diff --git a/modules/java/android_sdk/libcxx_helper/CMakeLists.txt b/modules/java/android_sdk/libcxx_helper/CMakeLists.txt
new file mode 100644
index 0000000000..bc9146f457
--- /dev/null
+++ b/modules/java/android_sdk/libcxx_helper/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 3.6)
+
+# dummy target to bring libc++_shared.so into packages
+add_library(opencv_jni_shared STATIC dummy.cpp)
diff --git a/modules/java/android_sdk/libcxx_helper/dummy.cpp b/modules/java/android_sdk/libcxx_helper/dummy.cpp
new file mode 100644
index 0000000000..8b1a393741
--- /dev/null
+++ b/modules/java/android_sdk/libcxx_helper/dummy.cpp
@@ -0,0 +1 @@
+// empty
diff --git a/platforms/android/build-tests/test_cmake_build.py b/platforms/android/build-tests/test_cmake_build.py
index d837c9fa8c..25d185b8e5 100644
--- a/platforms/android/build-tests/test_cmake_build.py
+++ b/platforms/android/build-tests/test_cmake_build.py
@@ -112,10 +112,10 @@ class TestCmakeBuild(unittest.TestCase):
 
 def suite(workdir, opencv_cmake_path):
     abis = {
-        "armeabi-v7a": { "ANDROID_ABI": "armeabi-v7a", "ANDROID_TOOLCHAIN": "clang", "ANDROID_STL": "c++_static", 'ANDROID_NATIVE_API_LEVEL': "21" },
-        "arm64-v8a": { "ANDROID_ABI": "arm64-v8a", "ANDROID_TOOLCHAIN": "clang", "ANDROID_STL": "c++_static", 'ANDROID_NATIVE_API_LEVEL': "21" },
-        "x86": { "ANDROID_ABI": "x86", "ANDROID_TOOLCHAIN": "clang", "ANDROID_STL": "c++_static", 'ANDROID_NATIVE_API_LEVEL': "21" },
-        "x86_64": { "ANDROID_ABI": "x86_64", "ANDROID_TOOLCHAIN": "clang", "ANDROID_STL": "c++_static", 'ANDROID_NATIVE_API_LEVEL': "21" },
+        "armeabi-v7a": { "ANDROID_ABI": "armeabi-v7a", "ANDROID_TOOLCHAIN": "clang", "ANDROID_STL": "c++_shared", 'ANDROID_NATIVE_API_LEVEL': "21" },
+        "arm64-v8a": { "ANDROID_ABI": "arm64-v8a", "ANDROID_TOOLCHAIN": "clang", "ANDROID_STL": "c++_shared", 'ANDROID_NATIVE_API_LEVEL': "21" },
+        "x86": { "ANDROID_ABI": "x86", "ANDROID_TOOLCHAIN": "clang", "ANDROID_STL": "c++_shared", 'ANDROID_NATIVE_API_LEVEL': "21" },
+        "x86_64": { "ANDROID_ABI": "x86_64", "ANDROID_TOOLCHAIN": "clang", "ANDROID_STL": "c++_shared", 'ANDROID_NATIVE_API_LEVEL': "21" },
     }
 
     suite = unittest.TestSuite()
diff --git a/platforms/android/build_sdk.py b/platforms/android/build_sdk.py
index 352d5088de..991133b066 100755
--- a/platforms/android/build_sdk.py
+++ b/platforms/android/build_sdk.py
@@ -125,7 +125,7 @@ class ABI:
             self.cmake_vars['ANDROID_TOOLCHAIN_NAME'] = toolchain
         else:
             self.cmake_vars['ANDROID_TOOLCHAIN'] = 'clang'
-            self.cmake_vars['ANDROID_STL'] = 'c++_static'
+            self.cmake_vars['ANDROID_STL'] = 'c++_shared'
         if ndk_api_level:
             self.cmake_vars['ANDROID_NATIVE_API_LEVEL'] = ndk_api_level
         self.cmake_vars.update(cmake_vars)