Blame view

3rdparty/opencv-4.5.4/platforms/apple/build_xcframework.py 7.08 KB
f4334277   Hu Chunming   提交3rdparty
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
  #!/usr/bin/env python3
  """
  This script builds OpenCV into an xcframework compatible with the platforms
  of your choice. Just run it and grab a snack; you'll be waiting a while.
  """
  
  import sys, os, argparse, pathlib, traceback, contextlib, shutil
  from cv_build_utils import execute, print_error, print_header, get_xcode_version, get_cmake_version
  
  if __name__ == "__main__":
  
      # Check for dependencies
      assert sys.version_info >= (3, 6), "Python 3.6 or later is required! Current version is {}".format(sys.version_info)
      # Need CMake 3.18.5/3.19 or later for a Silicon-related fix to building for the iOS Simulator.
      # See https://gitlab.kitware.com/cmake/cmake/-/issues/21425 for context.
      assert get_cmake_version() >= (3, 18, 5), "CMake 3.18.5 or later is required. Current version is {}".format(get_cmake_version())
      # Need Xcode 12.2 for Apple Silicon support
      assert get_xcode_version() >= (12, 2), \
          "Xcode 12.2 command line tools or later are required! Current version is {}. ".format(get_xcode_version()) + \
          "Run xcode-select to switch if you have multiple Xcode installs."
  
      # Parse arguments
      description = """
          This script builds OpenCV into an xcframework supporting the Apple platforms of your choice.
          """
      epilog = """
          Any arguments that are not recognized by this script are passed through to the ios/osx build_framework.py scripts.
          """
      parser = argparse.ArgumentParser(description=description, epilog=epilog)
      parser.add_argument('-o', '--out', metavar='OUTDIR', help='<Required> The directory where the xcframework will be created', required=True)
      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('--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')
  
      args, unknown_args = parser.parse_known_args()
      if unknown_args:
          print("The following args are not recognized by this script and will be passed through to the ios/osx build_framework.py scripts: {}".format(unknown_args))
  
      # Parse architectures from args
      iphoneos_archs = args.iphoneos_archs
      if not iphoneos_archs and not args.build_only_specified_archs:
          # Supply defaults
          iphoneos_archs = "armv7,arm64"
      print('Using iPhoneOS ARCHS={}'.format(iphoneos_archs))
  
      iphonesimulator_archs = args.iphonesimulator_archs
      if not iphonesimulator_archs and not args.build_only_specified_archs:
          # Supply defaults
          iphonesimulator_archs = "x86_64,arm64"
      print('Using iPhoneSimulator ARCHS={}'.format(iphonesimulator_archs))
  
      macos_archs = args.macos_archs
      if not macos_archs and not args.build_only_specified_archs:
          # Supply defaults
          macos_archs = "x86_64,arm64"
      print('Using MacOS ARCHS={}'.format(macos_archs))
  
      catalyst_archs = args.macos_archs
      if not catalyst_archs and not args.build_only_specified_archs:
          # Supply defaults
          catalyst_archs = "x86_64,arm64"
      print('Using Catalyst ARCHS={}'.format(catalyst_archs))
  
      # Build phase
  
      try:
          # 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')
  
          build_folders = []
  
          def get_or_create_build_folder(base_dir, platform):
              build_folder = "{}/{}".format(base_dir, platform).replace(" ", "\\ ")  # Escape spaces in output path
              pathlib.Path(build_folder).mkdir(parents=True, exist_ok=True)
              return build_folder
  
          if iphoneos_archs:
              build_folder = get_or_create_build_folder(args.out, "iphoneos")
              build_folders.append(build_folder)
              command = ["python3", ios_script_path, build_folder, "--iphoneos_archs", iphoneos_archs, "--framework_name", args.framework_name, "--build_only_specified_archs"] + unknown_args
              print_header("Building iPhoneOS frameworks")
              print(command)
              execute(command, cwd=os.getcwd())
          if iphonesimulator_archs:
              build_folder = get_or_create_build_folder(args.out, "iphonesimulator")
              build_folders.append(build_folder)
              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 macos_archs:
              build_folder = get_or_create_build_folder(args.out, "macos")
              build_folders.append(build_folder)
              command = ["python3", osx_script_path, build_folder, "--macos_archs", macos_archs, "--framework_name", args.framework_name, "--build_only_specified_archs"] + unknown_args
              print_header("Building MacOS frameworks")
              execute(command, cwd=os.getcwd())
          if catalyst_archs:
              build_folder = get_or_create_build_folder(args.out, "catalyst")
              build_folders.append(build_folder)
              command = ["python3", osx_script_path, build_folder, "--catalyst_archs", catalyst_archs, "--framework_name", args.framework_name, "--build_only_specified_archs"] + unknown_args
              print_header("Building Catalyst frameworks")
              execute(command, cwd=os.getcwd())
  
          # Phase 2: put all the built .frameworks together into a .xcframework
  
          xcframework_path = "{}/{}.xcframework".format(args.out, args.framework_name)
          print_header("Building {}".format(xcframework_path))
  
          # Remove the xcframework if it exists, otherwise the existing
          # file will cause the xcodebuild command to fail.
          with contextlib.suppress(FileNotFoundError):
              shutil.rmtree(xcframework_path)
              print("Removed existing xcframework at {}".format(xcframework_path))
  
          xcframework_build_command = [
              "xcodebuild",
              "-create-xcframework",
              "-output",
              xcframework_path,
          ]
          for folder in build_folders:
              xcframework_build_command += ["-framework", "{}/{}.framework".format(folder, args.framework_name)]
          execute(xcframework_build_command, cwd=os.getcwd())
  
          print("")
          print_header("Finished building {}".format(xcframework_path))
      except Exception as e:
          print_error(e)
          traceback.print_exc(file=sys.stderr)
          sys.exit(1)