From 3d9cb5329caddffc0b2c0f227ce2f480057a32f1 Mon Sep 17 00:00:00 2001 From: Giles Payne Date: Wed, 20 Dec 2023 21:35:10 +0900 Subject: [PATCH] Merge pull request #24136 from komakai:visionos_support Add experimental support for Apple VisionOS platform #24136 ### Pull Request Readiness Checklist 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 This is dependent on cmake support for VisionOs which is currently in progress. Creating PR now to test that there are no regressions in iOS and macOS builds --- CMakeLists.txt | 58 ++++----- cmake/OpenCVDetectPython.cmake | 4 +- cmake/OpenCVFindLibsGUI.cmake | 2 +- cmake/OpenCVGenInfoPlist.cmake | 8 ++ cmake/OpenCVGenPkgconfig.cmake | 2 +- cmake/OpenCVUtils.cmake | 2 +- modules/core/CMakeLists.txt | 2 +- modules/imgcodecs/CMakeLists.txt | 4 +- modules/imgcodecs/misc/objc/gen_dict.json | 5 + modules/objc/generator/CMakeLists.txt | 5 + modules/objc/generator/gen_objc.py | 17 ++- modules/videoio/CMakeLists.txt | 4 +- modules/videoio/src/cap_avfoundation.mm | 99 ++++++++++----- platforms/apple/build_xcframework.py | 23 ++++ platforms/ios/build_framework.py | 8 +- platforms/ios/build_visionos_framework.py | 116 ++++++++++++++++++ .../Toolchains/Toolchain-XROS_Xcode.cmake | 5 + .../Toolchain-XRSimulator_Xcode.cmake | 5 + .../Toolchains/common-ios-toolchain.cmake | 56 +++++++-- 19 files changed, 325 insertions(+), 100 deletions(-) create mode 100644 modules/imgcodecs/misc/objc/gen_dict.json create mode 100755 platforms/ios/build_visionos_framework.py create mode 100644 platforms/ios/cmake/Toolchains/Toolchain-XROS_Xcode.cmake create mode 100644 platforms/ios/cmake/Toolchains/Toolchain-XRSimulator_Xcode.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d6d22c204..300e17c9dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -238,9 +238,9 @@ OCV_OPTION(BUILD_ITT "Build Intel ITT from source" # Optional 3rd party components # =================================================== OCV_OPTION(WITH_1394 "Include IEEE1394 support" ON - VISIBLE_IF NOT ANDROID AND NOT IOS AND NOT WINRT + VISIBLE_IF NOT ANDROID AND NOT IOS AND NOT XROS AND NOT WINRT VERIFY HAVE_DC1394_2) -OCV_OPTION(WITH_AVFOUNDATION "Use AVFoundation for Video I/O (iOS/Mac)" ON +OCV_OPTION(WITH_AVFOUNDATION "Use AVFoundation for Video I/O (iOS/visionOS/Mac)" ON VISIBLE_IF APPLE VERIFY HAVE_AVFOUNDATION) OCV_OPTION(WITH_AVIF "Enable AVIF support" OFF @@ -249,15 +249,15 @@ OCV_OPTION(WITH_CAP_IOS "Enable iOS video capture" ON VISIBLE_IF IOS VERIFY HAVE_CAP_IOS) OCV_OPTION(WITH_CAROTENE "Use NVidia carotene acceleration library for ARM platform" (NOT CV_DISABLE_OPTIMIZATION) - VISIBLE_IF (ARM OR AARCH64) AND NOT IOS) + VISIBLE_IF (ARM OR AARCH64) AND NOT IOS AND NOT XROS) OCV_OPTION(WITH_CPUFEATURES "Use cpufeatures Android library" ON VISIBLE_IF ANDROID VERIFY HAVE_CPUFEATURES) OCV_OPTION(WITH_VTK "Include VTK library support (and build opencv_viz module eiher)" ON - VISIBLE_IF NOT ANDROID AND NOT IOS AND NOT WINRT AND NOT CMAKE_CROSSCOMPILING + VISIBLE_IF NOT ANDROID AND NOT IOS AND NOT XROS AND NOT WINRT AND NOT CMAKE_CROSSCOMPILING VERIFY HAVE_VTK) OCV_OPTION(WITH_CUDA "Include NVidia Cuda Runtime support" OFF - VISIBLE_IF NOT IOS AND NOT WINRT + VISIBLE_IF NOT IOS AND NOT XROS AND NOT WINRT VERIFY HAVE_CUDA) OCV_OPTION(WITH_CUFFT "Include NVidia Cuda Fast Fourier Transform (FFT) library support" WITH_CUDA VISIBLE_IF WITH_CUDA @@ -278,10 +278,10 @@ OCV_OPTION(WITH_EIGEN "Include Eigen2/Eigen3 support" (NOT CV_DISABLE_OPTIMIZATI VISIBLE_IF NOT WINRT VERIFY HAVE_EIGEN) OCV_OPTION(WITH_FFMPEG "Include FFMPEG support" (NOT ANDROID) - VISIBLE_IF NOT IOS AND NOT WINRT + VISIBLE_IF NOT IOS AND NOT XROS AND NOT WINRT VERIFY HAVE_FFMPEG) OCV_OPTION(WITH_GSTREAMER "Include Gstreamer support" ON - VISIBLE_IF NOT ANDROID AND NOT IOS AND NOT WINRT + VISIBLE_IF NOT ANDROID AND NOT IOS AND NOT XROS AND NOT WINRT VERIFY HAVE_GSTREAMER AND GSTREAMER_VERSION VERSION_GREATER "0.99") OCV_OPTION(WITH_GTK "Include GTK support" ON VISIBLE_IF UNIX AND NOT APPLE AND NOT ANDROID @@ -293,7 +293,7 @@ OCV_OPTION(WITH_WAYLAND "Include Wayland support" OFF VISIBLE_IF UNIX AND NOT APPLE AND NOT ANDROID VERIFY HAVE_WAYLAND) OCV_OPTION(WITH_IPP "Include Intel IPP support" (NOT MINGW AND NOT CV_DISABLE_OPTIMIZATION) - VISIBLE_IF (X86_64 OR X86) AND NOT WINRT AND NOT IOS + VISIBLE_IF (X86_64 OR X86) AND NOT WINRT AND NOT IOS AND NOT XROS VERIFY HAVE_IPP) OCV_OPTION(WITH_HALIDE "Include Halide support" OFF VISIBLE_IF TRUE @@ -309,10 +309,10 @@ OCV_OPTION(WITH_WEBNN "Include WebNN support" OFF VISIBLE_IF TRUE VERIFY HAVE_WEBNN) OCV_OPTION(WITH_JASPER "Include JPEG2K support (Jasper)" ON - VISIBLE_IF NOT IOS + VISIBLE_IF NOT IOS AND NOT XROS VERIFY HAVE_JASPER) OCV_OPTION(WITH_OPENJPEG "Include JPEG2K support (OpenJPEG)" ON - VISIBLE_IF NOT IOS + VISIBLE_IF NOT IOS AND NOT XROS VERIFY HAVE_OPENJPEG) OCV_OPTION(WITH_JPEG "Include JPEG support" ON VISIBLE_IF TRUE @@ -330,10 +330,10 @@ OCV_OPTION(WITH_OPENVX "Include OpenVX support" OFF VISIBLE_IF TRUE VERIFY HAVE_OPENVX) OCV_OPTION(WITH_OPENNI "Include OpenNI support" OFF - VISIBLE_IF NOT ANDROID AND NOT IOS AND NOT WINRT + VISIBLE_IF NOT ANDROID AND NOT IOS AND NOT XROS AND NOT WINRT VERIFY HAVE_OPENNI) OCV_OPTION(WITH_OPENNI2 "Include OpenNI2 support" OFF - VISIBLE_IF NOT ANDROID AND NOT IOS AND NOT WINRT + VISIBLE_IF NOT ANDROID AND NOT IOS AND NOT XROS AND NOT WINRT VERIFY HAVE_OPENNI2) OCV_OPTION(WITH_PNG "Include PNG support" ON VISIBLE_IF TRUE @@ -345,19 +345,19 @@ OCV_OPTION(WITH_GDCM "Include DICOM support" OFF VISIBLE_IF TRUE VERIFY HAVE_GDCM) OCV_OPTION(WITH_PVAPI "Include Prosilica GigE support" OFF - VISIBLE_IF NOT ANDROID AND NOT IOS AND NOT WINRT + VISIBLE_IF NOT ANDROID AND NOT IOS AND NOT XROS AND NOT WINRT VERIFY HAVE_PVAPI) OCV_OPTION(WITH_ARAVIS "Include Aravis GigE support" OFF - VISIBLE_IF NOT ANDROID AND NOT IOS AND NOT WINRT AND NOT WIN32 + VISIBLE_IF NOT ANDROID AND NOT IOS AND NOT XROS AND NOT WINRT AND NOT WIN32 VERIFY HAVE_ARAVIS_API) OCV_OPTION(WITH_QT "Build with Qt Backend support" OFF - VISIBLE_IF NOT ANDROID AND NOT IOS AND NOT WINRT + VISIBLE_IF NOT ANDROID AND NOT IOS AND NOT XROS AND NOT WINRT VERIFY HAVE_QT) OCV_OPTION(WITH_WIN32UI "Build with Win32 UI Backend support" ON VISIBLE_IF WIN32 AND NOT WINRT VERIFY HAVE_WIN32UI) OCV_OPTION(WITH_TBB "Include Intel TBB support" OFF - VISIBLE_IF NOT IOS AND NOT WINRT + VISIBLE_IF NOT IOS AND NOT XROS AND NOT WINRT VERIFY HAVE_TBB) OCV_OPTION(WITH_HPX "Include Ste||ar Group HPX support" OFF VISIBLE_IF TRUE @@ -369,7 +369,7 @@ OCV_OPTION(WITH_PTHREADS_PF "Use pthreads-based parallel_for" ON VISIBLE_IF NOT WIN32 OR MINGW VERIFY HAVE_PTHREADS_PF) OCV_OPTION(WITH_TIFF "Include TIFF support" ON - VISIBLE_IF NOT IOS + VISIBLE_IF NOT IOS AND NOT XROS VERIFY HAVE_TIFF) OCV_OPTION(WITH_V4L "Include Video 4 Linux support" ON VISIBLE_IF UNIX AND NOT ANDROID AND NOT APPLE @@ -396,16 +396,16 @@ OCV_OPTION(WITH_CLP "Include Clp support (EPL)" OFF VISIBLE_IF TRUE VERIFY HAVE_CLP) OCV_OPTION(WITH_OPENCL "Include OpenCL Runtime support" (NOT ANDROID AND NOT CV_DISABLE_OPTIMIZATION) - VISIBLE_IF NOT IOS AND NOT WINRT + VISIBLE_IF NOT IOS AND NOT XROS AND NOT WINRT VERIFY HAVE_OPENCL) OCV_OPTION(WITH_OPENCL_SVM "Include OpenCL Shared Virtual Memory support" OFF VISIBLE_IF TRUE VERIFY HAVE_OPENCL_SVM) # experimental OCV_OPTION(WITH_OPENCLAMDFFT "Include AMD OpenCL FFT library support" ON - VISIBLE_IF NOT ANDROID AND NOT IOS AND NOT WINRT + VISIBLE_IF NOT ANDROID AND NOT IOS AND NOT XROS AND NOT WINRT VERIFY HAVE_CLAMDFFT) OCV_OPTION(WITH_OPENCLAMDBLAS "Include AMD OpenCL BLAS library support" ON - VISIBLE_IF NOT ANDROID AND NOT IOS AND NOT WINRT + VISIBLE_IF NOT ANDROID AND NOT IOS AND NOT XROS AND NOT WINRT VERIFY HAVE_CLAMDBLAS) OCV_OPTION(WITH_DIRECTX "Include DirectX support" ON VISIBLE_IF WIN32 AND NOT WINRT @@ -429,13 +429,13 @@ OCV_OPTION(WITH_MFX "Include Intel Media SDK support" OFF VISIBLE_IF (UNIX AND NOT ANDROID) OR (WIN32 AND NOT WINRT AND NOT MINGW) VERIFY HAVE_MFX) OCV_OPTION(WITH_GDAL "Include GDAL Support" OFF - VISIBLE_IF NOT ANDROID AND NOT IOS AND NOT WINRT + VISIBLE_IF NOT ANDROID AND NOT IOS AND NOT XROS AND NOT WINRT VERIFY HAVE_GDAL) OCV_OPTION(WITH_GPHOTO2 "Include gPhoto2 library support" OFF - VISIBLE_IF UNIX AND NOT ANDROID AND NOT IOS + VISIBLE_IF UNIX AND NOT ANDROID AND NOT IOS AND NOT XROS VERIFY HAVE_GPHOTO2) OCV_OPTION(WITH_LAPACK "Include Lapack library support" (NOT CV_DISABLE_OPTIMIZATION) - VISIBLE_IF NOT ANDROID AND NOT IOS + VISIBLE_IF NOT ANDROID AND NOT IOS AND NOT XROS VERIFY HAVE_LAPACK) OCV_OPTION(WITH_ITT "Include Intel ITT support" ON VISIBLE_IF NOT APPLE_FRAMEWORK @@ -516,7 +516,7 @@ OCV_OPTION(INSTALL_TESTS "Install accuracy and performance test binar # OpenCV build options # =================================================== OCV_OPTION(ENABLE_CCACHE "Use ccache" (UNIX AND (CMAKE_GENERATOR MATCHES "Makefile" OR CMAKE_GENERATOR MATCHES "Ninja" OR CMAKE_GENERATOR MATCHES "Xcode")) ) -OCV_OPTION(ENABLE_PRECOMPILED_HEADERS "Use precompiled headers" MSVC IF (MSVC OR (NOT IOS AND NOT CMAKE_CROSSCOMPILING) ) ) +OCV_OPTION(ENABLE_PRECOMPILED_HEADERS "Use precompiled headers" MSVC IF (MSVC OR (NOT IOS AND NOT XROS AND NOT CMAKE_CROSSCOMPILING) ) ) OCV_OPTION(ENABLE_DELAYLOAD "Enable delayed loading of OpenCV DLLs" OFF VISIBLE_IF MSVC AND BUILD_SHARED_LIBS) OCV_OPTION(ENABLE_SOLUTION_FOLDERS "Solution folder in Visual Studio or in other IDEs" (MSVC_IDE OR CMAKE_GENERATOR MATCHES Xcode) ) OCV_OPTION(ENABLE_PROFILING "Enable profiling in the GCC compiler (Add flags: -g -pg)" OFF IF CV_GCC ) @@ -526,8 +526,8 @@ OCV_OPTION(ENABLE_OMIT_FRAME_POINTER "Enable -fomit-frame-pointer for GCC" OCV_OPTION(ENABLE_POWERPC "Enable PowerPC for GCC" ON IF (CV_GCC AND CMAKE_SYSTEM_PROCESSOR MATCHES powerpc.*) ) OCV_OPTION(ENABLE_FAST_MATH "Enable compiler options for fast math optimizations on FP computations (not recommended)" OFF) if(NOT IOS AND (NOT ANDROID OR OPENCV_ANDROID_USE_LEGACY_FLAGS) AND CMAKE_CROSSCOMPILING) # Use CPU_BASELINE instead -OCV_OPTION(ENABLE_NEON "Enable NEON instructions" (NEON OR ANDROID_ARM_NEON OR AARCH64) IF (CV_GCC OR CV_CLANG) AND (ARM OR AARCH64 OR IOS) ) -OCV_OPTION(ENABLE_VFPV3 "Enable VFPv3-D32 instructions" OFF IF (CV_GCC OR CV_CLANG) AND (ARM OR AARCH64 OR IOS) ) +OCV_OPTION(ENABLE_NEON "Enable NEON instructions" (NEON OR ANDROID_ARM_NEON OR AARCH64) IF (CV_GCC OR CV_CLANG) AND (ARM OR AARCH64 OR IOS OR XROS) ) +OCV_OPTION(ENABLE_VFPV3 "Enable VFPv3-D32 instructions" OFF IF (CV_GCC OR CV_CLANG) AND (ARM OR AARCH64 OR IOS OR XROS) ) endif() OCV_OPTION(ENABLE_NOISY_WARNINGS "Show all warnings even if they are too noisy" OFF ) OCV_OPTION(OPENCV_WARNINGS_ARE_ERRORS "Treat warnings as errors" OFF ) @@ -649,7 +649,7 @@ endif() ocv_cmake_hook(POST_CMAKE_BUILD_OPTIONS) # --- Python Support --- -if(NOT IOS) +if(NOT IOS AND NOT XROS) include(cmake/OpenCVDetectPython.cmake) endif() @@ -734,7 +734,7 @@ include(cmake/OpenCVModule.cmake) # Detect endianness of build platform # ---------------------------------------------------------------------------- -if(IOS) +if(IOS OR XROS) # test_big_endian needs try_compile, which doesn't work for iOS # http://public.kitware.com/Bug/view.php?id=12288 set(WORDS_BIGENDIAN 0) @@ -1007,7 +1007,7 @@ include(cmake/OpenCVGenAndroidMK.cmake) # Generate OpenCVConfig.cmake and OpenCVConfig-version.cmake for cmake projects include(cmake/OpenCVGenConfig.cmake) -# Generate Info.plist for the IOS framework +# Generate Info.plist for the iOS/visionOS framework if(APPLE_FRAMEWORK) include(cmake/OpenCVGenInfoPlist.cmake) endif() diff --git a/cmake/OpenCVDetectPython.cmake b/cmake/OpenCVDetectPython.cmake index d4098ce8e6..b18bebb674 100644 --- a/cmake/OpenCVDetectPython.cmake +++ b/cmake/OpenCVDetectPython.cmake @@ -175,7 +175,7 @@ if(NOT ${found}) endif() endif() - if(NOT ANDROID AND NOT IOS) + if(NOT ANDROID AND NOT IOS AND NOT XROS) if(CMAKE_HOST_UNIX) execute_process(COMMAND ${_executable} -c "from sysconfig import *; print(get_path('purelib'))" RESULT_VARIABLE _cvpy_process @@ -240,7 +240,7 @@ if(NOT ${found}) OUTPUT_STRIP_TRAILING_WHITESPACE) endif() endif() - endif(NOT ANDROID AND NOT IOS) + endif(NOT ANDROID AND NOT IOS AND NOT XROS) endif() # Export return values diff --git a/cmake/OpenCVFindLibsGUI.cmake b/cmake/OpenCVFindLibsGUI.cmake index 79758fa813..31c19b1da7 100644 --- a/cmake/OpenCVFindLibsGUI.cmake +++ b/cmake/OpenCVFindLibsGUI.cmake @@ -77,7 +77,7 @@ endif(WITH_OPENGL) # --- Cocoa --- if(APPLE) - if(NOT IOS AND CV_CLANG) + if(NOT IOS AND NOT XROS AND CV_CLANG) set(HAVE_COCOA YES) endif() endif() diff --git a/cmake/OpenCVGenInfoPlist.cmake b/cmake/OpenCVGenInfoPlist.cmake index 105087907f..f1a6926d07 100644 --- a/cmake/OpenCVGenInfoPlist.cmake +++ b/cmake/OpenCVGenInfoPlist.cmake @@ -13,6 +13,14 @@ if(IOS) configure_file("${OpenCV_SOURCE_DIR}/platforms/ios/Info.plist.in" "${CMAKE_BINARY_DIR}/ios/Info.plist") endif() +elseif(XROS) + if(APPLE_FRAMEWORK AND DYNAMIC_PLIST) + configure_file("${OpenCV_SOURCE_DIR}/platforms/ios/Info.Dynamic.plist.in" + "${CMAKE_BINARY_DIR}/visionos/Info.plist") + else() + configure_file("${OpenCV_SOURCE_DIR}/platforms/ios/Info.plist.in" + "${CMAKE_BINARY_DIR}/visionos/Info.plist") + endif() elseif(APPLE) configure_file("${OpenCV_SOURCE_DIR}/platforms/osx/Info.plist.in" "${CMAKE_BINARY_DIR}/osx/Info.plist") diff --git a/cmake/OpenCVGenPkgconfig.cmake b/cmake/OpenCVGenPkgconfig.cmake index 8d36b74f09..4fc80f5e4b 100644 --- a/cmake/OpenCVGenPkgconfig.cmake +++ b/cmake/OpenCVGenPkgconfig.cmake @@ -1,4 +1,4 @@ -if(MSVC OR IOS) +if(MSVC OR IOS OR XROS) return() endif() diff --git a/cmake/OpenCVUtils.cmake b/cmake/OpenCVUtils.cmake index a90eb5a5ab..3f82550065 100644 --- a/cmake/OpenCVUtils.cmake +++ b/cmake/OpenCVUtils.cmake @@ -1564,7 +1564,7 @@ function(ocv_add_library target) set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG 1) - if(IOS AND NOT MAC_CATALYST) + if((IOS OR XROS) AND NOT MAC_CATALYST) set(OPENCV_APPLE_INFO_PLIST "${CMAKE_BINARY_DIR}/ios/Info.plist") else() set(OPENCV_APPLE_INFO_PLIST "${CMAKE_BINARY_DIR}/osx/Info.plist") diff --git a/modules/core/CMakeLists.txt b/modules/core/CMakeLists.txt index 4d5ebf3483..bf3a65c7c3 100644 --- a/modules/core/CMakeLists.txt +++ b/modules/core/CMakeLists.txt @@ -20,7 +20,7 @@ ocv_add_dispatched_file_force_all(test_intrin512 TEST AVX512_SKX) set(PARALLEL_ENABLE_PLUGINS_DEFAULT ON) -if(EMSCRIPTEN OR IOS OR WINRT) +if(EMSCRIPTEN OR IOS OR XROS OR WINRT) set(PARALLEL_ENABLE_PLUGINS_DEFAULT OFF) endif() # parallel backends configuration diff --git a/modules/imgcodecs/CMakeLists.txt b/modules/imgcodecs/CMakeLists.txt index 8183837c43..1468d4d73b 100644 --- a/modules/imgcodecs/CMakeLists.txt +++ b/modules/imgcodecs/CMakeLists.txt @@ -137,11 +137,11 @@ if(APPLE OR APPLE_FRAMEWORK) list(APPEND imgcodecs_srcs ${CMAKE_CURRENT_LIST_DIR}/src/apple_conversions.h) list(APPEND imgcodecs_srcs ${CMAKE_CURRENT_LIST_DIR}/src/apple_conversions.mm) endif() -if(IOS) +if(IOS OR XROS) list(APPEND imgcodecs_srcs ${CMAKE_CURRENT_LIST_DIR}/src/ios_conversions.mm) list(APPEND IMGCODECS_LIBRARIES "-framework UIKit") endif() -if(APPLE AND (NOT IOS)) +if(APPLE AND (NOT IOS) AND (NOT XROS)) list(APPEND imgcodecs_srcs ${CMAKE_CURRENT_LIST_DIR}/src/macosx_conversions.mm) list(APPEND IMGCODECS_LIBRARIES "-framework AppKit") endif() diff --git a/modules/imgcodecs/misc/objc/gen_dict.json b/modules/imgcodecs/misc/objc/gen_dict.json new file mode 100644 index 0000000000..cfcd5889e7 --- /dev/null +++ b/modules/imgcodecs/misc/objc/gen_dict.json @@ -0,0 +1,5 @@ +{ + "SourceMap" : { + "visionos" : "ios" + } +} diff --git a/modules/objc/generator/CMakeLists.txt b/modules/objc/generator/CMakeLists.txt index b3cbbd3f5f..bd8f8325b3 100644 --- a/modules/objc/generator/CMakeLists.txt +++ b/modules/objc/generator/CMakeLists.txt @@ -9,6 +9,8 @@ file(REMOVE_RECURSE "${OPENCV_OBJC_BINDINGS_DIR}/osx") file(REMOVE "${OPENCV_DEPHELPER}/gen_opencv_objc_source_osx") # force re-run after CMake file(REMOVE_RECURSE "${OPENCV_OBJC_BINDINGS_DIR}/ios") file(REMOVE "${OPENCV_DEPHELPER}/gen_opencv_objc_source_ios") # force re-run after CMake +file(REMOVE_RECURSE "${OPENCV_OBJC_BINDINGS_DIR}/visionos") +file(REMOVE "${OPENCV_DEPHELPER}/gen_opencv_objc_source_visionos") # force re-run after CMake # This file is included from a subdirectory set(OBJC_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/..") @@ -67,6 +69,8 @@ string(REPLACE "opencv_" "" MODULES "${OPENCV_OBJC_MODULES}") if(NOT DEFINED OPENCV_OBJC_TARGET AND APPLE_FRAMEWORK) if(IOS) set(OPENCV_OBJC_TARGET "ios") + elseif(XROS) + set(OPENCV_OBJC_TARGET "visionos") else() set(OPENCV_OBJC_TARGET "osx") endif() @@ -117,6 +121,7 @@ if(OPENCV_OBJC_TARGET) else() ocv_add_objc_generated_target(osx) ocv_add_objc_generated_target(ios) + ocv_add_objc_generated_target(visionos) endif() add_custom_target(gen_opencv_objc_source diff --git a/modules/objc/generator/gen_objc.py b/modules/objc/generator/gen_objc.py index 3105e7eefd..58b7dd555c 100755 --- a/modules/objc/generator/gen_objc.py +++ b/modules/objc/generator/gen_objc.py @@ -1600,7 +1600,7 @@ if __name__ == "__main__": arg_parser = argparse.ArgumentParser(description='OpenCV Objective-C Wrapper Generator') arg_parser.add_argument('-p', '--parser', required=True, help='OpenCV header parser') arg_parser.add_argument('-c', '--config', required=True, help='OpenCV modules config') - arg_parser.add_argument('-t', '--target', required=True, help='Target (either ios or osx)') + arg_parser.add_argument('-t', '--target', required=True, help='Target (either ios or osx or visionos)') arg_parser.add_argument('-f', '--framework', required=True, help='Framework name') args=arg_parser.parse_args() @@ -1671,6 +1671,7 @@ if __name__ == "__main__": logging.info("\nCommon headers (%d):\n%s", len(common_headers), pformat(common_headers)) gendict_fname = os.path.join(misc_location, 'gen_dict.json') + module_source_map = {} if os.path.exists(gendict_fname): with open(gendict_fname) as f: gen_type_dict = json.load(f) @@ -1687,6 +1688,7 @@ if __name__ == "__main__": header_fix.update(gen_type_dict.get("header_fix", {})) enum_fix.update(gen_type_dict.get("enum_fix", {})) const_fix.update(gen_type_dict.get("const_fix", {})) + module_source_map = gen_type_dict.get("SourceMap", {}) namespaces_dict.update(gen_type_dict.get("namespaces_dict", {})) module_imports += gen_type_dict.get("module_imports", []) @@ -1695,15 +1697,10 @@ if __name__ == "__main__": if os.path.exists(objc_files_dir): copied_files += copy_objc_files(objc_files_dir, objc_base_path, module, True) - if args.target == 'ios': - ios_files_dir = os.path.join(misc_location, 'ios') - if os.path.exists(ios_files_dir): - copied_files += copy_objc_files(ios_files_dir, objc_base_path, module, True) - - if args.target == 'osx': - osx_files_dir = os.path.join(misc_location, 'macosx') - if os.path.exists(osx_files_dir): - copied_files += copy_objc_files(osx_files_dir, objc_base_path, module, True) + target_path = 'macosx' if args.target == 'osx' else module_source_map.get(args.target, args.target) + target_files_dir = os.path.join(misc_location, target_path) + if os.path.exists(target_files_dir): + copied_files += copy_objc_files(target_files_dir, objc_base_path, module, True) objc_test_files_dir = os.path.join(misc_location, 'test') if os.path.exists(objc_test_files_dir): diff --git a/modules/videoio/CMakeLists.txt b/modules/videoio/CMakeLists.txt index eee706d306..f800babdcd 100644 --- a/modules/videoio/CMakeLists.txt +++ b/modules/videoio/CMakeLists.txt @@ -1,5 +1,5 @@ set(VIDEOIO_ENABLE_PLUGINS_DEFAULT ON) -if(EMSCRIPTEN OR IOS OR WINRT) +if(EMSCRIPTEN OR IOS OR XROS OR WINRT) set(VIDEOIO_ENABLE_PLUGINS_DEFAULT OFF) endif() @@ -197,7 +197,7 @@ if(TARGET ocv.3rdparty.aravis) endif() if(TARGET ocv.3rdparty.avfoundation) - if(IOS) + if(IOS OR XROS) list(APPEND videoio_srcs ${CMAKE_CURRENT_LIST_DIR}/src/cap_avfoundation.mm) else() list(APPEND videoio_srcs ${CMAKE_CURRENT_LIST_DIR}/src/cap_avfoundation_mac.mm) diff --git a/modules/videoio/src/cap_avfoundation.mm b/modules/videoio/src/cap_avfoundation.mm index 12fa42f5b5..d0f2b41c37 100644 --- a/modules/videoio/src/cap_avfoundation.mm +++ b/modules/videoio/src/cap_avfoundation.mm @@ -61,6 +61,8 @@ #define DISABLE_AUTO_RESTART 999 +#if !TARGET_OS_VISION + @interface CaptureDelegate : NSObject { int newFrame; @@ -125,6 +127,7 @@ class CvCaptureCAM : public CvCapture { int disableAutoRestart; }; +#endif /***************************************************************************** * @@ -160,6 +163,7 @@ private: uint32_t mMode; int mFormat; + void handleTracks(NSArray* tracks, const char* filename); bool setupReadingAt(CMTime position); IplImage* retrieveFramePixelBuffer(); int getPreferredOrientationDegrees() const; @@ -217,6 +221,8 @@ cv::Ptr cv::create_AVFoundation_capture_file(const std::strin } +#if !TARGET_OS_VISION + cv::Ptr cv::create_AVFoundation_capture_cam(int index) { CvCaptureCAM* retval = new CvCaptureCAM(index); @@ -226,6 +232,8 @@ cv::Ptr cv::create_AVFoundation_capture_cam(int index) return 0; } +#endif + cv::Ptr cv::create_AVFoundation_writer(const std::string& filename, int fourcc, double fps, const cv::Size &frameSize, const cv::VideoWriterParameters& params) @@ -245,6 +253,8 @@ cv::Ptr cv::create_AVFoundation_writer(const std::string& file * *****************************************************************************/ +#if !TARGET_OS_VISION + CvCaptureCAM::CvCaptureCAM(int cameraNum) { mCaptureSession = nil; mCaptureDeviceInput = nil; @@ -773,6 +783,7 @@ fromConnection:(AVCaptureConnection *)connection{ @end +#endif /***************************************************************************** * @@ -811,24 +822,26 @@ CvCaptureFile::CvCaptureFile(const char* filename) { return; } +// Available since iOS 15 +#if TARGET_OS_VISION || (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 150000) + if (@available(iOS 15, visionOS 1, *)) { + [mAsset loadTracksWithMediaType:AVMediaTypeVideo completionHandler:^(NSArray* tracks, NSError* err) { + if (err != nil) { + handleTracks(tracks, filename); + } + [localpool drain]; + }]; + return; + } else { +#if !TARGET_OS_VISION + NSArray *tracks = [mAsset tracksWithMediaType:AVMediaTypeVideo]; + handleTracks(tracks, filename); +#endif + } +#else NSArray *tracks = [mAsset tracksWithMediaType:AVMediaTypeVideo]; - if ([tracks count] == 0) { - fprintf(stderr, "OpenCV: Couldn't read video stream from file \"%s\"\n", filename); - [localpool drain]; - started = 0; - return; - } - - mAssetTrack = [tracks[0] retain]; - - if ( ! setupReadingAt(kCMTimeZero) ) { - fprintf(stderr, "OpenCV: Couldn't read movie file \"%s\"\n", filename); - [localpool drain]; - started = 0; - return; - } - - started = 1; + handleTracks(tracks, filename); +#endif [localpool drain]; } @@ -850,6 +863,24 @@ CvCaptureFile::~CvCaptureFile() { [localpool drain]; } +void CvCaptureFile::handleTracks(NSArray* tracks, const char* filename) { + if ([tracks count] == 0) { + fprintf(stderr, "OpenCV: Couldn't read video stream from file \"%s\"\n", filename); + started = 0; + return; + } + + mAssetTrack = [tracks[0] retain]; + + if ( ! setupReadingAt(kCMTimeZero) ) { + fprintf(stderr, "OpenCV: Couldn't read movie file \"%s\"\n", filename); + started = 0; + return; + } + + started = 1; +} + bool CvCaptureFile::setupReadingAt(CMTime position) { if (mAssetReader) { if (mAssetReader.status == AVAssetReaderStatusReading) { @@ -1269,25 +1300,25 @@ CvVideoWriter_AVFoundation::CvVideoWriter_AVFoundation(const char* filename, int //exception; } - // Three codec supported AVVideoCodecH264 AVVideoCodecJPEG AVVideoCodecTypeHEVC + // Three codec supported AVVideoCodecTypeH264 AVVideoCodecTypeJPEG AVVideoCodecTypeHEVC // On iPhone 3G H264 is not supported. if (fourcc == CV_FOURCC('J','P','E','G') || fourcc == CV_FOURCC('j','p','e','g') || fourcc == CV_FOURCC('M','J','P','G') || fourcc == CV_FOURCC('m','j','p','g')){ - codec = [AVVideoCodecJPEG copy]; // Use JPEG codec if specified, otherwise H264 + codec = [AVVideoCodecTypeJPEG copy]; // Use JPEG codec if specified, otherwise H264 }else if(fourcc == CV_FOURCC('H','2','6','4') || fourcc == CV_FOURCC('a','v','c','1')){ - codec = [AVVideoCodecH264 copy]; + codec = [AVVideoCodecTypeH264 copy]; // Available since iOS 11 -#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000 +#if TARGET_OS_VISION || (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000) }else if(fourcc == CV_FOURCC('H','2','6','5') || fourcc == CV_FOURCC('h','v','c','1') || fourcc == CV_FOURCC('H','E','V','C') || fourcc == CV_FOURCC('h','e','v','c')){ - if (@available(iOS 11, *)) { + if (@available(iOS 11, visionOS 1, *)) { codec = [AVVideoCodecTypeHEVC copy]; } else { - codec = [AVVideoCodecH264 copy]; + codec = [AVVideoCodecTypeH264 copy]; } #endif }else{ - codec = [AVVideoCodecH264 copy]; // default canonical H264. + codec = [AVVideoCodecTypeH264 copy]; // default canonical H264. } //NSLog(@"Path: %@", path); @@ -1349,17 +1380,17 @@ CvVideoWriter_AVFoundation::~CvVideoWriter_AVFoundation() { NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init]; [mMovieWriterInput markAsFinished]; - [mMovieWriter finishWriting]; - [mMovieWriter release]; - [mMovieWriterInput release]; - [mMovieWriterAdaptor release]; - [path release]; - [codec release]; - [fileType release]; - cvReleaseImage(&argbimage); - - [localpool drain]; + [mMovieWriter finishWritingWithCompletionHandler:^() { + [mMovieWriter release]; + [mMovieWriterInput release]; + [mMovieWriterAdaptor release]; + [path release]; + [codec release]; + [fileType release]; + cvReleaseImage(&argbimage); + [localpool drain]; + }]; } bool CvVideoWriter_AVFoundation::writeFrame(const IplImage* iplimage) { diff --git a/platforms/apple/build_xcframework.py b/platforms/apple/build_xcframework.py index 49878435d0..3916c135f9 100755 --- a/platforms/apple/build_xcframework.py +++ b/platforms/apple/build_xcframework.py @@ -31,6 +31,8 @@ if __name__ == "__main__": parser.add_argument('--framework_name', default='opencv2', help='Name of OpenCV xcframework (default: opencv2, will change to OpenCV in future version)') parser.add_argument('--iphoneos_archs', default=None, help='select iPhoneOS target ARCHS. Default is "armv7,arm64"') parser.add_argument('--iphonesimulator_archs', default=None, help='select iPhoneSimulator target ARCHS. Default is "x86_64,arm64"') + parser.add_argument('--visionos_archs', default=None, help='select visionOS target ARCHS. Default is "arm64"') + parser.add_argument('--visionsimulator_archs', default=None, help='select visionSimulator target ARCHS. Default is "arm64"') parser.add_argument('--macos_archs', default=None, help='Select MacOS ARCHS. Default is "x86_64,arm64"') parser.add_argument('--catalyst_archs', default=None, help='Select Catalyst ARCHS. Default is "x86_64,arm64"') parser.add_argument('--build_only_specified_archs', default=False, action='store_true', help='if enabled, only directly specified archs are built and defaults are ignored') @@ -52,6 +54,13 @@ if __name__ == "__main__": iphonesimulator_archs = "x86_64,arm64" print('Using iPhoneSimulator ARCHS={}'.format(iphonesimulator_archs)) + # Parse architectures from args + visionos_archs = args.visionos_archs + print('Using visionOS ARCHS={}'.format(visionos_archs)) + + visionsimulator_archs = args.visionsimulator_archs + print('Using visionSimulator ARCHS={}'.format(visionsimulator_archs)) + macos_archs = args.macos_archs if not macos_archs and not args.build_only_specified_archs: # Supply defaults @@ -70,6 +79,7 @@ if __name__ == "__main__": # Phase 1: build .frameworks for each platform osx_script_path = os.path.abspath(os.path.abspath(os.path.dirname(__file__))+'/../osx/build_framework.py') ios_script_path = os.path.abspath(os.path.abspath(os.path.dirname(__file__))+'/../ios/build_framework.py') + visionos_script_path = os.path.abspath(os.path.abspath(os.path.dirname(__file__))+'/../ios/build_visionos_framework.py') build_folders = [] @@ -91,6 +101,19 @@ if __name__ == "__main__": command = ["python3", ios_script_path, build_folder, "--iphonesimulator_archs", iphonesimulator_archs, "--framework_name", args.framework_name, "--build_only_specified_archs"] + unknown_args print_header("Building iPhoneSimulator frameworks") execute(command, cwd=os.getcwd()) + if visionos_archs: + build_folder = get_or_create_build_folder(args.out, "visionos") + build_folders.append(build_folder) + command = ["python3", visionos_script_path, build_folder, "--visionos_archs", visionos_archs, "--framework_name", args.framework_name, "--build_only_specified_archs"] + unknown_args + print_header("Building visionOS frameworks") + print(command) + execute(command, cwd=os.getcwd()) + if visionsimulator_archs: + build_folder = get_or_create_build_folder(args.out, "visionsimulator") + build_folders.append(build_folder) + command = ["python3", visionos_script_path, build_folder, "--visionsimulator_archs", visionsimulator_archs, "--framework_name", args.framework_name, "--build_only_specified_archs"] + unknown_args + print_header("Building visionSimulator frameworks") + execute(command, cwd=os.getcwd()) if macos_archs: build_folder = get_or_create_build_folder(args.out, "macos") build_folders.append(build_folder) diff --git a/platforms/ios/build_framework.py b/platforms/ios/build_framework.py index 77878280f7..b876812720 100755 --- a/platforms/ios/build_framework.py +++ b/platforms/ios/build_framework.py @@ -254,9 +254,9 @@ class Builder: toolchain = self.getToolchain(arch, target) cmakecmd = self.getCMakeArgs(arch, target) + \ (["-DCMAKE_TOOLCHAIN_FILE=%s" % toolchain] if toolchain is not None else []) - if target.lower().startswith("iphoneos"): + if target.lower().startswith("iphoneos") or target.lower().startswith("xros"): cmakecmd.append("-DCPU_BASELINE=DETECT") - if target.lower().startswith("iphonesimulator"): + if target.lower().startswith("iphonesimulator") or target.lower().startswith("xrsimulator"): build_arch = check_output(["uname", "-m"]).decode('utf-8').rstrip() if build_arch != arch: print("build_arch (%s) != arch (%s)" % (build_arch, arch)) @@ -341,7 +341,7 @@ class Builder: def makeDynamicLib(self, builddir): target = builddir[(builddir.rfind("build-") + 6):] target_platform = target[(target.rfind("-") + 1):] - is_device = target_platform == "iphoneos" or target_platform == "catalyst" + is_device = target_platform == "iphoneos" or target_platform == "visionos" or target_platform == "catalyst" framework_dir = os.path.join(builddir, "install", "lib", self.framework_name + ".framework") if not os.path.exists(framework_dir): os.makedirs(framework_dir) @@ -379,7 +379,7 @@ class Builder: "-framework", "CoreImage", "-framework", "CoreMedia", "-framework", "QuartzCore", "-framework", "Accelerate", "-framework", "OpenCL", ] - elif target_platform == "iphoneos" or target_platform == "iphonesimulator": + elif target_platform == "iphoneos" or target_platform == "iphonesimulator" or target_platform == "xros" or target_platform == "xrsimulator": framework_options = [ "-iframework", "%s/System/iOSSupport/System/Library/Frameworks" % sdk_dir, "-framework", "AVFoundation", "-framework", "CoreGraphics", diff --git a/platforms/ios/build_visionos_framework.py b/platforms/ios/build_visionos_framework.py new file mode 100755 index 0000000000..96364c7b8b --- /dev/null +++ b/platforms/ios/build_visionos_framework.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python +""" +The script builds OpenCV.framework for visionOS. +""" + +from __future__ import print_function +import os, os.path, sys, argparse, traceback, multiprocessing + +# import common code +# sys.path.insert(0, os.path.abspath(os.path.abspath(os.path.dirname(__file__))+'/../ios')) +from build_framework import Builder +sys.path.insert(0, os.path.abspath(os.path.abspath(os.path.dirname(__file__))+'/../apple')) +from cv_build_utils import print_error, get_cmake_version + +XROS_DEPLOYMENT_TARGET='1.0' # default, can be changed via command line options or environment variable + +class visionOSBuilder(Builder): + + def checkCMakeVersion(self): + assert get_cmake_version() >= (3, 17), "CMake 3.17 or later is required. Current version is {}".format(get_cmake_version()) + + def getObjcTarget(self, target): + return 'visionos' + + def getToolchain(self, arch, target): + toolchain = os.path.join(self.opencv, "platforms", "ios", "cmake", "Toolchains", "Toolchain-%s_Xcode.cmake" % target) + return toolchain + + def getCMakeArgs(self, arch, target): + args = Builder.getCMakeArgs(self, arch, target) + args = args + [ + '-DVISIONOS_ARCH=%s' % arch + ] + return args + + def getBuildCommand(self, arch, target): + buildcmd = [ + "xcodebuild", + "XROS_DEPLOYMENT_TARGET=" + os.environ['XROS_DEPLOYMENT_TARGET'], + "ARCHS=%s" % arch, + "-sdk", target.lower(), + "-configuration", "Debug" if self.debug else "Release", + "-parallelizeTargets", + "-jobs", str(multiprocessing.cpu_count()) + ] + + return buildcmd + + def getInfoPlist(self, builddirs): + return os.path.join(builddirs[0], "visionos", "Info.plist") + + +if __name__ == "__main__": + folder = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "../..")) + parser = argparse.ArgumentParser(description='The script builds OpenCV.framework for visionOS.') + # TODO: When we can make breaking changes, we should make the out argument explicit and required like in build_xcframework.py. + parser.add_argument('out', metavar='OUTDIR', help='folder to put built framework') + parser.add_argument('--opencv', metavar='DIR', default=folder, help='folder with opencv repository (default is "../.." relative to script location)') + parser.add_argument('--contrib', metavar='DIR', default=None, help='folder with opencv_contrib repository (default is "None" - build only main framework)') + parser.add_argument('--without', metavar='MODULE', default=[], action='append', help='OpenCV modules to exclude from the framework. To exclude multiple, specify this flag again, e.g. "--without video --without objc"') + parser.add_argument('--disable', metavar='FEATURE', default=[], action='append', help='OpenCV features to disable (add WITH_*=OFF). To disable multiple, specify this flag again, e.g. "--disable tbb --disable openmp"') + parser.add_argument('--dynamic', default=False, action='store_true', help='build dynamic framework (default is "False" - builds static framework)') + parser.add_argument('--enable_nonfree', default=False, dest='enablenonfree', action='store_true', help='enable non-free modules (disabled by default)') + parser.add_argument('--visionos_deployment_target', default=os.environ.get('XROS_DEPLOYMENT_TARGET', XROS_DEPLOYMENT_TARGET), help='specify XROS_DEPLOYMENT_TARGET') + parser.add_argument('--visionos_archs', default=None, help='select visionOS target ARCHS. Default is none') + parser.add_argument('--visionsimulator_archs', default=None, help='select visionSimulator target ARCHS. Default is none') + parser.add_argument('--debug', action='store_true', help='Build "Debug" binaries (CMAKE_BUILD_TYPE=Debug)') + parser.add_argument('--debug_info', action='store_true', help='Build with debug information (useful for Release mode: BUILD_WITH_DEBUG_INFO=ON)') + parser.add_argument('--framework_name', default='opencv2', dest='framework_name', help='Name of OpenCV framework (default: opencv2, will change to OpenCV in future version)') + parser.add_argument('--legacy_build', default=False, dest='legacy_build', action='store_true', help='Build legacy framework (default: False, equivalent to "--framework_name=opencv2 --without=objc")') + parser.add_argument('--run_tests', default=False, dest='run_tests', action='store_true', help='Run tests') + parser.add_argument('--build_docs', default=False, dest='build_docs', action='store_true', help='Build docs') + parser.add_argument('--disable-swift', default=False, dest='swiftdisabled', action='store_true', help='Disable building of Swift extensions') + + args, unknown_args = parser.parse_known_args() + if unknown_args: + print("The following args are not recognized and will not be used: %s" % unknown_args) + + os.environ['XROS_DEPLOYMENT_TARGET'] = args.visionos_deployment_target + print('Using XROS_DEPLOYMENT_TARGET=' + os.environ['XROS_DEPLOYMENT_TARGET']) + + visionos_archs = None + if args.visionos_archs: + visionos_archs = args.visionos_archs.split(',') + print('Using visionOS ARCHS=' + str(visionos_archs)) + + visionsimulator_archs = None + if args.visionsimulator_archs: + visionsimulator_archs = args.visionsimulator_archs.split(',') + print('Using visionOS ARCHS=' + str(visionsimulator_archs)) + + # Prevent the build from happening if the same architecture is specified for multiple platforms. + # When `lipo` is run to stitch the frameworks together into a fat framework, it'll fail, so it's + # better to stop here while we're ahead. + if visionos_archs and visionsimulator_archs: + duplicate_archs = set(visionos_archs).intersection(visionsimulator_archs) + if duplicate_archs: + print_error("Cannot have the same architecture for multiple platforms in a fat framework! Consider using build_xcframework.py in the apple platform folder instead. Duplicate archs are %s" % duplicate_archs) + exit(1) + + if args.legacy_build: + args.framework_name = "opencv2" + if not "objc" in args.without: + args.without.append("objc") + + targets = [] + if not visionos_archs and not visionsimulator_archs: + print_error("--visionos_archs and --visionsimulator_archs are undefined; nothing will be built.") + sys.exit(1) + if visionos_archs: + targets.append((visionos_archs, "XROS")) + if visionsimulator_archs: + targets.append((visionsimulator_archs, "XRSimulator")), + + b = visionOSBuilder(args.opencv, args.contrib, args.dynamic, True, args.without, args.disable, args.enablenonfree, targets, args.debug, args.debug_info, args.framework_name, args.run_tests, args.build_docs, args.swiftdisabled) + b.build(args.out) diff --git a/platforms/ios/cmake/Toolchains/Toolchain-XROS_Xcode.cmake b/platforms/ios/cmake/Toolchains/Toolchain-XROS_Xcode.cmake new file mode 100644 index 0000000000..0f22bd73a9 --- /dev/null +++ b/platforms/ios/cmake/Toolchains/Toolchain-XROS_Xcode.cmake @@ -0,0 +1,5 @@ +message(STATUS "Setting up visionOS toolchain for VISIONOS_ARCH='${VISIONOS_ARCH}'") +set(VISIONOS TRUE) +set(XROS 1) +include(${CMAKE_CURRENT_LIST_DIR}/common-ios-toolchain.cmake) +message(STATUS "visionOS toolchain loaded") diff --git a/platforms/ios/cmake/Toolchains/Toolchain-XRSimulator_Xcode.cmake b/platforms/ios/cmake/Toolchains/Toolchain-XRSimulator_Xcode.cmake new file mode 100644 index 0000000000..aee12f4c5d --- /dev/null +++ b/platforms/ios/cmake/Toolchains/Toolchain-XRSimulator_Xcode.cmake @@ -0,0 +1,5 @@ +message(STATUS "Setting up visionSimulator toolchain for VISIONOS_ARCH='${VISIONOS_ARCH}'") +set(VISIONSIMULATOR TRUE) +set(XROS 1) +include(${CMAKE_CURRENT_LIST_DIR}/common-ios-toolchain.cmake) +message(STATUS "visionSimulator toolchain loaded") diff --git a/platforms/ios/cmake/Toolchains/common-ios-toolchain.cmake b/platforms/ios/cmake/Toolchains/common-ios-toolchain.cmake index 9918c468b4..7a14529c2d 100644 --- a/platforms/ios/cmake/Toolchains/common-ios-toolchain.cmake +++ b/platforms/ios/cmake/Toolchains/common-ios-toolchain.cmake @@ -61,26 +61,45 @@ else() endmacro() endif() # IN_TRY_COMPILE -if(NOT DEFINED IOS_ARCH) +if((IPHONEOS OR IPHONESIMULATOR) AND NOT DEFINED IOS_ARCH) message(FATAL_ERROR "iOS toolchain requires ARCH option for proper configuration of compiler flags") endif() -if(IOS_ARCH MATCHES "^arm64") +if((VISIONOS OR VISIONSIMULATOR) AND NOT DEFINED VISIONOS_ARCH) + message(FATAL_ERROR "visionOS toolchain requires ARCH option for proper configuration of compiler flags") +endif() +if((IOS_ARCH MATCHES "^arm64") OR (VISIONOS_ARCH MATCHES "^arm64")) set(AARCH64 1) elseif(IOS_ARCH MATCHES "^armv") set(ARM 1) -elseif(IOS_ARCH MATCHES "^x86_64") +elseif((IOS_ARCH MATCHES "^x86_64") OR (VISIONOS_ARCH MATCHES "^x86_64")) set(X86_64 1) elseif(IOS_ARCH MATCHES "^i386") set(X86 1) else() - message(FATAL_ERROR "iOS toolchain doesn't recognize ARCH='${IOS_ARCH}' value") + if(IPHONEOS OR IPHONESIMULATOR) + message(FATAL_ERROR "invalid value of IOS_ARCH='${IOS_ARCH}'") + elseif(VISIONOS OR VISIONSIMULATOR) + message(FATAL_ERROR "invalid value of VISIONOS_ARCH='${VISIONOS_ARCH}'") + endif() endif() if(NOT DEFINED CMAKE_OSX_SYSROOT) if(IPHONEOS) set(CMAKE_OSX_SYSROOT "iphoneos") + set(SYSTEM "iOS") + set(ARCH "${IOS_ARCH}") elseif(IPHONESIMULATOR) set(CMAKE_OSX_SYSROOT "iphonesimulator") + set(SYSTEM "iOS") + set(ARCH "${IOS_ARCH}") + elseif(VISIONOS) + set(CMAKE_OSX_SYSROOT "xros") + set(SYSTEM "visionOS") + set(ARCH "${VISIONOS_ARCH}") + elseif(VISIONSIMULATOR) + set(CMAKE_OSX_SYSROOT "xrsimulator") + set(SYSTEM "visionOS") + set(ARCH "${VISIONOS_ARCH}") elseif(MAC_CATALYST) # Use MacOS SDK for Catalyst builds set(CMAKE_OSX_SYSROOT "macosx") @@ -90,14 +109,25 @@ set(CMAKE_MACOSX_BUNDLE YES) set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO") if(APPLE_FRAMEWORK AND NOT BUILD_SHARED_LIBS) - set(CMAKE_OSX_ARCHITECTURES "${IOS_ARCH}" CACHE INTERNAL "Build architecture for iOS" FORCE) + set(CMAKE_OSX_ARCHITECTURES "${ARCH}" CACHE INTERNAL "Build architecture for iOS/visionOS" FORCE) endif() -if(NOT DEFINED IPHONEOS_DEPLOYMENT_TARGET AND NOT MAC_CATALYST) +if((IPHONEOS OR IPHONESIMULATOR) AND NOT DEFINED IPHONEOS_DEPLOYMENT_TARGET) if(NOT DEFINED ENV{IPHONEOS_DEPLOYMENT_TARGET}) message(FATAL_ERROR "IPHONEOS_DEPLOYMENT_TARGET is not specified") endif() set(IPHONEOS_DEPLOYMENT_TARGET "$ENV{IPHONEOS_DEPLOYMENT_TARGET}") + set(DEPLOYMENT_TARGET "${IPHONEOS_DEPLOYMENT_TARGET}") + set(DEPLOYMENT_TARGET_CMDLINE "IPHONEOS_DEPLOYMENT_TARGET=${IPHONEOS_DEPLOYMENT_TARGET}") +endif() + +if((VISIONOS OR VISIONSIMULATOR) AND NOT DEFINED XROS_DEPLOYMENT_TARGET) + if(NOT DEFINED ENV{XROS_DEPLOYMENT_TARGET}) + message(FATAL_ERROR "XROS_DEPLOYMENT_TARGET is not specified") + endif() + set(XROS_DEPLOYMENT_TARGET "$ENV{XROS_DEPLOYMENT_TARGET}") + set(DEPLOYMENT_TARGET "${XROS_DEPLOYMENT_TARGET}") + set(DEPLOYMENT_TARGET_CMDLINE "XROS_DEPLOYMENT_TARGET=${XROS_DEPLOYMENT_TARGET}") endif() if(NOT __IN_TRY_COMPILE) @@ -124,9 +154,9 @@ if(NOT __IN_TRY_COMPILE) message(FATAL_ERROR "Can't prepare xcodebuild_wrapper") endif() if(APPLE_FRAMEWORK AND BUILD_SHARED_LIBS) - set(XCODEBUILD_EXTRA_ARGS "${XCODEBUILD_EXTRA_ARGS} IPHONEOS_DEPLOYMENT_TARGET=${IPHONEOS_DEPLOYMENT_TARGET} CODE_SIGN_IDENTITY='' CODE_SIGNING_REQUIRED=NO -sdk ${CMAKE_OSX_SYSROOT}") + set(XCODEBUILD_EXTRA_ARGS "${XCODEBUILD_EXTRA_ARGS} ${DEPLOYMENT_TARGET_CMDLINE} CODE_SIGN_IDENTITY='' CODE_SIGNING_REQUIRED=NO -sdk ${CMAKE_OSX_SYSROOT}") else() - set(XCODEBUILD_EXTRA_ARGS "${XCODEBUILD_EXTRA_ARGS} IPHONEOS_DEPLOYMENT_TARGET=${IPHONEOS_DEPLOYMENT_TARGET} CODE_SIGN_IDENTITY='' CODE_SIGNING_REQUIRED=NO ARCHS=${IOS_ARCH} -sdk ${CMAKE_OSX_SYSROOT}") + set(XCODEBUILD_EXTRA_ARGS "${XCODEBUILD_EXTRA_ARGS} ${DEPLOYMENT_TARGET_CMDLINE} CODE_SIGN_IDENTITY='' CODE_SIGNING_REQUIRED=NO ARCHS=${ARCH} -sdk ${CMAKE_OSX_SYSROOT}") endif() configure_file("${CMAKE_CURRENT_LIST_DIR}/xcodebuild_wrapper.in" "${_xcodebuild_wrapper_tmp}" @ONLY) file(COPY "${_xcodebuild_wrapper_tmp}" DESTINATION ${CMAKE_BINARY_DIR} FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) @@ -137,16 +167,16 @@ if(NOT __IN_TRY_COMPILE) endif() # Standard settings -set(CMAKE_SYSTEM_NAME iOS) +set(CMAKE_SYSTEM_NAME "${SYSTEM}") # Apple Framework settings if(APPLE_FRAMEWORK AND BUILD_SHARED_LIBS) - set(CMAKE_SYSTEM_VERSION "${IPHONEOS_DEPLOYMENT_TARGET}") + set(CMAKE_SYSTEM_VERSION "${DEPLOYMENT_TARGET}") set(CMAKE_C_SIZEOF_DATA_PTR 4) set(CMAKE_CXX_SIZEOF_DATA_PTR 4) else() - set(CMAKE_SYSTEM_VERSION "${IPHONEOS_DEPLOYMENT_TARGET}") - set(CMAKE_SYSTEM_PROCESSOR "${IOS_ARCH}") + set(CMAKE_SYSTEM_VERSION "${DEPLOYMENT_TARGET}") + set(CMAKE_SYSTEM_PROCESSOR "${ARCH}") if(AARCH64 OR X86_64) set(CMAKE_C_SIZEOF_DATA_PTR 8) @@ -190,4 +220,4 @@ if(NOT CMAKE_FIND_ROOT_PATH_MODE_PROGRAM) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) endif() -toolchain_save_config(IOS_ARCH IPHONEOS_DEPLOYMENT_TARGET) +toolchain_save_config(IOS_ARCH VISIONOS_ARCH ARCH DEPLOYMENT_TARGET)