xmake.lua 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. package("opencv-mobile")
  2. set_homepage("https://github.com/nihui/opencv-mobile")
  3. set_description("The minimal opencv for Android, iOS, ARM Linux, Windows, Linux, MacOS, WebAssembly")
  4. set_license("Apache-2.0")
  5. -- parse version-tag: version -> ocv, tag -> ocv-mobile
  6. if on_source then
  7. on_source(function (package)
  8. local raw_ver = package:requireinfo().version
  9. if raw_ver and raw_ver:find('-') then
  10. local vers = raw_ver:split('-', {plain = true})
  11. if #vers == 2 then
  12. local ver_map = {
  13. ["v29"] = {
  14. ["4.10.0"] = "e9209285ad4d682536db4505bc06e46b94b9e56d91896e16c2853c83a870f004",
  15. ["3.4.20"] = "85c19b443454d3ae839d8f4f7a6a71c79f9ac38592a8a96e2f806fc0c68b64f4",
  16. },
  17. ["v31"] = {
  18. ["4.10.0"] = "0ad54eef6fbd34787a6b13e9486f97e99102b1dc478eb74f2e8d30008c35be4e",
  19. ["3.4.20"] = "60d05862441e85072e4e45b5241d1799de18f4a755bf26a7a89583d968b00e42",
  20. },
  21. ["v33"] = {
  22. ["4.11.0"] = "394b0dc31b9fee48333b6f043b0f22942ed95cd9b5acd101995e3054f468f930",
  23. ["3.4.20"] = "6c0b45d1df1165c798d8e051b049c10ec55fa84cba2a6fbd6f7cfe93ab36ebd0",
  24. },
  25. ["v34"] = {
  26. ["4.12.0"] = "34f2f113dd78392baaba97cae74226a0337e14b4d6b938f17e215c25d547dad6",
  27. ["3.4.20"] = "c976c30d47c18a6307f55703079a9c80f3bb73c7ec0dd50759a7e37aab111aff",
  28. }
  29. }
  30. local ocv_ver = vers[1]
  31. local ocv_mobile_ver = vers[2]
  32. if ver_map[ocv_mobile_ver] and ver_map[ocv_mobile_ver][ocv_ver] then
  33. local url = string.format("https://github.com/nihui/opencv-mobile/releases/download/%s/opencv-mobile-%s.zip", ocv_mobile_ver, ocv_ver)
  34. package:add("urls", url)
  35. -- package:version_set(ocv_ver)
  36. package:requireinfo().version = ocv_ver
  37. package:add("versions", ocv_ver, ver_map[ocv_mobile_ver][ocv_ver])
  38. else
  39. raise("package(opencv-mobile): The version that you are requiring is not supported or does not exist.")
  40. end
  41. else
  42. raise("package(opencv-mobile): Invalid version format! Please specify the version in the format of '<opencv_version>-<mobile_tag>' (like 4.12.0-v34).")
  43. end
  44. else
  45. -- this map stores the latest opencv-mobile version-tag mapping
  46. -- key = opencv version, value = the latest opencv-mobile release tag
  47. local lts_version_map = {
  48. ["4.12.0"] = "v34",
  49. ["4.11.0"] = "v33",
  50. ["4.10.0"] = "v31",
  51. ["3.4.20"] = "v34",
  52. }
  53. package:add("urls", "https://github.com/nihui/opencv-mobile/releases/download/$(version).zip", {version = function (version)
  54. local tag = lts_version_map[tostring(version)]
  55. if tag then
  56. return string.format("%s/opencv-mobile-%s", tag, tostring(version))
  57. else
  58. raise("The version of opencv-mobile that you are requiring is not supported or exists.")
  59. end
  60. end})
  61. package:add("versions", "4.12.0", "34f2f113dd78392baaba97cae74226a0337e14b4d6b938f17e215c25d547dad6") -- v34
  62. package:add("versions", "4.11.0", "394b0dc31b9fee48333b6f043b0f22942ed95cd9b5acd101995e3054f468f930") -- v33
  63. package:add("versions", "4.10.0", "0ad54eef6fbd34787a6b13e9486f97e99102b1dc478eb74f2e8d30008c35be4e") -- v31
  64. package:add("versions", "3.4.20", "c976c30d47c18a6307f55703079a9c80f3bb73c7ec0dd50759a7e37aab111aff") -- v34
  65. end
  66. end)
  67. end
  68. add_patches("*", "patches/msvc.patch", "6fa760ea58c8b90c87129f16c84b128a4447ea11cee7d6568ea4f5e7ae250971")
  69. add_deps("cmake")
  70. if not is_plat("android", "iphoneos") then
  71. add_deps("openmp")
  72. end
  73. if on_check then
  74. on_check("android", function (package)
  75. -- https://github.com/android/ndk/issues/1202#issuecomment-768524852
  76. if package:is_arch("armeabi-v7a") then
  77. local ndk = package:toolchain("ndk"):config("ndkver")
  78. assert(ndk and tonumber(ndk) >= 23, "package(opencv-mobile): armeabi-v7a requires NDK version >= r23")
  79. end
  80. end)
  81. end
  82. on_load("android", "iphoneos", "linux", "macosx", "windows", "mingw@windows,msys", function (package)
  83. if package:is_plat("windows") then
  84. local arch = "x64"
  85. if package:is_arch("x86") then arch = "x86"
  86. elseif package:is_arch("arm64") then arch = "ARM64"
  87. end
  88. local linkdir = (package:config("shared") and "lib" or "staticlib")
  89. local vs = package:toolchain("msvc"):config("vs")
  90. local vc_ver = "vc13"
  91. if vs == "2015" then vc_ver = "vc14"
  92. elseif vs == "2017" then vc_ver = "vc15"
  93. elseif vs == "2019" then vc_ver = "vc16"
  94. elseif vs == "2022" then vc_ver = "vc17"
  95. elseif vs == "2026" then vc_ver = "vc18"
  96. end
  97. package:add("linkdirs", linkdir) -- fix path for 4.9.0/vs2022
  98. package:add("linkdirs", path.join(arch, vc_ver, linkdir))
  99. elseif package:is_plat("mingw") then
  100. local arch = (package:is_arch("x86_64") and "x64" or "x86")
  101. local linkdir = (package:config("shared") and "lib" or "staticlib")
  102. package:add("linkdirs", path.join(arch, "mingw", linkdir))
  103. elseif package:is_plat("android") then
  104. local linkdir = (package:config("shared") and "libs" or "staticlibs")
  105. package:add("linkdirs", path.join("sdk/native", linkdir, package:targetarch()))
  106. package:add("linkdirs", path.join("sdk/native/3rdparty/libs", package:targetarch()))
  107. package:add("includedirs", "sdk/native/jni/include")
  108. elseif package:version():ge("4.0") then
  109. package:add("includedirs", "include/opencv4")
  110. end
  111. end)
  112. on_install("android", "iphoneos", "linux", "macosx", "windows", "mingw@windows,msys", function (package)
  113. if package:is_plat("windows", "mingw") then
  114. -- fix for v30-v34
  115. io.replace("modules/highgui/src/display_win32.cpp", "#include <mutex>\n\n", "#include <mutex>\n#include <cstdio>\n\n", {plain = true})
  116. -- fix for v30, v31
  117. io.replace("modules/highgui/src/display_win32.cpp", "static LRESULT", "LRESULT", {plain = true})
  118. io.replace("modules/highgui/src/display_win32.h", "#include <Windows.h>", "#include <windows.h>", {plain = true})
  119. io.replace("modules/highgui/src/display_win32.h", "static LRESULT", "LRESULT", {plain = true})
  120. end
  121. -- no platforms folder https://github.com/nihui/opencv-mobile/blob/v32/.github/workflows/release.yml#L73
  122. if package:is_plat("linux") and package:is_arch("arm64") and package:version():eq("4.11.0") then
  123. io.replace("cmake/platforms/OpenCV-Linux.cmake", "AND NOT CMAKE_CROSSCOMPILING", "AND FALSE", {plain = true})
  124. end
  125. local configs = {}
  126. table.insert(configs, "-DCMAKE_BUILD_TYPE=" .. (package:debug() and "Debug" or "Release"))
  127. table.insert(configs, "-DBUILD_SHARED_LIBS=" .. (package:config("shared") and "ON" or "OFF"))
  128. if package:is_plat("windows") then
  129. table.insert(configs, "-DBUILD_WITH_STATIC_CRT=" .. (package:has_runtime("MT", "MTd") and "ON" or "OFF"))
  130. if package:is_arch("arm64") then
  131. table.insert(configs, "-DOPENCV_SKIP_SYSTEM_PROCESSOR_DETECTION=ON")
  132. table.insert(configs, "-DAARCH64=ON")
  133. end
  134. elseif package:is_plat("mingw") then
  135. table.insert(configs, "-DCMAKE_SYSTEM_NAME=Windows")
  136. table.insert(configs, "-DCMAKE_SYSTEM_PROCESSOR=" .. (package:is_arch("x86_64") and "AMD64" or "i686"))
  137. elseif package:is_plat("macosx") then
  138. table.insert(configs, "-DCMAKE_SYSTEM_PROCESSOR=" .. (package:is_arch("x86_64") and "AMD64" or "ARM64"))
  139. elseif package:is_plat("android") then
  140. table.insert(configs, "-DANDROID_CPP_FEATURES=no-rtti no-exceptions")
  141. table.insert(configs, "-DOPENCV_DISABLE_FILESYSTEM_SUPPORT=ON")
  142. table.insert(configs, "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON")
  143. if package:is_arch("arm64-v8a") then
  144. -- https://github.com/Tencent/ncnn/pull/4362#issuecomment-2857174155
  145. local ndk = package:toolchain("ndk"):config("ndkver")
  146. if ndk and tonumber(ndk) >= 24 then
  147. table.insert(configs, "-DOPENCV_EXTRA_FLAGS=-mno-outline-atomics")
  148. end
  149. elseif package:is_arch("armeabi-v7a") then
  150. table.insert(configs, "-DANDROID_ARM_NEON=ON")
  151. end
  152. elseif package:is_plat("iphoneos") or (package:is_plat("linux") and package:is_arch("arm.*")) then
  153. table.insert(configs, "-DCMAKE_CXX_FLAGS=-fno-rtti -fno-exceptions")
  154. end
  155. local options = string.split(io.readfile("options.txt"), "\n", {plain = true})
  156. table.remove_if(options, function (_, option)
  157. return option:startswith("-DCMAKE_BUILD_TYPE") or option:startswith("-DBUILD_SHARED_LIBS") or option:startswith("-DBUILD_WITH_STATIC_CRT")
  158. end)
  159. table.join2(configs, options)
  160. import("package.tools.cmake").install(package, configs)
  161. if package:is_plat("windows") then
  162. local arch = "x64"
  163. if package:is_arch("x86") then arch = "x86"
  164. elseif package:is_arch("arm64") then arch = "ARM64"
  165. end
  166. if package:is_arch("arm64") then
  167. os.trymv(path.join(package:installdir(), "x64"), path.join(package:installdir(), "ARM64"))
  168. os.trymv(path.join(package:installdir(), "x86"), path.join(package:installdir(), "ARM64"))
  169. end
  170. local linkdir = (package:config("shared") and "lib" or "staticlib")
  171. local vs = package:toolchain("msvc"):config("vs")
  172. local vc_ver = "vc13"
  173. if vs == "2015" then vc_ver = "vc14"
  174. elseif vs == "2017" then vc_ver = "vc15"
  175. elseif vs == "2019" then vc_ver = "vc16"
  176. elseif vs == "2022" then vc_ver = "vc17"
  177. elseif vs == "2026" then vc_ver = "vc18"
  178. end
  179. local libfiles = {}
  180. table.join2(libfiles, os.files(package:installdir(linkdir, "*.lib")))
  181. table.join2(libfiles, os.files(package:installdir(arch, vc_ver, linkdir, "*.lib")))
  182. for _, f in ipairs(libfiles) do
  183. if not f:match("opencv_.+") then
  184. package:add("links", path.basename(f))
  185. end
  186. end
  187. package:addenv("PATH", "bin") -- fix path for 4.9.0/vs2022
  188. package:addenv("PATH", path.join(arch, vc_ver, "bin"))
  189. elseif package:is_plat("mingw") then
  190. local arch = package:is_arch("x86_64") and "x64" or "x86"
  191. local linkdir = (package:config("shared") and "lib" or "staticlib")
  192. for _, f in ipairs(os.files(package:installdir(arch, "mingw", linkdir, "lib*.a"))) do
  193. if not f:match("libopencv_.+") then
  194. package:add("links", path.basename(f):match("lib(.+)"))
  195. end
  196. end
  197. package:addenv("PATH", path.join(arch, "mingw", "bin"))
  198. elseif package:is_plat("android") then
  199. for _, suffix in ipairs({"*.a", "*.so"}) do
  200. local lib_name = package:config("shared") and "libs" or "staticlibs"
  201. local libdir_1 = package:installdir(path.join("sdk/native", lib_name, package:targetarch()))
  202. local libdir_2 = package:installdir(path.join("sdk/native/3rdparty/libs", package:targetarch()))
  203. local libfiles = {}
  204. table.join2(libfiles, os.files(path.join(libdir_1, suffix)))
  205. table.join2(libfiles, os.files(path.join(libdir_2, suffix)))
  206. for _, f in ipairs(libfiles) do
  207. package:add("links", path.basename(f):match("lib(.+)"))
  208. end
  209. end
  210. package:add("syslinks", "omp")
  211. else
  212. package:addenv("PATH", "bin")
  213. end
  214. end)
  215. on_test(function (package)
  216. assert(package:check_cxxsnippets({test = [[
  217. #include <iostream>
  218. void test(int argc, char** argv) {
  219. cv::CommandLineParser parser(argc, argv, "{help h||show help message}");
  220. if (parser.has("help")) {
  221. parser.printMessage();
  222. }
  223. cv::Mat image(3, 3, CV_8UC1);
  224. std::cout << CV_VERSION << std::endl;
  225. }
  226. ]]}, {configs = {languages = "c++11"},
  227. includes = package:version():ge("3.0") and "opencv2/opencv.hpp" or "opencv/cv.h"}))
  228. end)