test_cmake_build.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. #!/usr/bin/env python
  2. import unittest
  3. import os, sys, subprocess, argparse, shutil, re
  4. import logging as log
  5. log.basicConfig(format='%(message)s', level=log.DEBUG)
  6. CMAKE_TEMPLATE='''\
  7. CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
  8. # Enable C++11
  9. set(CMAKE_CXX_STANDARD 11)
  10. set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
  11. SET(PROJECT_NAME hello-android)
  12. PROJECT(${PROJECT_NAME})
  13. FIND_PACKAGE(OpenCV REQUIRED %(libset)s)
  14. FILE(GLOB srcs "*.cpp")
  15. ADD_EXECUTABLE(${PROJECT_NAME} ${srcs})
  16. TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${OpenCV_LIBS} dl z)
  17. '''
  18. CPP_TEMPLATE = '''\
  19. #include <opencv2/core.hpp>
  20. #include <opencv2/highgui.hpp>
  21. #include <opencv2/imgproc.hpp>
  22. using namespace cv;
  23. const char* message = "Hello Android!";
  24. int main(int argc, char* argv[])
  25. {
  26. (void)argc; (void)argv;
  27. printf("%s\\n", message);
  28. Size textsize = getTextSize(message, FONT_HERSHEY_COMPLEX, 3, 5, 0);
  29. Mat img(textsize.height + 20, textsize.width + 20, CV_32FC1, Scalar(230,230,230));
  30. putText(img, message, Point(10, img.rows - 10), FONT_HERSHEY_COMPLEX, 3, Scalar(0, 0, 0), 5);
  31. imwrite("/mnt/sdcard/HelloAndroid.png", img);
  32. return 0;
  33. }
  34. '''
  35. #===================================================================================================
  36. class TestCmakeBuild(unittest.TestCase):
  37. def __init__(self, libset, abi, cmake_vars, opencv_cmake_path, workdir, *args, **kwargs):
  38. unittest.TestCase.__init__(self, *args, **kwargs)
  39. self.libset = libset
  40. self.abi = abi
  41. self.cmake_vars = cmake_vars
  42. self.opencv_cmake_path = opencv_cmake_path
  43. self.workdir = workdir
  44. self.srcdir = os.path.join(self.workdir, "src")
  45. self.bindir = os.path.join(self.workdir, "build")
  46. def shortDescription(self):
  47. return "ABI: %s, LIBSET: %s" % (self.abi, self.libset)
  48. def getCMakeToolchain(self):
  49. if True:
  50. toolchain = os.path.join(os.environ['ANDROID_NDK'], 'build', 'cmake', 'android.toolchain.cmake')
  51. if os.path.exists(toolchain):
  52. return toolchain
  53. toolchain = os.path.join(self.opencv_cmake_path, "android.toolchain.cmake")
  54. if os.path.exists(toolchain):
  55. return toolchain
  56. else:
  57. raise Exception("Can't find toolchain")
  58. def gen_cmakelists(self):
  59. return CMAKE_TEMPLATE % {"libset": self.libset}
  60. def gen_code(self):
  61. return CPP_TEMPLATE
  62. def write_src_file(self, fname, content):
  63. with open(os.path.join(self.srcdir, fname), "w") as f:
  64. f.write(content)
  65. def setUp(self):
  66. if os.path.exists(self.workdir):
  67. shutil.rmtree(self.workdir)
  68. os.mkdir(self.workdir)
  69. os.mkdir(self.srcdir)
  70. os.mkdir(self.bindir)
  71. self.write_src_file("CMakeLists.txt", self.gen_cmakelists())
  72. self.write_src_file("main.cpp", self.gen_code())
  73. os.chdir(self.bindir)
  74. def tearDown(self):
  75. pass
  76. #if os.path.exists(self.workdir):
  77. # shutil.rmtree(self.workdir)
  78. def runTest(self):
  79. cmd = [
  80. "cmake",
  81. "-GNinja",
  82. "-DOpenCV_DIR=%s" % self.opencv_cmake_path,
  83. "-DCMAKE_TOOLCHAIN_FILE=%s" % self.getCMakeToolchain(),
  84. self.srcdir
  85. ] + [ "-D{}={}".format(key, value) for key, value in self.cmake_vars.items() ]
  86. log.info("Executing: %s" % cmd)
  87. retcode = subprocess.call(cmd)
  88. self.assertEqual(retcode, 0, "cmake failed")
  89. cmd = ["ninja", "-v"]
  90. log.info("Executing: %s" % cmd)
  91. retcode = subprocess.call(cmd)
  92. self.assertEqual(retcode, 0, "make failed")
  93. def suite(workdir, opencv_cmake_path):
  94. abis = {
  95. "armeabi-v7a": { "ANDROID_ABI": "armeabi-v7a", "ANDROID_TOOLCHAIN": "clang", "ANDROID_STL": "c++_shared", 'ANDROID_NATIVE_API_LEVEL': "21" },
  96. "arm64-v8a": { "ANDROID_ABI": "arm64-v8a", "ANDROID_TOOLCHAIN": "clang", "ANDROID_STL": "c++_shared", 'ANDROID_NATIVE_API_LEVEL': "21" },
  97. "x86": { "ANDROID_ABI": "x86", "ANDROID_TOOLCHAIN": "clang", "ANDROID_STL": "c++_shared", 'ANDROID_NATIVE_API_LEVEL': "21" },
  98. "x86_64": { "ANDROID_ABI": "x86_64", "ANDROID_TOOLCHAIN": "clang", "ANDROID_STL": "c++_shared", 'ANDROID_NATIVE_API_LEVEL': "21" },
  99. }
  100. suite = unittest.TestSuite()
  101. for libset in ["", "opencv_java"]:
  102. for abi, cmake_vars in abis.items():
  103. suite.addTest(TestCmakeBuild(libset, abi, cmake_vars, opencv_cmake_path,
  104. os.path.join(workdir, "{}-{}".format(abi, "static" if libset == "" else "shared"))))
  105. return suite
  106. if __name__ == '__main__':
  107. parser = argparse.ArgumentParser(description='Test OpenCV for Android SDK with cmake')
  108. parser.add_argument('--sdk_path', help="Path to Android SDK to use for build")
  109. parser.add_argument('--ndk_path', help="Path to Android NDK to use for build")
  110. parser.add_argument("--workdir", default="testspace", help="Working directory (and output)")
  111. parser.add_argument("opencv_cmake_path", help="Path to folder with OpenCVConfig.cmake and android.toolchain.cmake (usually <SDK>/sdk/native/jni/")
  112. args = parser.parse_args()
  113. if args.sdk_path is not None:
  114. os.environ["ANDROID_SDK"] = os.path.abspath(args.sdk_path)
  115. if args.ndk_path is not None:
  116. os.environ["ANDROID_NDK"] = os.path.abspath(args.ndk_path)
  117. if not 'ANDROID_HOME' in os.environ and 'ANDROID_SDK' in os.environ:
  118. os.environ['ANDROID_HOME'] = os.environ["ANDROID_SDK"]
  119. print("Using SDK: %s" % os.environ["ANDROID_SDK"])
  120. print("Using NDK: %s" % os.environ["ANDROID_NDK"])
  121. workdir = os.path.abspath(args.workdir)
  122. if not os.path.exists(workdir):
  123. os.mkdir(workdir)
  124. res = unittest.TextTestRunner(verbosity=3).run(suite(workdir, os.path.abspath(args.opencv_cmake_path)))
  125. if not res.wasSuccessful():
  126. sys.exit(res)