xref: /aosp_15_r20/external/cronet/build/config/ios/rules.gni (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1# Copyright 2015 The Chromium Authors
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import("//build/apple/apple_info_plist.gni")
6import("//build/config/apple/symbols.gni")
7import("//build/config/compiler/compiler.gni")
8import("//build/config/ios/ios_sdk.gni")
9import("//build/config/zip.gni")
10import("//build/toolchain/rbe.gni")
11import("//build/toolchain/siso.gni")
12import("//build/toolchain/toolchain.gni")
13import("//build_overrides/build.gni")
14
15# Constants corresponding to the bundle type identifiers use application,
16# application extension, XCTest and XCUITest targets respectively.
17_ios_xcode_app_bundle_id = "com.apple.product-type.application"
18_ios_xcode_appex_bundle_id = "com.apple.product-type.app-extension"
19_ios_xcode_xctest_bundle_id = "com.apple.product-type.bundle.unit-test"
20_ios_xcode_xcuitest_bundle_id = "com.apple.product-type.bundle.ui-testing"
21
22# Wrapper around create_bundle taking care of code signature settings.
23#
24# Arguments
25#
26#   product_type
27#       string, product type for the generated Xcode project.
28#
29#   bundle_gen_dir
30#       (optional) directory where the bundle is generated; must be below
31#       root_out_dir and defaults to root_out_dir if omitted.
32#
33#   bundle_deps
34#       (optional) list of additional dependencies.
35#
36#   bundle_deps_filter
37#       (optional) list of dependencies to filter (for more information
38#       see "gn help bundle_deps_filter").
39#
40#   bundle_extension
41#       string, extension of the bundle, used to generate bundle name.
42#
43#   bundle_binary_target
44#       (optional) string, label of the target generating the bundle main
45#       binary. This target and bundle_binary_path are mutually exclusive.
46#
47#   bundle_binary_output
48#       (optional) string, base name of the binary generated by the
49#       bundle_binary_target target, defaults to the target name.
50#
51#   bundle_binary_path
52#       (optional) string, path to the bundle main binary. This target and
53#       bundle_binary_target are mutually exclusive.
54#
55#   output_name:
56#       (optional) string, name of the generated application, if omitted,
57#       defaults to the target_name.
58#
59#   extra_system_frameworks
60#       (optional) list of system framework to copy to the bundle.
61#
62#   enable_code_signing
63#       (optional) boolean, control whether code signing is enabled or not,
64#       default to ios_enable_code_signing if not defined.
65#
66#   entitlements_path:
67#       (optional) path to the template to use to generate the application
68#       entitlements by performing variable substitutions, defaults to
69#       //build/config/ios/entitlements.plist.
70#
71#   entitlements_target:
72#       (optional) label of the target generating the application
73#       entitlements (must generate a single file as output); cannot be
74#       defined if entitlements_path is set.
75#
76#   has_public_headers:
77#       (optional) boolean, defaults to false; only meaningful if the bundle
78#       is a framework bundle; if true, then the frameworks includes public
79#       headers
80#
81#   disable_entitlements
82#       (optional, defaults to false) boolean, control whether entitlements willi
83#       be embedded in the application during signature. If false and no
84#       entitlements are provided, default empty entitlements will be used.
85#
86#   disable_embedded_mobileprovision
87#       (optional, default to false) boolean, control whether mobile provisions
88#       will be embedded in the bundle. If true, the existing
89#       embedded.mobileprovision will be deleted.
90#
91#   xcode_extra_attributes
92#       (optional) scope, extra attributes for Xcode projects.
93#
94#   xcode_test_application_name:
95#       (optional) string, name of the test application for Xcode unit or ui
96#       test target.
97#
98#   xcode_product_bundle_id:
99#       (optional) string, the bundle ID that will be added in the XCode
100#       attributes to enable some features when debugging (e.g. MetricKit).
101#
102#   primary_info_plist:
103#       (optional) path to Info.plist to merge with the $partial_info_plist
104#       generated by the compilation of the asset catalog.
105#
106#   partial_info_plist:
107#       (optional) path to the partial Info.plist generated by the asset
108#       catalog compiler; if defined $primary_info_plist must also be defined.
109#
110#   transparent
111#       (optional) boolean, whether the bundle is "transparent"; defaults to
112#       "false" if ommitted; a bundle is considered "transparent" if it does
113#       not package the "bundle_data" deps but forward them to all targets
114#       the depend on it (unless the "bundle_data" target sets "product_type"
115#       to the same value as the "create_signed_bundle" target).
116#
117template("create_signed_bundle") {
118  assert(defined(invoker.product_type),
119         "product_type must be defined for $target_name")
120  assert(defined(invoker.bundle_extension),
121         "bundle_extension must be defined for $target_name")
122  assert(defined(invoker.bundle_binary_target) !=
123             defined(invoker.bundle_binary_path),
124         "Only one of bundle_binary_target or bundle_binary_path may be " +
125             "specified for $target_name")
126  assert(!defined(invoker.partial_info_plist) ||
127             defined(invoker.primary_info_plist),
128         "primary_info_plist must be defined when partial_info_plist is " +
129             "defined for $target_name")
130
131  if (defined(invoker.xcode_test_application_name)) {
132    assert(
133        invoker.product_type == _ios_xcode_xctest_bundle_id ||
134            invoker.product_type == _ios_xcode_xcuitest_bundle_id,
135        "xcode_test_application_name can be only defined for Xcode unit or ui test target.")
136  }
137
138  _target_name = target_name
139  _output_name = target_name
140  if (defined(invoker.output_name)) {
141    _output_name = invoker.output_name
142  }
143
144  if (defined(invoker.bundle_binary_path)) {
145    _bundle_binary_path = invoker.bundle_binary_path
146  } else {
147    _bundle_binary_target = invoker.bundle_binary_target
148    _bundle_binary_output = get_label_info(_bundle_binary_target, "name")
149    if (defined(invoker.bundle_binary_output)) {
150      _bundle_binary_output = invoker.bundle_binary_output
151    }
152    _bundle_binary_path =
153        get_label_info(_bundle_binary_target, "target_out_dir") +
154        "/$_bundle_binary_output"
155  }
156
157  _bundle_gen_dir = root_out_dir
158  if (defined(invoker.bundle_gen_dir)) {
159    _bundle_gen_dir = invoker.bundle_gen_dir
160  }
161
162  _bundle_extension = invoker.bundle_extension
163
164  _enable_embedded_mobileprovision = true
165  if (defined(invoker.disable_embedded_mobileprovision)) {
166    _enable_embedded_mobileprovision = !invoker.disable_embedded_mobileprovision
167  }
168
169  if (target_environment == "catalyst") {
170    _enable_embedded_mobileprovision = false
171  }
172
173  _enable_entitlements = true
174  if (defined(invoker.disable_entitlements)) {
175    _enable_entitlements = !invoker.disable_entitlements
176  }
177
178  if (_enable_entitlements) {
179    if (!defined(invoker.entitlements_target)) {
180      _entitlements_path = "//build/config/ios/entitlements.plist"
181      if (defined(invoker.entitlements_path)) {
182        _entitlements_path = invoker.entitlements_path
183      }
184    } else {
185      assert(!defined(invoker.entitlements_path),
186             "Cannot define both entitlements_path and entitlements_target " +
187                 "for $target_name")
188
189      _entitlements_target_outputs =
190          get_target_outputs(invoker.entitlements_target)
191      _entitlements_path = _entitlements_target_outputs[0]
192    }
193  }
194
195  _enable_code_signing = ios_enable_code_signing
196  if (defined(invoker.enable_code_signing)) {
197    _enable_code_signing = invoker.enable_code_signing
198  }
199
200  create_bundle(_target_name) {
201    forward_variables_from(invoker,
202                           [
203                             "bundle_deps_filter",
204                             "data_deps",
205                             "deps",
206                             "partial_info_plist",
207                             "product_type",
208                             "public_configs",
209                             "public_deps",
210                             "testonly",
211                             "transparent",
212                             "visibility",
213                             "xcode_test_application_name",
214                           ])
215
216    bundle_root_dir = "$_bundle_gen_dir/$_output_name$_bundle_extension"
217    if (target_environment == "simulator" || target_environment == "device") {
218      bundle_contents_dir = bundle_root_dir
219      bundle_resources_dir = bundle_contents_dir
220      bundle_executable_dir = bundle_contents_dir
221    } else if (target_environment == "catalyst") {
222      if (_bundle_extension != ".framework") {
223        bundle_contents_dir = "$bundle_root_dir/Contents"
224        bundle_resources_dir = "$bundle_contents_dir/Resources"
225        bundle_executable_dir = "$bundle_contents_dir/MacOS"
226      } else {
227        bundle_contents_dir = "$bundle_root_dir/Versions/A"
228        bundle_resources_dir = "$bundle_contents_dir/Resources"
229        bundle_executable_dir = bundle_contents_dir
230      }
231    }
232
233    if (!defined(public_deps)) {
234      public_deps = []
235    }
236
237    _bundle_identifier = ""
238    if (defined(invoker.xcode_product_bundle_id)) {
239      _bundle_identifier = invoker.xcode_product_bundle_id
240      assert(_bundle_identifier == string_replace(_bundle_identifier, "_", "-"),
241             "$target_name: bundle_identifier does not respect rfc1034: " +
242                 _bundle_identifier)
243    }
244
245    xcode_extra_attributes = {
246      IPHONEOS_DEPLOYMENT_TARGET = ios_deployment_target
247      PRODUCT_BUNDLE_IDENTIFIER = _bundle_identifier
248      CODE_SIGNING_REQUIRED = "NO"
249      CODE_SIGNING_ALLOWED = "NO"
250      CODE_SIGN_IDENTITY = ""
251      DONT_GENERATE_INFOPLIST_FILE = "YES"
252
253      # If invoker has defined extra attributes, they override the defaults.
254      if (defined(invoker.xcode_extra_attributes)) {
255        forward_variables_from(invoker.xcode_extra_attributes, "*")
256      }
257    }
258
259    if (defined(invoker.bundle_binary_target)) {
260      public_deps += [ invoker.bundle_binary_target ]
261    }
262
263    if (defined(invoker.bundle_deps)) {
264      if (!defined(deps)) {
265        deps = []
266      }
267      deps += invoker.bundle_deps
268    }
269    if (!defined(deps)) {
270      deps = []
271    }
272
273    post_processing_script = "//build/config/ios/codesign.py"
274    post_processing_sources = [ _bundle_binary_path ]
275    if (_enable_entitlements) {
276      if (defined(invoker.entitlements_target)) {
277        deps += [ invoker.entitlements_target ]
278      }
279      post_processing_sources += [ _entitlements_path ]
280    }
281    post_processing_outputs = [ "$bundle_executable_dir/$_output_name" ]
282    if (_enable_code_signing) {
283      post_processing_outputs +=
284          [ "$bundle_contents_dir/_CodeSignature/CodeResources" ]
285    }
286    if (ios_code_signing_identity != "" && target_environment == "device" &&
287        _enable_embedded_mobileprovision) {
288      post_processing_outputs +=
289          [ "$bundle_contents_dir/embedded.mobileprovision" ]
290    }
291    if (_bundle_extension == ".framework") {
292      if (target_environment == "catalyst") {
293        post_processing_outputs += [
294          "$bundle_root_dir/Versions/Current",
295          "$bundle_root_dir/$_output_name",
296        ]
297
298        if (defined(invoker.has_public_headers) && invoker.has_public_headers) {
299          post_processing_outputs += [
300            "$bundle_root_dir/Headers",
301            "$bundle_root_dir/Modules",
302          ]
303        }
304      } else {
305        not_needed(invoker, [ "has_public_headers" ])
306      }
307    }
308
309    if (defined(invoker.extra_system_frameworks)) {
310      foreach(_framework, invoker.extra_system_frameworks) {
311        post_processing_outputs += [ "$bundle_contents_dir/Frameworks/" +
312                                     get_path_info(_framework, "file") ]
313      }
314    }
315
316    post_processing_args = [
317      "code-sign-bundle",
318      "-t=" + ios_sdk_name,
319      "-i=" + ios_code_signing_identity,
320      "-b=" + rebase_path(_bundle_binary_path, root_build_dir),
321    ]
322    foreach(mobileprovision, ios_mobileprovision_files) {
323      post_processing_args +=
324          [ "-m=" + rebase_path(mobileprovision, root_build_dir) ]
325    }
326    post_processing_sources += ios_mobileprovision_files
327    if (_enable_entitlements) {
328      post_processing_args +=
329          [ "-e=" + rebase_path(_entitlements_path, root_build_dir) ]
330    }
331    if (!_enable_embedded_mobileprovision) {
332      post_processing_args += [ "--disable-embedded-mobileprovision" ]
333    }
334    post_processing_args += [ rebase_path(bundle_root_dir, root_build_dir) ]
335    if (!_enable_code_signing) {
336      post_processing_args += [ "--disable-code-signature" ]
337    }
338    if (defined(invoker.extra_system_frameworks)) {
339      # All framework in extra_system_frameworks are expected to be system
340      # framework and the path to be already system absolute so do not use
341      # rebase_path here unless using RBE and system Xcode (as in that
342      # case the system framework are found via a symlink in root_build_dir).
343      foreach(_framework, invoker.extra_system_frameworks) {
344        if (use_system_xcode && (use_remoteexec || use_siso)) {
345          _framework_path = rebase_path(_framework, root_build_dir)
346        } else {
347          _framework_path = _framework
348        }
349        post_processing_args += [ "-F=$_framework_path" ]
350      }
351    }
352    if (defined(invoker.partial_info_plist)) {
353      _partial_info_plists = [
354        invoker.primary_info_plist,
355        invoker.partial_info_plist,
356      ]
357
358      _plist_compiler_path = "//build/apple/plist_util.py"
359
360      post_processing_sources += _partial_info_plists
361      post_processing_sources += [ _plist_compiler_path ]
362      if (target_environment != "catalyst" ||
363          _bundle_extension != ".framework") {
364        post_processing_outputs += [ "$bundle_contents_dir/Info.plist" ]
365      } else {
366        post_processing_outputs += [ "$bundle_resources_dir/Info.plist" ]
367      }
368
369      post_processing_args +=
370          [ "-P=" + rebase_path(_plist_compiler_path, root_build_dir) ]
371      foreach(_partial_info_plist, _partial_info_plists) {
372        post_processing_args +=
373            [ "-p=" + rebase_path(_partial_info_plist, root_build_dir) ]
374      }
375    }
376  }
377}
378
379# Generates Info.plist files for iOS apps and frameworks.
380#
381# Arguments
382#
383#     info_plist:
384#         (optional) string, path to the Info.plist file that will be used for
385#         the bundle.
386#
387#     info_plist_target:
388#         (optional) string, if the info_plist is generated from an action,
389#         rather than a regular source file, specify the target name in lieu
390#         of info_plist. The two arguments are mutually exclusive.
391#
392#     executable_name:
393#         string, name of the generated target used for the product
394#         and executable name as specified in the output Info.plist.
395#
396#     extra_substitutions:
397#         (optional) string array, 'key=value' pairs for extra fields which are
398#         specified in a source Info.plist template.
399template("ios_info_plist") {
400  assert(defined(invoker.info_plist) != defined(invoker.info_plist_target),
401         "Only one of info_plist or info_plist_target may be specified in " +
402             target_name)
403
404  if (defined(invoker.info_plist)) {
405    _info_plist = invoker.info_plist
406  } else {
407    _info_plist_target_output = get_target_outputs(invoker.info_plist_target)
408    _info_plist = _info_plist_target_output[0]
409  }
410
411  apple_info_plist(target_name) {
412    format = "binary1"
413    extra_substitutions = [
414      "IOS_BUNDLE_ID_PREFIX=$ios_app_bundle_id_prefix",
415      "IOS_PLATFORM_BUILD=$ios_platform_build",
416      "IOS_PLATFORM_NAME=$ios_sdk_name",
417      "IOS_PLATFORM_VERSION=$ios_sdk_version",
418      "IOS_SDK_BUILD=$ios_sdk_build",
419      "IOS_SDK_NAME=$ios_sdk_name$ios_sdk_version",
420      "IOS_SUPPORTED_PLATFORM=$ios_sdk_platform",
421      "BUILD_MACHINE_OS_BUILD=$machine_os_build",
422      "IOS_DEPLOYMENT_TARGET=$ios_deployment_target",
423      "XCODE_BUILD=$xcode_build",
424      "XCODE_VERSION=$xcode_version",
425    ]
426    if (defined(invoker.extra_substitutions)) {
427      extra_substitutions += invoker.extra_substitutions
428    }
429    plist_templates = [
430      "//build/config/ios/BuildInfo.plist",
431      _info_plist,
432    ]
433    if (defined(invoker.info_plist_target)) {
434      deps = [ invoker.info_plist_target ]
435    }
436    forward_variables_from(invoker,
437                           [
438                             "executable_name",
439                             "output_name",
440                             "visibility",
441                             "testonly",
442                           ])
443  }
444}
445
446# Template to build an application bundle for iOS.
447#
448# This should be used instead of "executable" built-in target type on iOS.
449# As the template forward the generation of the application executable to
450# an "executable" target, all arguments supported by "executable" targets
451# are also supported by this template.
452#
453# Arguments
454#
455#   output_name:
456#       (optional) string, name of the generated application, if omitted,
457#       defaults to the target_name.
458#
459#   extra_substitutions:
460#       (optional) list of string in "key=value" format, each value will
461#       be used as an additional variable substitution rule when generating
462#       the application Info.plist
463#
464#   info_plist:
465#       (optional) string, path to the Info.plist file that will be used for
466#       the bundle.
467#
468#   info_plist_target:
469#       (optional) string, if the info_plist is generated from an action,
470#       rather than a regular source file, specify the target name in lieu
471#       of info_plist. The two arguments are mutually exclusive.
472#
473#   entitlements_path:
474#       (optional) path to the template to use to generate the application
475#       entitlements by performing variable substitutions, defaults to
476#       //build/config/ios/entitlements.plist.
477#
478#   entitlements_target:
479#       (optional) label of the target generating the application
480#       entitlements (must generate a single file as output); cannot be
481#       defined if entitlements_path is set.
482#
483#   product_type
484#       (optional) string, product type for the generated Xcode project,
485#       default to "com.apple.product-type.application". Should only be
486#       overriden when building application extension.
487#
488#   enable_code_signing
489#       (optional) boolean, control whether code signing is enabled or not,
490#       default to ios_enable_code_signing if not defined.
491#
492#   variants
493#       (optional) list of scopes, each scope needs to define the attributes
494#       "name" and "bundle_deps"; if defined and non-empty, then one bundle
495#       named $target_out_dir/$variant/$output_name will be created for each
496#       variant with the same binary but the correct bundle_deps, the bundle
497#       at $target_out_dir/$output_name will be a copy of the first variant.
498#
499#   bundle_identifier:
500#       (optional) string, value of CFBundleIdentifier in the application
501#       Info.plist, defaults to "$ios_app_bundle_id_prefix.$output_name"
502#       if omitted. Will be used to set BUNDLE_IDENTIFIER when generating
503#       the application Info.plist
504#
505#   orderfile_path:
506#       (optional) string, path to an orderfile passed to the linker in order
507#       to improve application launch performance.
508#
509#   intents_target:
510#       (optional) string, label of the target defining the intents for the
511#       application. If defined, it must corresponds to a `swift_source_set`
512#       target configured with `generate_intents = true`.
513#
514# For more information, see "gn help executable".
515template("ios_app_bundle") {
516  _output_name = target_name
517  _target_name = target_name
518  if (defined(invoker.output_name)) {
519    _output_name = invoker.output_name
520  }
521
522  assert(
523      !defined(invoker.bundle_extension),
524      "bundle_extension must not be set for ios_app_bundle template for $target_name")
525
526  # Whether the intents metadata should be extracted (note that they are
527  # disabled when building for the catalyst environment)
528  _extract_intents_metadata = false
529  if (defined(invoker.intents_target)) {
530    _extract_intents_metadata =
531        invoker.intents_target != "" && target_environment != "catalyst"
532  }
533
534  if (defined(invoker.bundle_identifier)) {
535    _bundle_identifier = invoker.bundle_identifier
536    assert(_bundle_identifier == string_replace(_bundle_identifier, "_", "-"),
537           "$target_name: bundle_identifier does not respect rfc1034: " +
538               _bundle_identifier)
539  } else {
540    # Bundle identifier should respect rfc1034, so replace "_" with "-".
541    _bundle_identifier =
542        "$ios_app_bundle_id_prefix." + string_replace(_output_name, "_", "-")
543  }
544
545  if (defined(invoker.variants) && invoker.variants != []) {
546    _variants = []
547
548    foreach(_variant, invoker.variants) {
549      assert(defined(_variant.name) && _variant.name != "",
550             "name must be defined for all $target_name variants")
551
552      assert(defined(_variant.bundle_deps),
553             "bundle_deps must be defined for all $target_name variants")
554
555      _variants += [
556        {
557          name = _variant.name
558          bundle_deps = _variant.bundle_deps
559          target_name = "${_target_name}_variants_${_variant.name}"
560          bundle_gen_dir = "$root_out_dir/variants/${_variant.name}"
561        },
562      ]
563    }
564  } else {
565    # If no variants are passed to the template, use a fake variant with
566    # no name to avoid duplicating code. As no variant can have an empty
567    # name except this fake variant, it is possible to know if a variant
568    # is fake or not.
569    _variants = [
570      {
571        name = ""
572        bundle_deps = []
573        target_name = _target_name
574        bundle_gen_dir = root_out_dir
575      },
576    ]
577  }
578
579  _default_variant = _variants[0]
580
581  _executable_target = _target_name + "_executable"
582  _generate_entitlements_target = _target_name + "_gen_entitlements"
583  _generate_entitlements_output =
584      get_label_info(":$_generate_entitlements_target", "target_out_dir") +
585      "/$_output_name.xcent"
586
587  _product_type = _ios_xcode_app_bundle_id
588  if (defined(invoker.product_type)) {
589    _product_type = invoker.product_type
590  }
591
592  if (_product_type == _ios_xcode_app_bundle_id) {
593    _bundle_extension = ".app"
594  } else if (_product_type == _ios_xcode_appex_bundle_id) {
595    _bundle_extension = ".appex"
596  } else {
597    assert(false, "unknown product_type \"$product_type\" for $_target_name")
598  }
599
600  _is_app_bundle = _product_type == _ios_xcode_app_bundle_id
601
602  if (_extract_intents_metadata) {
603    _metadata_extraction = _target_name + "_metadata_extraction"
604    _metadata_bundledata = _target_name + "_metadata_bundledata"
605  }
606
607  executable(_executable_target) {
608    forward_variables_from(invoker,
609                           "*",
610                           [
611                             "bundle_deps",
612                             "bundle_deps_filter",
613                             "bundle_extension",
614                             "enable_code_signing",
615                             "entitlements_path",
616                             "entitlements_target",
617                             "extra_substitutions",
618                             "extra_system_frameworks",
619                             "info_plist",
620                             "info_plist_target",
621                             "output_name",
622                             "product_type",
623                             "visibility",
624                             "xcode_extra_attributes",
625                           ])
626
627    if (!defined(deps)) {
628      deps = []
629    }
630
631    visibility = []
632    foreach(_variant, _variants) {
633      visibility += [ ":${_variant.target_name}" ]
634    }
635    if (_extract_intents_metadata) {
636      visibility += [ ":$_metadata_extraction" ]
637      deps += [ invoker.intents_target ]
638    }
639
640    if (defined(invoker.orderfile_path)) {
641      orderfile_path = invoker.orderfile_path
642      if (!defined(ldflags)) {
643        ldflags = []
644      }
645      ldflags += [
646        "-Wl,-order_file",
647        "-Wl," + rebase_path(orderfile_path, root_build_dir),
648      ]
649
650      if (!defined(inputs)) {
651        inputs = []
652      }
653      inputs += [ orderfile_path ]
654    }
655
656    if (target_environment == "simulator") {
657      deps += [ ":$_generate_entitlements_target" ]
658
659      if (!defined(inputs)) {
660        inputs = []
661      }
662      inputs += [ _generate_entitlements_output ]
663
664      if (!defined(ldflags)) {
665        ldflags = []
666      }
667      ldflags += [ "-Wl,-sectcreate,__TEXT,__entitlements," +
668                   rebase_path(_generate_entitlements_output, root_build_dir) ]
669    }
670
671    output_name = _output_name
672    output_prefix_override = true
673    output_dir = target_out_dir
674  }
675
676  if (_extract_intents_metadata) {
677    _module_info_path =
678        get_label_info(invoker.intents_target, "target_out_dir") + "/" +
679        get_label_info(invoker.intents_target, "name") + ".module_info.json"
680
681    action(_metadata_extraction) {
682      _output_dir = "$target_out_dir/$target_name"
683      _binary_path = "$target_out_dir/$_output_name"
684
685      visibility = [ ":$_metadata_bundledata" ]
686      script = "//build/config/ios/extract_metadata.py"
687      sources = [
688        _binary_path,
689        _module_info_path,
690      ]
691      outputs = [
692        "$_output_dir/Metadata.appintents/extract.actionsdata",
693        "$_output_dir/Metadata.appintents/version.json",
694      ]
695      deps = [
696        ":$_executable_target",
697        invoker.intents_target,
698      ]
699      depfile = "$target_out_dir/$target_name.d"
700      args = [
701        "--toolchain-dir",
702        rebase_path(ios_toolchains_path, root_build_dir),
703        "--sdk-root",
704        rebase_path(ios_sdk_path, root_build_dir),
705        "--deployment-target",
706        ios_deployment_target,
707        "--target-cpu",
708        current_cpu,
709        "--target-environment",
710        target_environment,
711        "--depfile",
712        rebase_path(depfile, root_build_dir),
713        "--output",
714        rebase_path(_output_dir, root_build_dir),
715        "--binary-file",
716        rebase_path(_binary_path, root_build_dir),
717        "--module-info-path",
718        rebase_path(_module_info_path, root_build_dir),
719      ]
720
721      # Starting with Xcode 15.3, appintentsmetadataprocessor requires to be
722      # passed --xcode-version as parameter (with ${xcode_build} as value),
723      # while previous versions did not recognize the parameter. So check
724      # the version before deciding whether to set the parameter or not.
725      if (xcode_version_int >= 1530) {
726        args += [
727          "--xcode-version",
728          xcode_build,
729        ]
730      }
731    }
732
733    bundle_data(_metadata_bundledata) {
734      public_deps = [ ":$_metadata_extraction" ]
735      sources = get_target_outputs(":$_metadata_extraction")
736      outputs = [ "{{bundle_resources_dir}}/" +
737                  "Metadata.appintents/{{source_file_part}}" ]
738    }
739  }
740
741  _generate_info_plist = target_name + "_generate_info_plist"
742  ios_info_plist(_generate_info_plist) {
743    forward_variables_from(invoker,
744                           [
745                             "info_plist",
746                             "info_plist_target",
747                           ])
748
749    executable_name = _output_name
750
751    extra_substitutions = [ "BUNDLE_IDENTIFIER=$_bundle_identifier" ]
752    if (defined(invoker.extra_substitutions)) {
753      extra_substitutions += invoker.extra_substitutions
754    }
755  }
756
757  if (!defined(invoker.entitlements_target)) {
758    _entitlements_path = "//build/config/ios/entitlements.plist"
759    if (defined(invoker.entitlements_path)) {
760      _entitlements_path = invoker.entitlements_path
761    }
762  } else {
763    assert(!defined(invoker.entitlements_path),
764           "Cannot define both entitlements_path and entitlements_target" +
765               "for $_target_name")
766
767    _entitlements_target_outputs =
768        get_target_outputs(invoker.entitlements_target)
769    _entitlements_path = _entitlements_target_outputs[0]
770  }
771
772  action(_generate_entitlements_target) {
773    _gen_info_plist_outputs = get_target_outputs(":$_generate_info_plist")
774    _info_plist_path = _gen_info_plist_outputs[0]
775
776    script = "//build/config/ios/codesign.py"
777    deps = [ ":$_generate_info_plist" ]
778    if (defined(invoker.entitlements_target)) {
779      deps += [ invoker.entitlements_target ]
780    }
781    sources = [
782      _entitlements_path,
783      _info_plist_path,
784    ]
785    sources += ios_mobileprovision_files
786
787    outputs = [ _generate_entitlements_output ]
788
789    args = [
790      "generate-entitlements",
791      "-e=" + rebase_path(_entitlements_path, root_build_dir),
792      "-p=" + rebase_path(_info_plist_path, root_build_dir),
793    ]
794    foreach(mobileprovision, ios_mobileprovision_files) {
795      args += [ "-m=" + rebase_path(mobileprovision, root_build_dir) ]
796    }
797    args += rebase_path(outputs, root_build_dir)
798  }
799
800  # Only write PkgInfo for real application, not application extension.
801  if (_is_app_bundle) {
802    _create_pkg_info = target_name + "_pkg_info"
803    action(_create_pkg_info) {
804      forward_variables_from(invoker, [ "testonly" ])
805      script = "//build/apple/write_pkg_info.py"
806      inputs = [ "//build/apple/plist_util.py" ]
807      sources = get_target_outputs(":$_generate_info_plist")
808      outputs = [
809        # Cannot name the output PkgInfo as the name will not be unique if
810        # multiple ios_app_bundle are defined in the same BUILD.gn file. The
811        # file is renamed in the bundle_data outputs to the correct name.
812        "$target_gen_dir/$target_name",
813      ]
814      args = [ "--plist" ] + rebase_path(sources, root_build_dir) +
815             [ "--output" ] + rebase_path(outputs, root_build_dir)
816      deps = [ ":$_generate_info_plist" ]
817    }
818
819    _bundle_data_pkg_info = target_name + "_bundle_data_pkg_info"
820    bundle_data(_bundle_data_pkg_info) {
821      forward_variables_from(invoker, [ "testonly" ])
822      sources = get_target_outputs(":$_create_pkg_info")
823      outputs = [ "{{bundle_resources_dir}}/PkgInfo" ]
824      public_deps = [ ":$_create_pkg_info" ]
825    }
826  }
827
828  foreach(_variant, _variants) {
829    create_signed_bundle(_variant.target_name) {
830      forward_variables_from(invoker,
831                             [
832                               "bundle_deps",
833                               "bundle_deps_filter",
834                               "data_deps",
835                               "deps",
836                               "enable_code_signing",
837                               "entitlements_path",
838                               "entitlements_target",
839                               "extra_system_frameworks",
840                               "public_configs",
841                               "public_deps",
842                               "testonly",
843                               "visibility",
844                               "xcode_extra_attributes",
845                             ])
846
847      output_name = _output_name
848      bundle_gen_dir = _variant.bundle_gen_dir
849      bundle_binary_target = ":$_executable_target"
850      bundle_binary_output = _output_name
851      bundle_extension = _bundle_extension
852      product_type = _product_type
853      xcode_product_bundle_id = _bundle_identifier
854
855      _generate_info_plist_outputs =
856          get_target_outputs(":$_generate_info_plist")
857      primary_info_plist = _generate_info_plist_outputs[0]
858      partial_info_plist =
859          "$target_gen_dir/${_variant.target_name}_partial_info.plist"
860
861      if (!defined(deps)) {
862        deps = []
863      }
864      deps += [ ":$_generate_info_plist" ]
865
866      if (!defined(bundle_deps)) {
867        bundle_deps = []
868      }
869      if (_is_app_bundle) {
870        bundle_deps += [ ":$_bundle_data_pkg_info" ]
871      }
872      bundle_deps += _variant.bundle_deps
873      if (_extract_intents_metadata) {
874        bundle_deps += [ ":$_metadata_bundledata" ]
875      }
876
877      if (target_environment == "simulator") {
878        if (!defined(data_deps)) {
879          data_deps = []
880        }
881        if (build_with_chromium) {
882          data_deps += [ "//testing/iossim" ]
883        }
884      }
885    }
886  }
887
888  if (_default_variant.name != "") {
889    _bundle_short_name = "$_output_name$_bundle_extension"
890    action(_target_name) {
891      forward_variables_from(invoker, [ "testonly" ])
892
893      script = "//build/config/ios/hardlink.py"
894      public_deps = []
895      foreach(_variant, _variants) {
896        public_deps += [ ":${_variant.target_name}" ]
897      }
898
899      sources = [ "${_default_variant.bundle_gen_dir}/$_bundle_short_name" ]
900      outputs = [ "$root_out_dir/$_bundle_short_name" ]
901
902      args = [
903               "--output-dir",
904               rebase_path(root_out_dir, root_build_dir),
905               "--relative-to",
906               rebase_path(_default_variant.bundle_gen_dir, root_build_dir),
907             ] + rebase_path(sources, root_build_dir)
908    }
909  }
910}
911
912set_defaults("ios_app_bundle") {
913  configs = default_executable_configs
914}
915
916# Template to build an application extension bundle for iOS.
917#
918# This should be used instead of "executable" built-in target type on iOS.
919# As the template forward the generation of the application executable to
920# an "executable" target, all arguments supported by "executable" targets
921# are also supported by this template.
922#
923# Arguments
924#
925#   output_name:
926#       (optional) string, name of the generated application, if omitted,
927#       defaults to the target_name.
928#
929#   extra_substitutions:
930#       (optional) list of string in "key=value" format, each value will
931#       be used as an additional variable substitution rule when generating
932#       the application Info.plist
933#
934#   info_plist:
935#       (optional) string, path to the Info.plist file that will be used for
936#       the bundle.
937#
938#   info_plist_target:
939#       (optional) string, if the info_plist is generated from an action,
940#       rather than a regular source file, specify the target name in lieu
941#       of info_plist. The two arguments are mutually exclusive.
942#
943# For more information, see "gn help executable".
944template("ios_appex_bundle") {
945  assert(ios_is_app_extension,
946         "$target_name needs to be defined in app extension toolchain context")
947  ios_app_bundle(target_name) {
948    forward_variables_from(invoker,
949                           "*",
950                           [
951                             "bundle_extension",
952                             "product_type",
953                           ])
954    product_type = _ios_xcode_appex_bundle_id
955  }
956}
957
958set_defaults("ios_appex_bundle") {
959  configs = [ "//build/config/ios:ios_extension_executable_flags" ]
960}
961
962# Template to compile .xib and .storyboard files.
963#
964# Arguments
965#
966#     sources:
967#         list of string, sources to compile
968#
969#     ibtool_flags:
970#         (optional) list of string, additional flags to pass to the ibtool
971template("compile_ib_files") {
972  action_foreach(target_name) {
973    forward_variables_from(invoker,
974                           [
975                             "testonly",
976                             "visibility",
977                           ])
978    assert(defined(invoker.sources),
979           "sources must be specified for $target_name")
980    assert(defined(invoker.output_extension),
981           "output_extension must be specified for $target_name")
982
983    ibtool_flags = []
984    if (defined(invoker.ibtool_flags)) {
985      ibtool_flags = invoker.ibtool_flags
986    }
987
988    _output_extension = invoker.output_extension
989
990    script = "//build/config/ios/compile_ib_files.py"
991    sources = invoker.sources
992    outputs = [
993      "$target_gen_dir/$target_name/{{source_name_part}}.$_output_extension",
994    ]
995    args = [
996      "--input",
997      "{{source}}",
998      "--output",
999      rebase_path(
1000          "$target_gen_dir/$target_name/{{source_name_part}}.$_output_extension",
1001          root_build_dir),
1002    ]
1003    args += ibtool_flags
1004  }
1005}
1006
1007# Compile a xib or storyboard file and add it to a bundle_data so that it is
1008# available at runtime in the bundle.
1009#
1010# Arguments
1011#
1012#   source:
1013#       string, path of the xib or storyboard to compile.
1014#
1015# Forwards all variables to the bundle_data target.
1016template("bundle_data_ib_file") {
1017  assert(defined(invoker.source), "source needs to be defined for $target_name")
1018
1019  _source_extension = get_path_info(invoker.source, "extension")
1020  assert(_source_extension == "xib" || _source_extension == "storyboard",
1021         "source must be a .xib or .storyboard for $target_name")
1022
1023  _target_name = target_name
1024  if (_source_extension == "xib") {
1025    _compile_ib_file = target_name + "_compile_xib"
1026    _output_extension = "nib"
1027  } else {
1028    _compile_ib_file = target_name + "_compile_storyboard"
1029    _output_extension = "storyboardc"
1030  }
1031
1032  compile_ib_files(_compile_ib_file) {
1033    sources = [ invoker.source ]
1034    output_extension = _output_extension
1035    visibility = [ ":$_target_name" ]
1036    ibtool_flags = [
1037      "--minimum-deployment-target",
1038      ios_deployment_target,
1039      "--auto-activate-custom-fonts",
1040      "--target-device",
1041      "iphone",
1042      "--target-device",
1043      "ipad",
1044    ]
1045  }
1046
1047  bundle_data(_target_name) {
1048    forward_variables_from(invoker, "*", [ "source" ])
1049
1050    if (!defined(public_deps)) {
1051      public_deps = []
1052    }
1053    public_deps += [ ":$_compile_ib_file" ]
1054
1055    sources = get_target_outputs(":$_compile_ib_file")
1056
1057    outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ]
1058  }
1059}
1060
1061# Compile a strings file and add it to a bundle_data so that it is available
1062# at runtime in the bundle.
1063#
1064# Arguments
1065#
1066#   source:
1067#       string, path of the strings file to compile.
1068#
1069#   output:
1070#       string, path of the compiled file in the final bundle.
1071#
1072# Forwards all variables to the bundle_data target.
1073template("bundle_data_strings") {
1074  assert(defined(invoker.source), "source needs to be defined for $target_name")
1075  assert(defined(invoker.output), "output needs to be defined for $target_name")
1076
1077  _source_extension = get_path_info(invoker.source, "extension")
1078  assert(_source_extension == "strings",
1079         "source must be a .strings for $target_name")
1080
1081  _target_name = target_name
1082  _convert_target = target_name + "_compile_strings"
1083
1084  convert_plist(_convert_target) {
1085    visibility = [ ":$_target_name" ]
1086    source = invoker.source
1087    output =
1088        "$target_gen_dir/$_target_name/" + get_path_info(invoker.source, "file")
1089    format = "binary1"
1090  }
1091
1092  bundle_data(_target_name) {
1093    forward_variables_from(invoker,
1094                           "*",
1095                           [
1096                             "source",
1097                             "output",
1098                           ])
1099
1100    if (!defined(public_deps)) {
1101      public_deps = []
1102    }
1103    public_deps += [ ":$_convert_target" ]
1104
1105    sources = get_target_outputs(":$_convert_target")
1106
1107    outputs = [ invoker.output ]
1108  }
1109}
1110
1111# This template declares a bundle_data target that reference an assets
1112# catalog so that is is compiled to the asset catalog of the generated
1113# bundle.
1114#
1115# The target will ensure that only the files explicitly listed will be
1116# compiled into the final application (i.e. it allow listing some of
1117# the assets catalog content conditionally).
1118#
1119# The target requires that the files are located in a .xcassets bundle
1120# in the repository (or generated via a script). This ensures that the
1121# assets catalog is correctly visible in Xcode (though as usual, using
1122# Xcode to make change to the .xcassets bundle will not be reflected in
1123# the final build unless the target is updated in the gn configuration).
1124#
1125# Arguments
1126#
1127#     sources:
1128#       required, list of strings, path to the files contained in the
1129#       .xcassets bundle; this may contains a sub-set of the files on
1130#       disk if some assets are only compiled conditionally
1131#
1132#     catalog:
1133#       required, string, path to the .xcassets bundle; all path in
1134#       sources must be relative to this path or the compilation will
1135#       fail
1136#
1137# Example
1138#
1139#     bundle_data_xcassets("assets") {
1140#       catalog = "Assets.xcassets"
1141#       sources = [
1142#         "Assets.xcassets/Color.colorset/Contents.json",
1143#         "Assets.xcassets/Contents.json",
1144#       ]
1145#       if (includes_images) {
1146#         sources += [
1147#           "Assets.xcassets/Image.imageset/Contents.json",
1148#           "Assets.xcassets/Image.imageset/Image.svg",
1149#         ]
1150#       }
1151#     }
1152template("bundle_data_xcassets") {
1153  assert(defined(invoker.sources), "sources must be defined for $target_name")
1154  assert(defined(invoker.catalog), "catalog must be defined for $target_name")
1155
1156  _target_name = target_name
1157  _target_zip = target_name + "_zip"
1158
1159  zip(_target_zip) {
1160    _catalog_name = get_path_info(invoker.catalog, "file")
1161    _catalog_path = get_path_info(invoker.catalog, "dir")
1162
1163    inputs = invoker.sources
1164    output = "$target_out_dir/$target_name/$_catalog_name"
1165    base_dir = _catalog_path
1166  }
1167
1168  bundle_data(_target_name) {
1169    forward_variables_from(invoker,
1170                           "*",
1171                           [
1172                             "sources",
1173                             "deps",
1174                             "public_deps",
1175                           ])
1176
1177    public_deps = [ ":$_target_zip" ]
1178    sources = get_target_outputs(":$_target_zip")
1179    outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ]
1180  }
1181}
1182
1183# Template to package a shared library into an iOS framework bundle.
1184#
1185# By default, the bundle target this template generates does not link the
1186# resulting framework into anything that depends on it. If a dependency wants
1187# a link-time (as well as build-time) dependency on the framework bundle,
1188# depend against "$target_name+link". If only the build-time dependency is
1189# required (e.g., for copying into another bundle), then use "$target_name".
1190#
1191# Arguments
1192#
1193#     output_name:
1194#         (optional) string, name of the generated framework without the
1195#         .framework suffix. If omitted, defaults to target_name.
1196#
1197#     public_headers:
1198#         (optional) list of paths to header file that needs to be copied
1199#         into the framework bundle Headers subdirectory. If omitted or
1200#         empty then the Headers subdirectory is not created.
1201#
1202#     sources
1203#         (optional) list of files. Needs to be defined and non-empty if
1204#         public_headers is defined and non-empty.
1205#
1206#   enable_code_signing
1207#       (optional) boolean, control whether code signing is enabled or not,
1208#       default to ios_enable_code_signing if not defined.
1209#
1210#   transparent
1211#       (optional) boolean, whether the bundle is "transparent"; defaults to
1212#       "false" if ommitted; a bundle is considered "transparent" if it does
1213#       not package the "bundle_data" deps but forward them to all targets
1214#       the depend on it (unless the "bundle_data" target sets "product_type"
1215#       to "com.apple.product-type.framework").
1216#
1217# This template provides two targets for the resulting framework bundle. The
1218# link-time behavior varies depending on which of the two targets below is
1219# added as a dependency:
1220#   - $target_name only adds a build-time dependency. Targets that depend on
1221#     it will not link against the framework.
1222#   - $target_name+link adds a build-time and link-time dependency. Targets
1223#     that depend on it will link against the framework.
1224#
1225# The build-time-only dependency is used for when a target needs to use the
1226# framework either only for resources, or because the target loads it at run-
1227# time, via dlopen() or NSBundle. The link-time dependency will cause the
1228# dependee to have the framework loaded by dyld at launch.
1229#
1230# Example of build-time only dependency:
1231#
1232#     framework_bundle("CoreTeleportation") {
1233#       sources = [ ... ]
1234#     }
1235#
1236#     bundle_data("core_teleportation_bundle_data") {
1237#       deps = [ ":CoreTeleportation" ]
1238#       sources = [ "$root_out_dir/CoreTeleportation.framework" ]
1239#       outputs = [ "{{bundle_contents_dir}}/Frameworks/{{source_file_part}}" ]
1240#     }
1241#
1242#     app_bundle("GoatTeleporter") {
1243#       sources = [ ... ]
1244#       deps = [
1245#         ":core_teleportation_bundle_data",
1246#       ]
1247#     }
1248#
1249# The GoatTeleporter.app will not directly link against
1250# CoreTeleportation.framework, but it will be included in the bundle's
1251# Frameworks directory.
1252#
1253# Example of link-time dependency:
1254#
1255#     framework_bundle("CoreTeleportation") {
1256#       sources = [ ... ]
1257#       ldflags = [
1258#         "-install_name",
1259#         "@executable_path/../Frameworks/$target_name.framework"
1260#       ]
1261#     }
1262#
1263#     bundle_data("core_teleportation_bundle_data") {
1264#       deps = [ ":CoreTeleportation+link" ]
1265#       sources = [ "$root_out_dir/CoreTeleportation.framework" ]
1266#       outputs = [ "{{bundle_contents_dir}}/Frameworks/{{source_file_part}}" ]
1267#     }
1268#
1269#     app_bundle("GoatTeleporter") {
1270#       sources = [ ... ]
1271#       deps = [
1272#         ":core_teleportation_bundle_data",
1273#       ]
1274#     }
1275#
1276# Note that the framework is still copied to the app's bundle, but dyld will
1277# load this library when the app is launched because it uses the "+link"
1278# target as a dependency. This also requires that the framework set its
1279# install_name so that dyld can locate it.
1280#
1281# See "gn help shared_library" for more information on arguments supported
1282# by shared library target.
1283template("ios_framework_bundle") {
1284  _target_name = target_name
1285  _output_name = target_name
1286  if (defined(invoker.output_name)) {
1287    _output_name = invoker.output_name
1288  }
1289
1290  _product_type = "com.apple.product-type.framework"
1291  _has_public_headers =
1292      defined(invoker.public_headers) && invoker.public_headers != []
1293
1294  _shared_library_target = _target_name + "_shared_library"
1295  _link_target_name = _target_name + "+link"
1296
1297  if (_has_public_headers) {
1298    _default_toolchain_target_gen_dir =
1299        get_label_info("$_target_name", "target_gen_dir")
1300
1301    _framework_headers_target = _target_name + "_framework_headers"
1302
1303    _headers_map_config = _target_name + "_headers_map"
1304    _header_map_filename =
1305        "$_default_toolchain_target_gen_dir/$_output_name.headers.hmap"
1306    config(_headers_map_config) {
1307      visibility = [
1308        ":${_shared_library_target}",
1309        ":${_target_name}_signed_bundle",
1310      ]
1311      include_dirs = [ _header_map_filename ]
1312    }
1313  }
1314
1315  _framework_headers_config = _target_name + "_framework_headers_config"
1316  config(_framework_headers_config) {
1317    framework_dirs = [ root_out_dir ]
1318  }
1319
1320  _framework_public_config = _target_name + "_public_config"
1321  config(_framework_public_config) {
1322    configs = [ ":$_framework_headers_config" ]
1323    frameworks = [ "$_output_name.framework" ]
1324  }
1325
1326  shared_library(_shared_library_target) {
1327    forward_variables_from(invoker,
1328                           "*",
1329                           [
1330                             "bundle_deps",
1331                             "bundle_deps_filter",
1332                             "data_deps",
1333                             "enable_code_signing",
1334                             "extra_substitutions",
1335                             "info_plist",
1336                             "info_plist_target",
1337                             "output_name",
1338                             "public_configs",
1339                             "transparent",
1340                             "visibility",
1341                           ])
1342
1343    visibility = [ ":${_target_name}_signed_bundle" ]
1344
1345    if (!defined(ldflags)) {
1346      ldflags = []
1347    }
1348    ldflags +=
1349        [ "-Wl,-install_name,@rpath/$_output_name.framework/$_output_name" ]
1350
1351    if (_has_public_headers) {
1352      configs += [ ":$_headers_map_config" ]
1353
1354      if (!defined(deps)) {
1355        deps = []
1356      }
1357      deps += [ ":$_framework_headers_target" ]
1358    }
1359
1360    output_extension = ""
1361    output_name = _output_name
1362    output_prefix_override = true
1363    output_dir = target_out_dir
1364  }
1365
1366  if (_has_public_headers) {
1367    _public_headers = invoker.public_headers
1368
1369    _framework_root_dir = "$root_out_dir/$_output_name.framework"
1370    if (target_environment == "simulator" || target_environment == "device") {
1371      _framework_contents_dir = _framework_root_dir
1372    } else if (target_environment == "catalyst") {
1373      _framework_contents_dir = "$_framework_root_dir/Versions/A"
1374    }
1375
1376    _compile_headers_map_target = _target_name + "_compile_headers_map"
1377    action(_compile_headers_map_target) {
1378      visibility = [ ":$_framework_headers_target" ]
1379      forward_variables_from(invoker,
1380                             [
1381                               "deps",
1382                               "public_deps",
1383                               "testonly",
1384                             ])
1385      script = "//build/config/ios/write_framework_hmap.py"
1386      outputs = [ _header_map_filename ]
1387
1388      # The header map generation only wants the list of headers, not all of
1389      # sources, so filter any non-header source files from "sources". It is
1390      # less error prone that having the developer duplicate the list of all
1391      # headers in addition to "sources".
1392      sources = []
1393      foreach(_source, invoker.sources) {
1394        if (get_path_info(_source, "extension") == "h") {
1395          sources += [ _source ]
1396        }
1397      }
1398
1399      args = [
1400               rebase_path(_header_map_filename, root_build_dir),
1401               rebase_path(_framework_root_dir, root_build_dir),
1402             ] + rebase_path(sources, root_build_dir)
1403    }
1404
1405    _create_module_map_target = _target_name + "_module_map"
1406    action(_create_module_map_target) {
1407      visibility = [ ":$_framework_headers_target" ]
1408      script = "//build/config/ios/write_framework_modulemap.py"
1409      outputs = [ "$_framework_contents_dir/Modules/module.modulemap" ]
1410      args = [
1411        _output_name,
1412        rebase_path("$_framework_contents_dir/Modules", root_build_dir),
1413      ]
1414    }
1415
1416    _copy_public_headers_target = _target_name + "_copy_public_headers"
1417    copy(_copy_public_headers_target) {
1418      forward_variables_from(invoker,
1419                             [
1420                               "testonly",
1421                               "deps",
1422                             ])
1423      visibility = [ ":$_framework_headers_target" ]
1424      sources = _public_headers
1425      outputs = [ "$_framework_contents_dir/Headers/{{source_file_part}}" ]
1426
1427      # Do not use forward_variables_from for "public_deps" as
1428      # we do not want to forward those dependencies.
1429      if (defined(invoker.public_deps)) {
1430        if (!defined(deps)) {
1431          deps = []
1432        }
1433        deps += invoker.public_deps
1434      }
1435    }
1436
1437    group(_framework_headers_target) {
1438      forward_variables_from(invoker, [ "testonly" ])
1439      deps = [
1440        ":$_compile_headers_map_target",
1441        ":$_create_module_map_target",
1442      ]
1443      public_deps = [ ":$_copy_public_headers_target" ]
1444    }
1445  }
1446
1447  # Bundle identifier should respect rfc1034, so replace "_" with "-".
1448  _bundle_identifier =
1449      "$ios_app_bundle_id_prefix." + string_replace(_output_name, "_", "-")
1450
1451  _info_plist_target = _target_name + "_info_plist"
1452  _info_plist_bundle = _target_name + "_info_plist_bundle"
1453  ios_info_plist(_info_plist_target) {
1454    visibility = [ ":$_info_plist_bundle" ]
1455    executable_name = _output_name
1456    forward_variables_from(invoker,
1457                           [
1458                             "info_plist",
1459                             "info_plist_target",
1460                           ])
1461
1462    extra_substitutions = [ "BUNDLE_IDENTIFIER=$_bundle_identifier" ]
1463    if (defined(invoker.extra_substitutions)) {
1464      extra_substitutions += invoker.extra_substitutions
1465    }
1466  }
1467
1468  bundle_data(_info_plist_bundle) {
1469    visibility = [ ":${_target_name}_signed_bundle" ]
1470    forward_variables_from(invoker, [ "testonly" ])
1471    sources = get_target_outputs(":$_info_plist_target")
1472    public_deps = [ ":$_info_plist_target" ]
1473    product_type = _product_type
1474
1475    if (target_environment != "catalyst") {
1476      outputs = [ "{{bundle_contents_dir}}/Info.plist" ]
1477    } else {
1478      outputs = [ "{{bundle_resources_dir}}/Info.plist" ]
1479    }
1480  }
1481
1482  create_signed_bundle(_target_name + "_signed_bundle") {
1483    forward_variables_from(invoker,
1484                           [
1485                             "bundle_deps",
1486                             "bundle_deps_filter",
1487                             "data_deps",
1488                             "deps",
1489                             "enable_code_signing",
1490                             "public_configs",
1491                             "public_deps",
1492                             "testonly",
1493                             "transparent",
1494                             "visibility",
1495                           ])
1496
1497    product_type = _product_type
1498    bundle_extension = ".framework"
1499
1500    output_name = _output_name
1501    bundle_binary_target = ":$_shared_library_target"
1502    bundle_binary_output = _output_name
1503
1504    has_public_headers = _has_public_headers
1505
1506    # Framework do not have entitlements nor mobileprovision because they use
1507    # the one from the bundle using them (.app or .appex) as they are just
1508    # dynamic library with shared code.
1509    disable_entitlements = true
1510    disable_embedded_mobileprovision = true
1511
1512    if (!defined(deps)) {
1513      deps = []
1514    }
1515    deps += [ ":$_info_plist_bundle" ]
1516  }
1517
1518  group(_target_name) {
1519    forward_variables_from(invoker,
1520                           [
1521                             "public_configs",
1522                             "public_deps",
1523                             "testonly",
1524                             "visibility",
1525                           ])
1526    if (!defined(public_deps)) {
1527      public_deps = []
1528    }
1529    public_deps += [ ":${_target_name}_signed_bundle" ]
1530
1531    if (_has_public_headers) {
1532      if (!defined(public_configs)) {
1533        public_configs = []
1534      }
1535      public_configs += [ ":$_framework_headers_config" ]
1536    }
1537  }
1538
1539  group(_link_target_name) {
1540    forward_variables_from(invoker,
1541                           [
1542                             "public_configs",
1543                             "public_deps",
1544                             "testonly",
1545                             "visibility",
1546                           ])
1547    if (!defined(public_deps)) {
1548      public_deps = []
1549    }
1550    public_deps += [ ":$_target_name" ]
1551
1552    if (!defined(all_dependent_configs)) {
1553      all_dependent_configs = []
1554    }
1555    all_dependent_configs += [ ":$_framework_public_config" ]
1556  }
1557
1558  bundle_data(_target_name + "+bundle") {
1559    forward_variables_from(invoker,
1560                           [
1561                             "testonly",
1562                             "visibility",
1563                           ])
1564    public_deps = [ ":$_target_name" ]
1565    sources = [ "$root_out_dir/$_output_name.framework" ]
1566    outputs = [ "{{bundle_contents_dir}}/Frameworks/$_output_name.framework" ]
1567  }
1568}
1569
1570set_defaults("ios_framework_bundle") {
1571  configs = default_shared_library_configs
1572}
1573
1574# Template to build a xctest bundle that contains a loadable module for iOS.
1575#
1576# Arguments
1577#
1578#   deps:
1579#       list of labels to depends on, these values are used to create the
1580#       loadable module.
1581#
1582#   product_type
1583#       string, product type for the generated Xcode project, use
1584#       "com.apple.product-type.bundle.unit-test" for unit test and
1585#       "com.apple.product-type.bundle.ui-testing" for UI testing.
1586#
1587#   host_target:
1588#       string, name of the target that depends on the generated bundle, this
1589#       value is used to restrict visibilities.
1590#
1591#   xcode_test_application_name:
1592#       string, name of the test application for Xcode unit or ui test target.
1593#
1594#   output_name
1595#       (optional) string, name of the generated application, if omitted,
1596#       defaults to the target_name.
1597#
1598# This template defines two targets, one named "${target_name}" is the xctest
1599# bundle, and the other named "${target_name}_bundle" is a bundle_data that
1600# wraps the xctest bundle and that only the "${host_target}" can depend on.
1601#
1602template("ios_xctest_bundle") {
1603  assert(defined(invoker.deps), "deps must be defined for $target_name")
1604  assert(defined(invoker.product_type),
1605         "product_type must be defined for $target_name")
1606  assert(invoker.product_type == _ios_xcode_xctest_bundle_id ||
1607             invoker.product_type == _ios_xcode_xcuitest_bundle_id,
1608         "product_type defined for $target_name is invalid.")
1609  assert(defined(invoker.host_target),
1610         "host_target must be defined for $target_name")
1611  assert(defined(invoker.xcode_test_application_name),
1612         "xcode_test_application_name must be defined for $target_name")
1613
1614  _target_name = target_name
1615  _output_name = target_name
1616
1617  if (defined(invoker.output_name)) {
1618    _output_name = invoker.output_name
1619  }
1620
1621  _loadable_module_target = _target_name + "_loadable_module"
1622
1623  loadable_module(_loadable_module_target) {
1624    forward_variables_from(invoker,
1625                           "*",
1626                           [
1627                             "bundle_deps",
1628                             "bundle_deps_filter",
1629                             "host_target",
1630                             "output_dir",
1631                             "output_extension",
1632                             "output_name",
1633                             "output_prefix_override",
1634                             "product_type",
1635                             "testonly",
1636                             "visibility",
1637                             "xcode_test_application_name",
1638                             "xcode_test_application_output_name",
1639                             "xctest_bundle_principal_class",
1640                           ])
1641
1642    testonly = true
1643    visibility = [ ":$_target_name" ]
1644
1645    configs += [ "//build/config/ios:xctest_config" ]
1646
1647    output_dir = target_out_dir
1648    output_name = _output_name
1649    output_prefix_override = true
1650    output_extension = ""
1651  }
1652
1653  _info_plist_target = _target_name + "_info_plist"
1654  _info_plist_bundle = _target_name + "_info_plist_bundle"
1655
1656  # Bundle identifier should respect rfc1034, so replace "_" with "-".
1657  _bundle_identifier = "$ios_app_bundle_id_prefix.chrome." +
1658                       string_replace(_output_name, "_", "-")
1659
1660  ios_info_plist(_info_plist_target) {
1661    testonly = true
1662    visibility = [ ":$_info_plist_bundle" ]
1663
1664    info_plist = "//build/config/ios/Module-Info.plist"
1665    executable_name = _output_name
1666
1667    if (defined(invoker.xctest_bundle_principal_class)) {
1668      _principal_class = invoker.xctest_bundle_principal_class
1669    } else {
1670      # Fall back to a reasonable default value.
1671      _principal_class = "NSObject"
1672    }
1673    extra_substitutions = [
1674      "XCTEST_BUNDLE_PRINCIPAL_CLASS=${_principal_class}",
1675      "BUNDLE_IDENTIFIER=$_bundle_identifier",
1676    ]
1677  }
1678
1679  bundle_data(_info_plist_bundle) {
1680    testonly = true
1681    visibility = [ ":$_target_name" ]
1682
1683    public_deps = [ ":$_info_plist_target" ]
1684
1685    sources = get_target_outputs(":$_info_plist_target")
1686    outputs = [ "{{bundle_contents_dir}}/Info.plist" ]
1687  }
1688
1689  _xctest_bundle = _target_name + "_bundle"
1690  create_signed_bundle(_target_name) {
1691    forward_variables_from(invoker,
1692                           [
1693                             "bundle_deps",
1694                             "bundle_deps_filter",
1695                             "bundle_id",
1696                             "data_deps",
1697                             "enable_code_signing",
1698                             "product_type",
1699                             "xcode_test_application_name",
1700                           ])
1701
1702    testonly = true
1703    visibility = [ ":$_xctest_bundle" ]
1704
1705    bundle_extension = ".xctest"
1706
1707    output_name = _output_name
1708    bundle_binary_target = ":$_loadable_module_target"
1709    bundle_binary_output = _output_name
1710
1711    xcode_extra_attributes = {
1712      IPHONEOS_DEPLOYMENT_TARGET = ios_deployment_target
1713      PRODUCT_BUNDLE_IDENTIFIER = _bundle_identifier
1714      CODE_SIGNING_REQUIRED = "NO"
1715      CODE_SIGNING_ALLOWED = "NO"
1716      CODE_SIGN_IDENTITY = ""
1717      DONT_GENERATE_INFOPLIST_FILE = "YES"
1718
1719      # For XCUITest, Xcode requires specifying the host application name
1720      # via the TEST_TARGET_NAME attribute.
1721      if (invoker.product_type == _ios_xcode_xcuitest_bundle_id) {
1722        TEST_TARGET_NAME = invoker.xcode_test_application_name
1723      }
1724
1725      # For XCTest, Xcode requires specifying the host application path via
1726      # both BUNDLE_LOADER and TEST_HOST attributes.
1727      if (invoker.product_type == _ios_xcode_xctest_bundle_id) {
1728        _xcode_app_name = invoker.xcode_test_application_name
1729        if (defined(invoker.xcode_test_application_output_name)) {
1730          _xcode_app_name = invoker.xcode_test_application_output_name
1731        }
1732
1733        BUNDLE_LOADER = "\$(TEST_HOST)"
1734        TEST_HOST = "\$(BUILT_PRODUCTS_DIR)/" +
1735                    "${_xcode_app_name}.app/${_xcode_app_name}"
1736      }
1737    }
1738
1739    deps = [ ":$_info_plist_bundle" ]
1740  }
1741
1742  bundle_data(_xctest_bundle) {
1743    forward_variables_from(invoker, [ "host_target" ])
1744
1745    testonly = true
1746    visibility = [ ":$host_target" ]
1747
1748    public_deps = [ ":$_target_name" ]
1749    sources = [ "$root_out_dir/$_output_name.xctest" ]
1750    outputs = [ "{{bundle_contents_dir}}/PlugIns/$_output_name.xctest" ]
1751  }
1752}
1753
1754set_defaults("ios_xctest_bundle") {
1755  configs = default_shared_library_configs
1756}
1757
1758# For Chrome on iOS we want to run XCTests for all our build configurations
1759# (Debug, Release, ...). In addition, the symbols visibility is configured to
1760# private by default. To simplify testing with those constraints, our tests are
1761# compiled in the TEST_HOST target instead of the .xctest bundle.
1762template("ios_xctest_test") {
1763  _target_name = target_name
1764  _output_name = target_name
1765  if (defined(invoker.output_name)) {
1766    _output_name = invoker.output_name
1767  }
1768
1769  _xctest_target = _target_name + "_module"
1770  _xctest_output = _output_name + "_module"
1771
1772  _host_target = _target_name
1773  _host_output = _output_name
1774
1775  # Allow invokers to specify their own target for the xctest module, but
1776  # fall back to a default (empty) module otherwise.
1777  if (defined(invoker.xctest_module_target)) {
1778    _xctest_module_target = invoker.xctest_module_target
1779  } else {
1780    _xctest_module_target_name = _xctest_target + "shell_source"
1781    _xctest_module_target = ":$_xctest_module_target_name"
1782    source_set(_xctest_module_target_name) {
1783      sources = [ "//build/config/ios/xctest_shell.mm" ]
1784
1785      configs += [ "//build/config/ios:xctest_config" ]
1786    }
1787  }
1788
1789  ios_xctest_bundle(_xctest_target) {
1790    forward_variables_from(invoker, [ "data_deps" ])
1791    output_name = _xctest_output
1792    product_type = _ios_xcode_xctest_bundle_id
1793    host_target = _host_target
1794
1795    # TODO(crbug.com/1056328) The change in output name results in a mismatch
1796    # between this value and the ios_app_bundle target name. To mitigate, this
1797    # has been modified to _host_target. output_name is set to _host_output
1798    # to mitigate the naming.
1799    xcode_test_application_name = _host_target
1800    xcode_test_application_output_name = _host_output
1801
1802    deps = [ _xctest_module_target ]
1803  }
1804
1805  ios_app_bundle(_host_target) {
1806    forward_variables_from(invoker, "*", [ "testonly" ])
1807
1808    testonly = true
1809    output_name = _host_output
1810    configs += [ "//build/config/ios:xctest_config" ]
1811
1812    if (!defined(invoker.info_plist) && !defined(invoker.info_plist_target)) {
1813      info_plist = "//build/config/ios/Host-Info.plist"
1814    }
1815
1816    # Xcode needs the following frameworks installed in the application (and
1817    # signed) for the XCTest to run, so install them using
1818    # extra_system_frameworks.
1819    extra_system_frameworks = [
1820      "$ios_sdk_platform_path/Developer/Library/Frameworks/XCTest.framework",
1821      "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCTAutomationSupport.framework",
1822      "$ios_sdk_platform_path/Developer/usr/lib/libXCTestBundleInject.dylib",
1823    ]
1824
1825    # Xcode 13 now depends on XCTestCore. To keep things future proof, copy over
1826    # everything that Xcode copies.
1827    if (xcode_version_int >= 1300) {
1828      extra_system_frameworks += [
1829        "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCTestCore.framework",
1830        "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCUIAutomation.framework",
1831        "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCUnit.framework",
1832        "$ios_sdk_platform_path/Developer/usr/lib/libXCTestSwiftSupport.dylib",
1833      ]
1834    }
1835
1836    # XCTestSupport framework is required as of Xcode 14.3 or later.
1837    if (xcode_version_int >= 1430) {
1838      extra_system_frameworks += [ "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCTestSupport.framework" ]
1839    }
1840
1841    _xctest_bundle = _xctest_target + "_bundle"
1842    if (!defined(bundle_deps)) {
1843      bundle_deps = []
1844    }
1845    bundle_deps += [ ":$_xctest_bundle" ]
1846  }
1847}
1848
1849set_defaults("ios_xctest_test") {
1850  configs = default_executable_configs
1851}
1852
1853# Template to build a xcuitest test runner bundle.
1854#
1855# Xcode requires a test runner application with a copy of the XCTest dynamic
1856# library bundle in it for the XCUITest to run. The test runner bundle is created
1857# by copying the system bundle XCTRunner.app from Xcode SDK with the plist file
1858# being properly tweaked, and a xctest and it needs to be code signed in order
1859# to run on devices.
1860#
1861# Arguments
1862#
1863#   xctest_bundle
1864#       string, name of the dependent xctest bundle target.
1865#
1866#   output_name
1867#       (optional) string, name of the generated application, if omitted,
1868#       defaults to the target_name.
1869#
1870template("ios_xcuitest_test_runner_bundle") {
1871  assert(defined(invoker.xctest_bundle),
1872         "xctest_bundle must be defined for $target_name")
1873
1874  _target_name = target_name
1875  _output_name = target_name
1876  if (defined(invoker.output_name)) {
1877    _output_name = invoker.output_name
1878  }
1879
1880  # Bundle identifier should respect rfc1034, so replace "_" with "-".
1881  _bundle_identifier = "$ios_app_bundle_id_prefix.chrome." +
1882                       string_replace(_output_name, "_", "-")
1883
1884  _xctrunner_path =
1885      "$ios_sdk_platform_path/Developer/Library/Xcode/Agents/XCTRunner.app"
1886
1887  _info_plist_merge_plist = _target_name + "_info_plist_merge_plist"
1888  _info_plist_target = _target_name + "_info_plist"
1889  _info_plist_bundle = _target_name + "_info_plist_bundle"
1890
1891  action(_info_plist_merge_plist) {
1892    testonly = true
1893    script = "//build/apple/plist_util.py"
1894
1895    sources = [
1896      "$_xctrunner_path/Info.plist",
1897
1898      # NOTE: The XCTRunnerAddition+Info.plist must come after the Info.plist
1899      # because it overrides the values under "CFBundleIdentifier" and
1900      # "CFBundleName".
1901      "//build/config/ios/resources/XCTRunnerAddition+Info.plist",
1902    ]
1903
1904    _output_name = "$target_gen_dir/${_target_name}_merged.plist"
1905    outputs = [ _output_name ]
1906    args = [
1907             "merge",
1908             "-f=xml1",
1909             "-x=$xcode_version",
1910             "-o=" + rebase_path(_output_name, root_build_dir),
1911           ] + rebase_path(sources, root_build_dir)
1912
1913    if (use_system_xcode && (use_remoteexec || use_siso)) {
1914      deps = [ "//build/config/ios:copy_xctrunner_app" ]
1915    }
1916  }
1917
1918  ios_info_plist(_info_plist_target) {
1919    testonly = true
1920    visibility = [ ":$_info_plist_bundle" ]
1921
1922    executable_name = _output_name
1923    info_plist_target = ":$_info_plist_merge_plist"
1924    extra_substitutions = [ "BUNDLE_IDENTIFIER=$_bundle_identifier" ]
1925  }
1926
1927  bundle_data(_info_plist_bundle) {
1928    testonly = true
1929    visibility = [ ":$_target_name" ]
1930
1931    public_deps = [ ":$_info_plist_target" ]
1932
1933    sources = get_target_outputs(":$_info_plist_target")
1934    outputs = [ "{{bundle_contents_dir}}/Info.plist" ]
1935  }
1936
1937  _pkginfo_bundle = _target_name + "_pkginfo_bundle"
1938  bundle_data(_pkginfo_bundle) {
1939    testonly = true
1940    visibility = [ ":$_target_name" ]
1941
1942    sources = [ "$_xctrunner_path/PkgInfo" ]
1943
1944    outputs = [ "{{bundle_contents_dir}}/PkgInfo" ]
1945
1946    if (use_system_xcode && (use_remoteexec || use_siso)) {
1947      public_deps = [ "//build/config/ios:copy_xctrunner_app" ]
1948    }
1949  }
1950
1951  _xctest_bundle = invoker.xctest_bundle
1952  create_signed_bundle(_target_name) {
1953    testonly = true
1954
1955    bundle_binary_target = "//build/config/ios:xctest_runner_without_arm64e"
1956    bundle_binary_output = "XCTRunner"
1957    bundle_extension = ".app"
1958    product_type = _ios_xcode_app_bundle_id
1959
1960    output_name = _output_name
1961
1962    # Xcode needs the following frameworks installed in the application
1963    # (and signed) for the XCUITest to run, so install them using
1964    # extra_system_frameworks.
1965    extra_system_frameworks = [
1966      "$ios_sdk_platform_path/Developer/Library/Frameworks/XCTest.framework",
1967      "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCTAutomationSupport.framework",
1968    ]
1969
1970    # Xcode 13 now depends on XCTestCore. To keep things future proof, copy over
1971    # everything that Xcode copies.
1972    if (xcode_version_int >= 1300) {
1973      extra_system_frameworks += [
1974        "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCTestCore.framework",
1975        "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCUIAutomation.framework",
1976        "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCUnit.framework",
1977        "$ios_sdk_platform_path/Developer/usr/lib/libXCTestSwiftSupport.dylib",
1978      ]
1979    }
1980
1981    # XCTestSupport framework is required as of Xcode 14.3 or later.
1982    if (xcode_version_int >= 1430) {
1983      extra_system_frameworks += [ "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCTestSupport.framework" ]
1984    }
1985
1986    bundle_deps = []
1987    if (defined(invoker.bundle_deps)) {
1988      bundle_deps += invoker.bundle_deps
1989    }
1990    bundle_deps += [
1991      ":$_info_plist_bundle",
1992      ":$_pkginfo_bundle",
1993      ":$_xctest_bundle",
1994    ]
1995  }
1996}
1997
1998# Template to build a XCUITest that consists of two parts: the test runner
1999# application bundle and the xctest dynamic library.
2000#
2001# Arguments
2002#
2003#   deps:
2004#       list of labels to depends on, these values are used to create the
2005#       xctest dynamic library.
2006#
2007#   xcode_test_application_name:
2008#       string, name of the test application for the ui test target.
2009#
2010#   runner_only_bundle_deps:
2011#       list of labels of bundle target to include in the runner and
2012#       exclude from the test module (the use case is a framework bundle
2013#       that is used by the test module and thus needs to be packaged in
2014#       the runner application bundle)
2015#
2016# This template defines two targets, one named "${target_name}_module" is the
2017# xctest dynamic library, and the other named "${target_name}_runner" is the
2018# test runner application bundle.
2019#
2020template("ios_xcuitest_test") {
2021  assert(defined(invoker.deps), "deps must be defined for $target_name")
2022  assert(defined(invoker.xcode_test_application_name),
2023         "xcode_test_application_name must be defined for $target_name")
2024
2025  _xcuitest_target = target_name
2026  if (defined(invoker.output_name)) {
2027    _xcuitest_target = invoker.output_name
2028  }
2029
2030  _xcuitest_runner_target = _xcuitest_target + "_runner"
2031  _xcuitest_module_target = _xcuitest_target + "_module"
2032
2033  group(target_name) {
2034    testonly = true
2035
2036    deps = [ ":$_xcuitest_runner_target" ]
2037  }
2038
2039  _xcuitest_module_output = _xcuitest_target
2040  ios_xctest_bundle(_xcuitest_module_target) {
2041    forward_variables_from(invoker,
2042                           [
2043                             "bundle_deps",
2044                             "data_deps",
2045                             "deps",
2046                             "xcode_test_application_name",
2047                             "xctest_bundle_principal_class",
2048                           ])
2049
2050    product_type = _ios_xcode_xcuitest_bundle_id
2051    host_target = _xcuitest_runner_target
2052    output_name = _xcuitest_module_output
2053
2054    if (defined(invoker.runner_only_bundle_deps)) {
2055      bundle_deps_filter = invoker.runner_only_bundle_deps
2056    }
2057  }
2058
2059  _xcuitest_runner_output = _xcuitest_target + "-Runner"
2060  ios_xcuitest_test_runner_bundle(_xcuitest_runner_target) {
2061    output_name = _xcuitest_runner_output
2062    xctest_bundle = _xcuitest_module_target + "_bundle"
2063
2064    if (defined(invoker.runner_only_bundle_deps)) {
2065      if (!defined(bundle_deps)) {
2066        bundle_deps = []
2067      }
2068      bundle_deps += invoker.runner_only_bundle_deps
2069    }
2070  }
2071}
2072
2073set_defaults("ios_xcuitest_test") {
2074  configs = default_executable_configs
2075}
2076