Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/chromium/build/config/ios/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 52 kB image not shown  

Quelle  rules.gni   Sprache: unbekannt

 
Spracherkennung für: .gni vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

# Copyright 2015 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import("//chromium/build/apple/apple_info_plist.gni")
import("//chromium/build/config/apple/create_signed_bundle.gni")
import("//chromium/build/config/apple/mobile_bundle_data.gni")
import("//chromium/build/config/apple/symbols.gni")
import("//chromium/build/config/compiler/compiler.gni")
import("//chromium/build/config/ios/ios_sdk.gni")
import("//chromium/build/toolchain/rbe.gni")
import("//chromium/build/toolchain/siso.gni")
import("//chromium/build/toolchain/toolchain.gni")
import("//build_overrides/build.gni")

# iOS-specific wrapper around apple_mobile_create_signed_bundle.
#
# See //build/config/apple/mobile_rules.gni for a description of arguments.
template("ios_create_signed_bundle") {
  apple_mobile_create_signed_bundle(target_name) {
    forward_variables_from(invoker,
                           "*",
                           [
                             "platform_sdk_name",
                             "xcode_extra_attributes",
                           ])
    platform_sdk_name = ios_sdk_name
    xcode_extra_attributes = {
      IPHONEOS_DEPLOYMENT_TARGET = ios_deployment_target

      # If invoker has defined extra attributes, they override the defaults.
      if (defined(invoker.xcode_extra_attributes)) {
        forward_variables_from(invoker.xcode_extra_attributes, "*")
      }
    }
  }
}

# Expose the template under its original name, to avoid breaking dependencies.
template("create_signed_bundle") {
  ios_create_signed_bundle(target_name) {
    forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
    forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
  }
}

# Generates Info.plist files for iOS apps and frameworks.
#
# Arguments
#
#     info_plist:
#         (optional) string, path to the Info.plist file that will be used for
#         the bundle.
#
#     info_plist_target:
#         (optional) string, if the info_plist is generated from an action,
#         rather than a regular source file, specify the target name in lieu
#         of info_plist. The two arguments are mutually exclusive.
#
#     executable_name:
#         string, name of the generated target used for the product
#         and executable name as specified in the output Info.plist.
#
#     extra_substitutions:
#         (optional) string array, 'key=value' pairs for extra fields which are
#         specified in a source Info.plist template.
template("ios_info_plist") {
  assert(defined(invoker.info_plist) != defined(invoker.info_plist_target),
         "Only one of info_plist or info_plist_target may be specified in " +
             target_name)

  if (defined(invoker.info_plist)) {
    _info_plist = invoker.info_plist
  } else {
    _info_plist_target_output = get_target_outputs(invoker.info_plist_target)
    _info_plist = _info_plist_target_output[0]
  }

  apple_info_plist(target_name) {
    format = "binary1"
    extra_substitutions = [
      "IOS_BUNDLE_ID_PREFIX=$ios_app_bundle_id_prefix",
      "IOS_PLATFORM_BUILD=$ios_platform_build",
      "IOS_PLATFORM_NAME=$ios_sdk_name",
      "IOS_PLATFORM_VERSION=$ios_sdk_version",
      "IOS_SDK_BUILD=$ios_sdk_build",
      "IOS_SDK_NAME=$ios_sdk_name$ios_sdk_version",
      "IOS_SUPPORTED_PLATFORM=$ios_sdk_platform",
      "BUILD_MACHINE_OS_BUILD=$machine_os_build",
      "IOS_DEPLOYMENT_TARGET=$ios_deployment_target",
      "XCODE_BUILD=$xcode_build",
      "XCODE_VERSION=$xcode_version",
    ]
    if (defined(invoker.extra_substitutions)) {
      extra_substitutions += invoker.extra_substitutions
    }
    plist_templates = [
      "//chromium/build/config/ios/BuildInfo.plist",
      _info_plist,
    ]
    if (defined(invoker.info_plist_target)) {
      deps = [ invoker.info_plist_target ]
    }
    forward_variables_from(invoker,
                           [
                             "executable_name",
                             "output_name",
                             "visibility",
                             "testonly",
                           ])
  }
}

# Template to build an application bundle for iOS.
#
# This should be used instead of "executable" built-in target type on iOS.
# As the template forward the generation of the application executable to
# an "executable" target, all arguments supported by "executable" targets
# are also supported by this template.
#
# Arguments
#
#   output_name:
#       (optional) string, name of the generated application, if omitted,
#       defaults to the target_name.
#
#   extra_substitutions:
#       (optional) list of string in "key=value" format, each value will
#       be used as an additional variable substitution rule when generating
#       the application Info.plist
#
#   info_plist:
#       (optional) string, path to the Info.plist file that will be used for
#       the bundle.
#
#   info_plist_target:
#       (optional) string, if the info_plist is generated from an action,
#       rather than a regular source file, specify the target name in lieu
#       of info_plist. The two arguments are mutually exclusive.
#
#   entitlements_path:
#       (optional) path to the template to use to generate the application
#       entitlements by performing variable substitutions, defaults to
#       //build/config/ios/entitlements.plist.
#
#   entitlements_target:
#       (optional) label of the target generating the application
#       entitlements (must generate a single file as output); cannot be
#       defined if entitlements_path is set.
#
#   product_type
#       (optional) string, product type for the generated Xcode project,
#       default to "com.apple.product-type.application". Should only be
#       overriden when building application extension.
#
#   enable_code_signing
#       (optional) boolean, control whether code signing is enabled or not,
#       default to ios_enable_code_signing if not defined.
#
#   variants
#       (optional) list of scopes, each scope needs to define the attributes
#       "name" and "bundle_deps"; if defined and non-empty, then one bundle
#       named $target_out_dir/$variant/$output_name will be created for each
#       variant with the same binary but the correct bundle_deps, the bundle
#       at $target_out_dir/$output_name will be a copy of the first variant.
#
#   bundle_identifier:
#       (optional) string, value of CFBundleIdentifier in the application
#       Info.plist, defaults to "$ios_app_bundle_id_prefix.$output_name"
#       if omitted. Will be used to set BUNDLE_IDENTIFIER when generating
#       the application Info.plist
#
#   orderfile_path:
#       (optional) string, path to an orderfile passed to the linker in order
#       to improve application launch performance.
#
#   intents_target:
#       (optional) string, label of the target defining the intents for the
#       application. If defined, it must corresponds to a `swift_source_set`
#       target configured with `generate_intents = true`.
#
#   transparent
#       (optional) boolean, whether the bundle is "transparent"; defaults to
#       "false" if omitted; a bundle is considered "transparent" if it does
#       not package the "bundle_data" deps but forward them to all targets
#       the depend on it (unless the "bundle_data" target sets "product_type"
#       to the same value as the "ios_create_signed_bundle" target).
#
# For more information, see "gn help executable".
template("ios_app_bundle") {
  _output_name = target_name
  _target_name = target_name
  if (defined(invoker.output_name)) {
    _output_name = invoker.output_name
  }

  assert(
      !defined(invoker.bundle_extension),
      "bundle_extension must not be set for ios_app_bundle template for $target_name")

  # Whether the intents metadata should be extracted (note that they are
  # disabled when building for the catalyst environment)
  _extract_intents_metadata = false
  if (defined(invoker.intents_target)) {
    _extract_intents_metadata =
        invoker.intents_target != "" && target_environment != "catalyst"
  }

  if (defined(invoker.bundle_identifier)) {
    _bundle_identifier = invoker.bundle_identifier
    assert(_bundle_identifier == string_replace(_bundle_identifier, "_", "-"),
           "$target_name: bundle_identifier does not respect rfc1034: " +
               _bundle_identifier)
  } else {
    # Bundle identifier should respect rfc1034, so replace "_" with "-".
    _bundle_identifier =
        "$ios_app_bundle_id_prefix." + string_replace(_output_name, "_", "-")
  }

  if (defined(invoker.variants) && invoker.variants != []) {
    _variants = []

    foreach(_variant, invoker.variants) {
      assert(defined(_variant.name) && _variant.name != "",
             "name must be defined for all $target_name variants")

      assert(defined(_variant.bundle_deps),
             "bundle_deps must be defined for all $target_name variants")

      _variants += [
        {
          name = _variant.name
          bundle_deps = _variant.bundle_deps
          target_name = "${_target_name}_variants_${_variant.name}"
          bundle_gen_dir = "$root_out_dir/variants/${_variant.name}"
        },
      ]
    }
  } else {
    # If no variants are passed to the template, use a fake variant with
    # no name to avoid duplicating code. As no variant can have an empty
    # name except this fake variant, it is possible to know if a variant
    # is fake or not.
    _variants = [
      {
        name = ""
        bundle_deps = []
        target_name = _target_name
        bundle_gen_dir = root_out_dir
      },
    ]
  }

  _default_variant = _variants[0]

  _executable_target = _target_name + "_executable"
  _generate_entitlements_target = _target_name + "_gen_entitlements"
  _generate_entitlements_output =
      get_label_info(":$_generate_entitlements_target", "target_out_dir") +
      "/$_output_name.xcent"

  _product_type = apple_mobile_xcode_app_bundle_id
  if (defined(invoker.product_type)) {
    _product_type = invoker.product_type
  }

  if (_product_type == apple_mobile_xcode_app_bundle_id) {
    _bundle_extension = ".app"
  } else if (_product_type == apple_mobile_xcode_appex_bundle_id) {
    _bundle_extension = ".appex"
  } else {
    assert(false, "unknown product_type \"$product_type\" for $_target_name")
  }

  _is_app_bundle = _product_type == apple_mobile_xcode_app_bundle_id

  if (_extract_intents_metadata) {
    _metadata_extraction = _target_name + "_metadata_extraction"
    _metadata_bundledata = _target_name + "_metadata_bundledata"
  }

  executable(_executable_target) {
    forward_variables_from(invoker,
                           "*",
                           [
                             "bundle_deps",
                             "bundle_deps_filter",
                             "bundle_extension",
                             "enable_code_signing",
                             "entitlements_path",
                             "entitlements_target",
                             "extra_substitutions",
                             "extra_system_frameworks",
                             "info_plist",
                             "info_plist_target",
                             "output_name",
                             "product_type",
                             "transparent",
                             "visibility",
                             "xcode_extra_attributes",
                           ])

    if (!defined(deps)) {
      deps = []
    }

    visibility = []
    foreach(_variant, _variants) {
      visibility += [ ":${_variant.target_name}" ]
    }
    if (_extract_intents_metadata) {
      visibility += [ ":$_metadata_extraction" ]
      deps += [ invoker.intents_target ]
    }

    if (defined(invoker.orderfile_path)) {
      orderfile_path = invoker.orderfile_path
      if (!defined(ldflags)) {
        ldflags = []
      }
      ldflags += [
        "-Wl,-order_file",
        "-Wl," + rebase_path(orderfile_path, root_build_dir),
      ]

      if (!defined(inputs)) {
        inputs = []
      }
      inputs += [ orderfile_path ]
    }

    if (target_environment == "simulator") {
      deps += [ ":$_generate_entitlements_target" ]

      if (!defined(inputs)) {
        inputs = []
      }
      inputs += [ _generate_entitlements_output ]

      if (!defined(ldflags)) {
        ldflags = []
      }
      ldflags += [ "-Wl,-sectcreate,__TEXT,__entitlements," +
                   rebase_path(_generate_entitlements_output, root_build_dir) ]
    }

    output_name = _output_name
    output_prefix_override = true
    output_dir = target_out_dir
  }

  if (_extract_intents_metadata) {
    _module_info_path =
        get_label_info(invoker.intents_target, "target_out_dir") + "/" +
        get_label_info(invoker.intents_target, "name") + ".module_info.json"

    action(_metadata_extraction) {
      _output_dir = "$target_out_dir/$target_name"
      _binary_path = "$target_out_dir/$_output_name"

      visibility = [ ":$_metadata_bundledata" ]
      script = "//chromium/build/config/ios/extract_metadata.py"
      sources = [
        _binary_path,
        _module_info_path,
      ]
      outputs = [
        "$_output_dir/Metadata.appintents/extract.actionsdata",
        "$_output_dir/Metadata.appintents/version.json",
      ]
      deps = [
        ":$_executable_target",
        invoker.intents_target,
      ]
      depfile = "$target_out_dir/$target_name.d"
      args = [
        "--toolchain-dir",
        rebase_path(ios_toolchains_path, root_build_dir),
        "--sdk-root",
        rebase_path(ios_sdk_path, root_build_dir),
        "--deployment-target",
        ios_deployment_target,
        "--target-cpu",
        target_cpu,
        "--target-environment",
        target_environment,
        "--depfile",
        rebase_path(depfile, root_build_dir),
        "--output",
        rebase_path(_output_dir, root_build_dir),
        "--binary-file",
        rebase_path(_binary_path, root_build_dir),
        "--module-info-path",
        rebase_path(_module_info_path, root_build_dir),
      ]

      # Starting with Xcode 15.3, appintentsmetadataprocessor requires to be
      # passed --xcode-version as parameter (with ${xcode_build} as value),
      # while previous versions did not recognize the parameter. So check
      # the version before deciding whether to set the parameter or not.
      if (xcode_version_int >= 1530) {
        args += [
          "--xcode-version",
          xcode_build,
        ]
      }
    }

    bundle_data(_metadata_bundledata) {
      public_deps = [ ":$_metadata_extraction" ]
      sources = get_target_outputs(":$_metadata_extraction")
      outputs = [ "{{bundle_resources_dir}}/" +
                  "Metadata.appintents/{{source_file_part}}" ]
    }
  }

  _generate_info_plist = target_name + "_generate_info_plist"
  ios_info_plist(_generate_info_plist) {
    forward_variables_from(invoker,
                           [
                             "info_plist",
                             "info_plist_target",
                           ])

    executable_name = _output_name

    extra_substitutions = [ "BUNDLE_IDENTIFIER=$_bundle_identifier" ]
    if (defined(invoker.extra_substitutions)) {
      extra_substitutions += invoker.extra_substitutions
    }
  }

  if (!defined(invoker.entitlements_target)) {
    _entitlements_path = "//chromium/build/config/ios/entitlements.plist"
    if (defined(invoker.entitlements_path)) {
      _entitlements_path = invoker.entitlements_path
    }
  } else {
    assert(!defined(invoker.entitlements_path),
           "Cannot define both entitlements_path and entitlements_target" +
               "for $_target_name")

    _entitlements_target_outputs =
        get_target_outputs(invoker.entitlements_target)
    _entitlements_path = _entitlements_target_outputs[0]
  }

  action(_generate_entitlements_target) {
    _gen_info_plist_outputs = get_target_outputs(":$_generate_info_plist")
    _info_plist_path = _gen_info_plist_outputs[0]

    script = "//chromium/build/config/apple/codesign.py"
    deps = [ ":$_generate_info_plist" ]
    if (defined(invoker.entitlements_target)) {
      deps += [ invoker.entitlements_target ]
    }
    sources = [
      _entitlements_path,
      _info_plist_path,
    ]
    sources += ios_mobileprovision_files

    outputs = [ _generate_entitlements_output ]

    args = [
      "generate-entitlements",
      "-e=" + rebase_path(_entitlements_path, root_build_dir),
      "-p=" + rebase_path(_info_plist_path, root_build_dir),
    ]
    foreach(mobileprovision, ios_mobileprovision_files) {
      args += [ "-m=" + rebase_path(mobileprovision, root_build_dir) ]
    }
    args += rebase_path(outputs, root_build_dir)
  }

  # Only write PkgInfo for real application, not application extension.
  if (_is_app_bundle) {
    _create_pkg_info = target_name + "_pkg_info"
    action(_create_pkg_info) {
      forward_variables_from(invoker, [ "testonly" ])
      script = "//chromium/build/apple/write_pkg_info.py"
      inputs = [ "//chromium/build/apple/plist_util.py" ]
      sources = get_target_outputs(":$_generate_info_plist")
      outputs = [
        # Cannot name the output PkgInfo as the name will not be unique if
        # multiple ios_app_bundle are defined in the same BUILD.gn file. The
        # file is renamed in the bundle_data outputs to the correct name.
        "$target_gen_dir/$target_name",
      ]
      args = [ "--plist" ] + rebase_path(sources, root_build_dir) +
             [ "--output" ] + rebase_path(outputs, root_build_dir)
      deps = [ ":$_generate_info_plist" ]
    }

    _bundle_data_pkg_info = target_name + "_bundle_data_pkg_info"
    bundle_data(_bundle_data_pkg_info) {
      forward_variables_from(invoker, [ "testonly" ])
      sources = get_target_outputs(":$_create_pkg_info")
      outputs = [ "{{bundle_resources_dir}}/PkgInfo" ]
      public_deps = [ ":$_create_pkg_info" ]
    }
  }

  foreach(_variant, _variants) {
    ios_create_signed_bundle(_variant.target_name) {
      forward_variables_from(invoker,
                             [
                               "bundle_deps",
                               "bundle_deps_filter",
                               "data_deps",
                               "deps",
                               "enable_code_signing",
                               "entitlements_path",
                               "entitlements_target",
                               "extra_system_frameworks",
                               "public_configs",
                               "public_deps",
                               "testonly",
                               "transparent",
                               "visibility",
                               "xcasset_compiler_flags",
                               "xcode_extra_attributes",
                             ])

      output_name = _output_name
      bundle_gen_dir = _variant.bundle_gen_dir
      bundle_binary_target = ":$_executable_target"
      bundle_binary_output = _output_name
      bundle_extension = _bundle_extension
      product_type = _product_type
      xcode_product_bundle_id = _bundle_identifier

      _generate_info_plist_outputs =
          get_target_outputs(":$_generate_info_plist")
      primary_info_plist = _generate_info_plist_outputs[0]
      partial_info_plist =
          "$target_gen_dir/${_variant.target_name}_partial_info.plist"

      if (!defined(deps)) {
        deps = []
      }
      deps += [ ":$_generate_info_plist" ]

      if (!defined(bundle_deps)) {
        bundle_deps = []
      }
      if (_is_app_bundle) {
        bundle_deps += [ ":$_bundle_data_pkg_info" ]
      }
      bundle_deps += _variant.bundle_deps
      if (_extract_intents_metadata) {
        bundle_deps += [ ":$_metadata_bundledata" ]
      }

      if (target_environment == "simulator") {
        if (!defined(data_deps)) {
          data_deps = []
        }
        if (build_with_chromium) {
          data_deps += [ "//testing/iossim" ]
        }
      }
    }
  }

  if (_default_variant.name != "") {
    _bundle_short_name = "$_output_name$_bundle_extension"
    action(_target_name) {
      forward_variables_from(invoker, [ "testonly" ])

      script = "//chromium/build/config/ios/hardlink.py"
      public_deps = []
      foreach(_variant, _variants) {
        public_deps += [ ":${_variant.target_name}" ]
      }

      sources = [ "${_default_variant.bundle_gen_dir}/$_bundle_short_name" ]
      outputs = [ "$root_out_dir/$_bundle_short_name" ]

      args = [
               "--output-dir",
               rebase_path(root_out_dir, root_build_dir),
               "--relative-to",
               rebase_path(_default_variant.bundle_gen_dir, root_build_dir),
             ] + rebase_path(sources, root_build_dir)
    }
  }
}

set_defaults("ios_app_bundle") {
  configs = default_executable_configs
}

# Template to build an application extension bundle for iOS.
#
# This should be used instead of "executable" built-in target type on iOS.
# As the template forward the generation of the application executable to
# an "executable" target, all arguments supported by "executable" targets
# are also supported by this template.
#
# Arguments
#
#   output_name:
#       (optional) string, name of the generated application, if omitted,
#       defaults to the target_name.
#
#   extra_substitutions:
#       (optional) list of string in "key=value" format, each value will
#       be used as an additional variable substitution rule when generating
#       the application Info.plist
#
#   info_plist:
#       (optional) string, path to the Info.plist file that will be used for
#       the bundle.
#
#   info_plist_target:
#       (optional) string, if the info_plist is generated from an action,
#       rather than a regular source file, specify the target name in lieu
#       of info_plist. The two arguments are mutually exclusive.
#
# For more information, see "gn help executable".
template("ios_appex_bundle") {
  assert(ios_is_app_extension,
         "$target_name needs to be defined in app extension toolchain context")
  ios_app_bundle(target_name) {
    forward_variables_from(invoker,
                           "*",
                           [
                             "bundle_extension",
                             "product_type",
                           ])
    product_type = apple_mobile_xcode_appex_bundle_id
  }
}

set_defaults("ios_appex_bundle") {
  configs = [ "//chromium/build/config/ios:ios_extension_executable_flags" ]
}

# Template to package a shared library into an iOS framework bundle.
#
# By default, the bundle target this template generates does not link the
# resulting framework into anything that depends on it. If a dependency wants
# a link-time (as well as build-time) dependency on the framework bundle,
# depend against "$target_name+link". If only the build-time dependency is
# required (e.g., for copying into another bundle), then use "$target_name".
#
# Arguments
#
#     output_name:
#         (optional) string, name of the generated framework without the
#         .framework suffix. If omitted, defaults to target_name.
#
#     public_headers:
#         (optional) list of paths to header file that needs to be copied
#         into the framework bundle Headers subdirectory. If omitted or
#         empty then the Headers subdirectory is not created.
#
#     sources
#         (optional) list of files. Needs to be defined and non-empty if
#         public_headers is defined and non-empty.
#
#   enable_code_signing
#       (optional) boolean, control whether code signing is enabled or not,
#       default to ios_enable_code_signing if not defined.
#
#   transparent
#       (optional) boolean, whether the bundle is "transparent"; defaults to
#       "false" if omitted; a bundle is considered "transparent" if it does
#       not package the "bundle_data" deps but forward them to all targets
#       the depend on it (unless the "bundle_data" target sets "product_type"
#       to "com.apple.product-type.framework").
#
# This template provides two targets for the resulting framework bundle. The
# link-time behavior varies depending on which of the two targets below is
# added as a dependency:
#   - $target_name only adds a build-time dependency. Targets that depend on
#     it will not link against the framework.
#   - $target_name+link adds a build-time and link-time dependency. Targets
#     that depend on it will link against the framework.
#
# The build-time-only dependency is used for when a target needs to use the
# framework either only for resources, or because the target loads it at run-
# time, via dlopen() or NSBundle. The link-time dependency will cause the
# dependee to have the framework loaded by dyld at launch.
#
# Example of build-time only dependency:
#
#     framework_bundle("CoreTeleportation") {
#       sources = [ ... ]
#     }
#
#     bundle_data("core_teleportation_bundle_data") {
#       deps = [ ":CoreTeleportation" ]
#       sources = [ "$root_out_dir/CoreTeleportation.framework" ]
#       outputs = [ "{{bundle_contents_dir}}/Frameworks/{{source_file_part}}" ]
#     }
#
#     app_bundle("GoatTeleporter") {
#       sources = [ ... ]
#       deps = [
#         ":core_teleportation_bundle_data",
#       ]
#     }
#
# The GoatTeleporter.app will not directly link against
# CoreTeleportation.framework, but it will be included in the bundle's
# Frameworks directory.
#
# Example of link-time dependency:
#
#     framework_bundle("CoreTeleportation") {
#       sources = [ ... ]
#       ldflags = [
#         "-install_name",
#         "@executable_path/../Frameworks/$target_name.framework"
#       ]
#     }
#
#     bundle_data("core_teleportation_bundle_data") {
#       deps = [ ":CoreTeleportation+link" ]
#       sources = [ "$root_out_dir/CoreTeleportation.framework" ]
#       outputs = [ "{{bundle_contents_dir}}/Frameworks/{{source_file_part}}" ]
#     }
#
#     app_bundle("GoatTeleporter") {
#       sources = [ ... ]
#       deps = [
#         ":core_teleportation_bundle_data",
#       ]
#     }
#
# Note that the framework is still copied to the app's bundle, but dyld will
# load this library when the app is launched because it uses the "+link"
# target as a dependency. This also requires that the framework set its
# install_name so that dyld can locate it.
#
# See "gn help shared_library" for more information on arguments supported
# by shared library target.
template("ios_framework_bundle") {
  _target_name = target_name
  _output_name = target_name
  if (defined(invoker.output_name)) {
    _output_name = invoker.output_name
  }

  _product_type = "com.apple.product-type.framework"
  _has_public_headers =
      defined(invoker.public_headers) && invoker.public_headers != []

  _shared_library_target = _target_name + "_shared_library"
  _link_target_name = _target_name + "+link"

  if (_has_public_headers) {
    _default_toolchain_target_gen_dir =
        get_label_info("$_target_name", "target_gen_dir")

    _framework_headers_target = _target_name + "_framework_headers"

    _headers_map_config = _target_name + "_headers_map"
    _header_map_filename =
        "$_default_toolchain_target_gen_dir/$_output_name.headers.hmap"
    config(_headers_map_config) {
      visibility = [
        ":${_shared_library_target}",
        ":${_target_name}_signed_bundle",
      ]
      include_dirs = [ _header_map_filename ]
    }
  }

  _framework_headers_config = _target_name + "_framework_headers_config"
  config(_framework_headers_config) {
    framework_dirs = [ root_out_dir ]
  }

  _framework_public_config = _target_name + "_public_config"
  config(_framework_public_config) {
    configs = [ ":$_framework_headers_config" ]
    frameworks = [ "$_output_name.framework" ]
  }

  shared_library(_shared_library_target) {
    forward_variables_from(invoker,
                           "*",
                           [
                             "bundle_deps",
                             "bundle_deps_filter",
                             "data_deps",
                             "enable_code_signing",
                             "extra_substitutions",
                             "info_plist",
                             "info_plist_target",
                             "output_name",
                             "public_configs",
                             "transparent",
                             "visibility",
                           ])

    visibility = [ ":${_target_name}_signed_bundle" ]

    if (!defined(ldflags)) {
      ldflags = []
    }
    ldflags +=
        [ "-Wl,-install_name,@rpath/$_output_name.framework/$_output_name" ]

    if (_has_public_headers) {
      configs += [ ":$_headers_map_config" ]

      if (!defined(deps)) {
        deps = []
      }
      deps += [ ":$_framework_headers_target" ]
    }

    output_extension = ""
    output_name = _output_name
    output_prefix_override = true
    output_dir = target_out_dir
  }

  if (_has_public_headers) {
    _public_headers = invoker.public_headers

    _framework_root_dir = "$root_out_dir/$_output_name.framework"
    if (target_environment == "simulator" || target_environment == "device") {
      _framework_contents_dir = _framework_root_dir
    } else if (target_environment == "catalyst") {
      _framework_contents_dir = "$_framework_root_dir/Versions/A"
    }

    _compile_headers_map_target = _target_name + "_compile_headers_map"
    action(_compile_headers_map_target) {
      visibility = [ ":$_framework_headers_target" ]
      forward_variables_from(invoker,
                             [
                               "deps",
                               "public_deps",
                               "testonly",
                             ])
      script = "//chromium/build/config/apple/write_framework_hmap.py"
      outputs = [ _header_map_filename ]

      # The header map generation only wants the list of headers, not all of
      # sources, so filter any non-header source files from "sources". It is
      # less error prone that having the developer duplicate the list of all
      # headers in addition to "sources".
      sources = []
      if (defined(invoker.sources)) {
        foreach(_source, invoker.sources) {
          if (get_path_info(_source, "extension") == "h") {
            sources += [ _source ]
          }
        }
      }

      args = [
               rebase_path(_header_map_filename, root_build_dir),
               rebase_path(_framework_root_dir, root_build_dir),
             ] + rebase_path(sources, root_build_dir)
    }

    _create_module_map_target = _target_name + "_module_map"
    action(_create_module_map_target) {
      visibility = [ ":$_framework_headers_target" ]
      script = "//chromium/build/config/apple/write_framework_modulemap.py"
      outputs = [ "$_framework_contents_dir/Modules/module.modulemap" ]
      args = [
        _output_name,
        rebase_path("$_framework_contents_dir/Modules", root_build_dir),
      ]
    }

    _copy_public_headers_target = _target_name + "_copy_public_headers"
    copy(_copy_public_headers_target) {
      forward_variables_from(invoker,
                             [
                               "testonly",
                               "deps",
                             ])
      visibility = [ ":$_framework_headers_target" ]
      sources = _public_headers
      outputs = [ "$_framework_contents_dir/Headers/{{source_file_part}}" ]

      # Do not use forward_variables_from for "public_deps" as
      # we do not want to forward those dependencies.
      if (defined(invoker.public_deps)) {
        if (!defined(deps)) {
          deps = []
        }
        deps += invoker.public_deps
      }
    }

    group(_framework_headers_target) {
      forward_variables_from(invoker, [ "testonly" ])
      deps = [
        ":$_compile_headers_map_target",
        ":$_create_module_map_target",
      ]
      public_deps = [ ":$_copy_public_headers_target" ]
    }
  }

  # Bundle identifier should respect rfc1034, so replace "_" with "-".
  _bundle_identifier =
      "$ios_app_bundle_id_prefix." + string_replace(_output_name, "_", "-")

  _info_plist_target = _target_name + "_info_plist"
  _info_plist_bundle = _target_name + "_info_plist_bundle"
  ios_info_plist(_info_plist_target) {
    visibility = [ ":$_info_plist_bundle" ]
    executable_name = _output_name
    forward_variables_from(invoker,
                           [
                             "info_plist",
                             "info_plist_target",
                           ])

    extra_substitutions = [ "BUNDLE_IDENTIFIER=$_bundle_identifier" ]
    if (defined(invoker.extra_substitutions)) {
      extra_substitutions += invoker.extra_substitutions
    }
  }

  bundle_data(_info_plist_bundle) {
    visibility = [ ":${_target_name}_signed_bundle" ]
    forward_variables_from(invoker, [ "testonly" ])
    sources = get_target_outputs(":$_info_plist_target")
    public_deps = [ ":$_info_plist_target" ]
    product_type = _product_type

    if (target_environment != "catalyst") {
      outputs = [ "{{bundle_contents_dir}}/Info.plist" ]
    } else {
      outputs = [ "{{bundle_resources_dir}}/Info.plist" ]
    }
  }

  ios_create_signed_bundle(_target_name + "_signed_bundle") {
    forward_variables_from(invoker,
                           [
                             "bundle_deps",
                             "bundle_deps_filter",
                             "data_deps",
                             "deps",
                             "enable_code_signing",
                             "public_configs",
                             "public_deps",
                             "testonly",
                             "transparent",
                             "visibility",
                           ])

    product_type = _product_type
    bundle_extension = ".framework"

    output_name = _output_name
    bundle_binary_target = ":$_shared_library_target"
    bundle_binary_output = _output_name

    has_public_headers = _has_public_headers

    # Framework do not have entitlements nor mobileprovision because they use
    # the one from the bundle using them (.app or .appex) as they are just
    # dynamic library with shared code.
    disable_entitlements = true
    disable_embedded_mobileprovision = true

    if (!defined(deps)) {
      deps = []
    }
    deps += [ ":$_info_plist_bundle" ]
  }

  group(_target_name) {
    forward_variables_from(invoker,
                           [
                             "public_configs",
                             "public_deps",
                             "testonly",
                             "visibility",
                           ])
    if (!defined(public_deps)) {
      public_deps = []
    }
    public_deps += [ ":${_target_name}_signed_bundle" ]

    if (_has_public_headers) {
      if (!defined(public_configs)) {
        public_configs = []
      }
      public_configs += [ ":$_framework_headers_config" ]
    }
  }

  group(_link_target_name) {
    forward_variables_from(invoker,
                           [
                             "public_configs",
                             "public_deps",
                             "testonly",
                             "visibility",
                           ])
    if (!defined(public_deps)) {
      public_deps = []
    }
    public_deps += [ ":$_target_name" ]

    if (!defined(all_dependent_configs)) {
      all_dependent_configs = []
    }
    all_dependent_configs += [ ":$_framework_public_config" ]
  }

  bundle_data(_target_name + "+bundle") {
    forward_variables_from(invoker,
                           [
                             "testonly",
                             "visibility",
                           ])
    public_deps = [ ":$_target_name" ]
    sources = [ "$root_out_dir/$_output_name.framework" ]
    outputs = [ "{{bundle_contents_dir}}/Frameworks/$_output_name.framework" ]
  }
}

set_defaults("ios_framework_bundle") {
  configs = default_shared_library_configs
}

# Template to build a xctest bundle that contains a loadable module for iOS.
#
# Arguments
#
#   deps:
#       list of labels to depends on, these values are used to create the
#       loadable module.
#
#   product_type
#       string, product type for the generated Xcode project, use
#       "com.apple.product-type.bundle.unit-test" for unit test and
#       "com.apple.product-type.bundle.ui-testing" for UI testing.
#
#   host_target:
#       string, name of the target that depends on the generated bundle, this
#       value is used to restrict visibilities.
#
#   xcode_test_application_name:
#       string, name of the test application for Xcode unit or ui test target.
#
#   output_name
#       (optional) string, name of the generated application, if omitted,
#       defaults to the target_name.
#
# This template defines two targets, one named "${target_name}" is the xctest
# bundle, and the other named "${target_name}_bundle" is a bundle_data that
# wraps the xctest bundle and that only the "${host_target}" can depend on.
#
template("ios_xctest_bundle") {
  assert(defined(invoker.deps), "deps must be defined for $target_name")
  assert(defined(invoker.product_type),
         "product_type must be defined for $target_name")
  assert(invoker.product_type == apple_mobile_xcode_xctest_bundle_id ||
             invoker.product_type == apple_mobile_xcode_xcuitest_bundle_id,
         "product_type defined for $target_name is invalid.")
  assert(defined(invoker.host_target),
         "host_target must be defined for $target_name")
  assert(defined(invoker.xcode_test_application_name),
         "xcode_test_application_name must be defined for $target_name")

  _target_name = target_name
  _output_name = target_name

  if (defined(invoker.output_name)) {
    _output_name = invoker.output_name
  }

  _loadable_module_target = _target_name + "_loadable_module"

  loadable_module(_loadable_module_target) {
    forward_variables_from(invoker,
                           "*",
                           [
                             "bundle_deps",
                             "bundle_deps_filter",
                             "host_target",
                             "output_dir",
                             "output_extension",
                             "output_name",
                             "output_prefix_override",
                             "product_type",
                             "testonly",
                             "visibility",
                             "xcode_test_application_name",
                             "xcode_test_application_output_name",
                             "xctest_bundle_principal_class",
                           ])

    testonly = true
    visibility = [ ":$_target_name" ]

    configs += [ "//chromium/build/config/ios:xctest_config" ]

    output_dir = target_out_dir
    output_name = _output_name
    output_prefix_override = true
    output_extension = ""
  }

  _info_plist_target = _target_name + "_info_plist"
  _info_plist_bundle = _target_name + "_info_plist_bundle"

  # Bundle identifier should respect rfc1034, so replace "_" with "-".
  _bundle_identifier = "$ios_app_bundle_id_prefix.chrome." +
                       string_replace(_output_name, "_", "-")

  ios_info_plist(_info_plist_target) {
    testonly = true
    visibility = [ ":$_info_plist_bundle" ]

    info_plist = "//chromium/build/config/ios/Module-Info.plist"
    executable_name = _output_name

    if (defined(invoker.xctest_bundle_principal_class)) {
      _principal_class = invoker.xctest_bundle_principal_class
    } else {
      # Fall back to a reasonable default value.
      _principal_class = "NSObject"
    }
    extra_substitutions = [
      "XCTEST_BUNDLE_PRINCIPAL_CLASS=${_principal_class}",
      "BUNDLE_IDENTIFIER=$_bundle_identifier",
    ]
  }

  bundle_data(_info_plist_bundle) {
    testonly = true
    visibility = [ ":$_target_name" ]

    public_deps = [ ":$_info_plist_target" ]

    sources = get_target_outputs(":$_info_plist_target")
    outputs = [ "{{bundle_contents_dir}}/Info.plist" ]
  }

  _xctest_bundle = _target_name + "_bundle"
  ios_create_signed_bundle(_target_name) {
    forward_variables_from(invoker,
                           [
                             "bundle_deps",
                             "bundle_deps_filter",
                             "bundle_id",
                             "data_deps",
                             "enable_code_signing",
                             "product_type",
                             "transparent",
                             "xcode_test_application_name",
                           ])

    testonly = true
    visibility = [ ":$_xctest_bundle" ]

    bundle_extension = ".xctest"

    output_name = _output_name
    bundle_binary_target = ":$_loadable_module_target"
    bundle_binary_output = _output_name

    xcode_extra_attributes = {
      IPHONEOS_DEPLOYMENT_TARGET = ios_deployment_target
      PRODUCT_BUNDLE_IDENTIFIER = _bundle_identifier
      CODE_SIGNING_REQUIRED = "NO"
      CODE_SIGNING_ALLOWED = "NO"
      CODE_SIGN_IDENTITY = ""
      DONT_GENERATE_INFOPLIST_FILE = "YES"

      # For XCUITest, Xcode requires specifying the host application name
      # via the TEST_TARGET_NAME attribute.
      if (invoker.product_type == apple_mobile_xcode_xcuitest_bundle_id) {
        TEST_TARGET_NAME = invoker.xcode_test_application_name
      }

      # For XCTest, Xcode requires specifying the host application path via
      # both BUNDLE_LOADER and TEST_HOST attributes.
      if (invoker.product_type == apple_mobile_xcode_xctest_bundle_id) {
        _xcode_app_name = invoker.xcode_test_application_name
        if (defined(invoker.xcode_test_application_output_name)) {
          _xcode_app_name = invoker.xcode_test_application_output_name
        }

        BUNDLE_LOADER = "\$(TEST_HOST)"
        TEST_HOST = "\$(BUILT_PRODUCTS_DIR)/" +
                    "${_xcode_app_name}.app/${_xcode_app_name}"
      }
    }

    deps = [ ":$_info_plist_bundle" ]
  }

  bundle_data(_xctest_bundle) {
    forward_variables_from(invoker, [ "host_target" ])

    testonly = true
    visibility = [ ":$host_target" ]

    public_deps = [ ":$_target_name" ]
    sources = [ "$root_out_dir/$_output_name.xctest" ]
    outputs = [ "{{bundle_contents_dir}}/PlugIns/$_output_name.xctest" ]
  }
}

set_defaults("ios_xctest_bundle") {
  configs = default_shared_library_configs
}

# For Chrome on iOS we want to run XCTests for all our build configurations
# (Debug, Release, ...). In addition, the symbols visibility is configured to
# private by default. To simplify testing with those constraints, our tests are
# compiled in the TEST_HOST target instead of the .xctest bundle.
template("ios_xctest_test") {
  _target_name = target_name
  _output_name = target_name
  if (defined(invoker.output_name)) {
    _output_name = invoker.output_name
  }

  _xctest_target = _target_name + "_module"
  _xctest_output = _output_name + "_module"

  _host_target = _target_name
  _host_output = _output_name

  # Allow invokers to specify their own target for the xctest module, but
  # fall back to a default (empty) module otherwise.
  if (defined(invoker.xctest_module_target)) {
    _xctest_module_target = invoker.xctest_module_target
  } else {
    _xctest_module_target_name = _xctest_target + "shell_source"
    _xctest_module_target = ":$_xctest_module_target_name"
    source_set(_xctest_module_target_name) {
      sources = [ "//chromium/build/config/ios/xctest_shell.mm" ]

      configs += [ "//chromium/build/config/ios:xctest_config" ]
    }
  }

  ios_xctest_bundle(_xctest_target) {
    forward_variables_from(invoker, [ "data_deps" ])
    output_name = _xctest_output
    product_type = apple_mobile_xcode_xctest_bundle_id
    host_target = _host_target

    # TODO(crbug.com/40120290) The change in output name results in a mismatch
    # between this value and the ios_app_bundle target name. To mitigate, this
    # has been modified to _host_target. output_name is set to _host_output
    # to mitigate the naming.
    xcode_test_application_name = _host_target
    xcode_test_application_output_name = _host_output

    deps = [ _xctest_module_target ]
  }

  ios_app_bundle(_host_target) {
    forward_variables_from(invoker, "*", [ "testonly" ])

    testonly = true
    output_name = _host_output
    configs += [ "//chromium/build/config/ios:xctest_config" ]

    if (!defined(invoker.info_plist) && !defined(invoker.info_plist_target)) {
      info_plist = "//chromium/build/config/ios/Host-Info.plist"
    }

    # Xcode needs the following frameworks installed in the application (and
    # signed) for the XCTest to run, so install them using
    # extra_system_frameworks.
    extra_system_frameworks = [
      "$ios_sdk_platform_path/Developer/Library/Frameworks/XCTest.framework",
      "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCTAutomationSupport.framework",
      "$ios_sdk_platform_path/Developer/usr/lib/libXCTestBundleInject.dylib",
    ]

    # Xcode 13 now depends on XCTestCore. To keep things future proof, copy over
    # everything that Xcode copies.
    if (xcode_version_int >= 1300) {
      extra_system_frameworks += [
        "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCTestCore.framework",
        "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCUnit.framework",
        "$ios_sdk_platform_path/Developer/usr/lib/libXCTestSwiftSupport.dylib",
      ]

      # Xcode 16.3 moved XCUIAutomation.framework
      if (xcode_version_int < 1630) {
        extra_system_frameworks += [ "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCUIAutomation.framework" ]
      } else {
        extra_system_frameworks += [ "$ios_sdk_platform_path/Developer/Library/Frameworks/XCUIAutomation.framework" ]
      }
    }

    # XCTestSupport framework is required as of Xcode 14.3 or later.
    if (xcode_version_int >= 1430) {
      extra_system_frameworks += [ "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCTestSupport.framework" ]
    }

    _xctest_bundle = _xctest_target + "_bundle"
    if (!defined(bundle_deps)) {
      bundle_deps = []
    }
    bundle_deps += [ ":$_xctest_bundle" ]
  }
}

set_defaults("ios_xctest_test") {
  configs = default_executable_configs
}

# Template to build a xcuitest test runner bundle.
#
# Xcode requires a test runner application with a copy of the XCTest dynamic
# library bundle in it for the XCUITest to run. The test runner bundle is created
# by copying the system bundle XCTRunner.app from Xcode SDK with the plist file
# being properly tweaked, and a xctest and it needs to be code signed in order
# to run on devices.
#
# Arguments
#
#   xctest_bundle
#       string, name of the dependent xctest bundle target.
#
#   output_name
#       (optional) string, name of the generated application, if omitted,
#       defaults to the target_name.
#
template("ios_xcuitest_test_runner_bundle") {
  assert(defined(invoker.xctest_bundle),
         "xctest_bundle must be defined for $target_name")

  _target_name = target_name
  _output_name = target_name
  if (defined(invoker.output_name)) {
    _output_name = invoker.output_name
  }

  # Bundle identifier should respect rfc1034, so replace "_" with "-".
  _bundle_identifier = "$ios_app_bundle_id_prefix.chrome." +
                       string_replace(_output_name, "_", "-")

  _xctrunner_path =
      "$ios_sdk_platform_path/Developer/Library/Xcode/Agents/XCTRunner.app"

  _info_plist_merge_plist = _target_name + "_info_plist_merge_plist"
  _info_plist_target = _target_name + "_info_plist"
  _info_plist_bundle = _target_name + "_info_plist_bundle"

  action(_info_plist_merge_plist) {
    testonly = true
    script = "//chromium/build/apple/plist_util.py"

    sources = [
      "$_xctrunner_path/Info.plist",

      # NOTE: The XCTRunnerAddition+Info.plist must come after the Info.plist
      # because it overrides the values under "CFBundleIdentifier" and
      # "CFBundleName".
      "//chromium/build/config/ios/resources/XCTRunnerAddition+Info.plist",
    ]

    _output_name = "$target_gen_dir/${_target_name}_merged.plist"
    outputs = [ _output_name ]
    args = [
             "merge",
             "-f=xml1",
             "-x=$xcode_version",
             "-o=" + rebase_path(_output_name, root_build_dir),
           ] + rebase_path(sources, root_build_dir)

    if (ios_use_xcode_symlinks) {
      deps = [ "//chromium/build/config/ios:copy_xctrunner_app" ]
    }
  }

  ios_info_plist(_info_plist_target) {
    testonly = true
    visibility = [ ":$_info_plist_bundle" ]

    executable_name = _output_name
    info_plist_target = ":$_info_plist_merge_plist"
    extra_substitutions = [ "BUNDLE_IDENTIFIER=$_bundle_identifier" ]
  }

  bundle_data(_info_plist_bundle) {
    testonly = true
    visibility = [ ":$_target_name" ]

    public_deps = [ ":$_info_plist_target" ]

    sources = get_target_outputs(":$_info_plist_target")
    outputs = [ "{{bundle_contents_dir}}/Info.plist" ]
  }

  _pkginfo_bundle = _target_name + "_pkginfo_bundle"
  bundle_data(_pkginfo_bundle) {
    testonly = true
    visibility = [ ":$_target_name" ]

    sources = [ "$_xctrunner_path/PkgInfo" ]

    outputs = [ "{{bundle_contents_dir}}/PkgInfo" ]

    if (ios_use_xcode_symlinks) {
      public_deps = [ "//chromium/build/config/ios:copy_xctrunner_app" ]
    }
  }

  _xctest_bundle = invoker.xctest_bundle
  ios_create_signed_bundle(_target_name) {
    testonly = true

    bundle_binary_target = "//chromium/build/config/ios:xctest_runner_without_arm64e"
    bundle_binary_output = "XCTRunner"
    bundle_extension = ".app"
    product_type = apple_mobile_xcode_app_bundle_id

    output_name = _output_name

    # Xcode needs the following frameworks installed in the application
    # (and signed) for the XCUITest to run, so install them using
    # extra_system_frameworks.
    extra_system_frameworks = [
      "$ios_sdk_platform_path/Developer/Library/Frameworks/XCTest.framework",
      "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCTAutomationSupport.framework",
    ]

    # Xcode 13 now depends on XCTestCore. To keep things future proof, copy over
    # everything that Xcode copies.
    if (xcode_version_int >= 1300) {
      extra_system_frameworks += [
        "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCTestCore.framework",
        "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCUnit.framework",
        "$ios_sdk_platform_path/Developer/usr/lib/libXCTestSwiftSupport.dylib",
      ]

      # Xcode 16.3 moved XCUIAutomation.framework
      if (xcode_version_int < 1630) {
        extra_system_frameworks += [ "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCUIAutomation.framework" ]
      } else {
        extra_system_frameworks += [ "$ios_sdk_platform_path/Developer/Library/Frameworks/XCUIAutomation.framework" ]
      }
    }

    # XCTestSupport framework is required as of Xcode 14.3 or later.
    if (xcode_version_int >= 1430) {
      extra_system_frameworks += [ "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCTestSupport.framework" ]
    }

    bundle_deps = []
    if (defined(invoker.bundle_deps)) {
      bundle_deps += invoker.bundle_deps
    }
    bundle_deps += [
      ":$_info_plist_bundle",
      ":$_pkginfo_bundle",
      ":$_xctest_bundle",
    ]
  }
}

# Template to build a XCUITest that consists of two parts: the test runner
# application bundle and the xctest dynamic library.
#
# Arguments
#
#   deps:
#       list of labels to depends on, these values are used to create the
#       xctest dynamic library.
#
#   xcode_test_application_name:
#       string, name of the test application for the ui test target.
#
#   runner_only_bundle_deps:
#       list of labels of bundle target to include in the runner and
#       exclude from the test module (the use case is a framework bundle
#       that is used by the test module and thus needs to be packaged in
#       the runner application bundle)
#
# This template defines two targets, one named "${target_name}_module" is the
# xctest dynamic library, and the other named "${target_name}_runner" is the
# test runner application bundle.
#
template("ios_xcuitest_test") {
  assert(defined(invoker.deps), "deps must be defined for $target_name")
  assert(defined(invoker.xcode_test_application_name),
         "xcode_test_application_name must be defined for $target_name")

  _xcuitest_target = target_name
  if (defined(invoker.output_name)) {
    _xcuitest_target = invoker.output_name
  }

  _xcuitest_runner_target = _xcuitest_target + "_runner"
  _xcuitest_module_target = _xcuitest_target + "_module"

  group(target_name) {
    testonly = true

    deps = [ ":$_xcuitest_runner_target" ]
  }

  _xcuitest_module_output = _xcuitest_target
  ios_xctest_bundle(_xcuitest_module_target) {
    forward_variables_from(invoker,
                           [
                             "bundle_deps",
                             "data_deps",
                             "deps",
                             "xcode_test_application_name",
                             "xctest_bundle_principal_class",
                           ])

    product_type = apple_mobile_xcode_xcuitest_bundle_id
    host_target = _xcuitest_runner_target
    output_name = _xcuitest_module_output

    if (defined(invoker.runner_only_bundle_deps)) {
      bundle_deps_filter = invoker.runner_only_bundle_deps
    }
  }

  _xcuitest_runner_output = _xcuitest_target + "-Runner"
  ios_xcuitest_test_runner_bundle(_xcuitest_runner_target) {
    output_name = _xcuitest_runner_output
    xctest_bundle = _xcuitest_module_target + "_bundle"

    if (defined(invoker.runner_only_bundle_deps)) {
      if (!defined(bundle_deps)) {
        bundle_deps = []
      }
      bundle_deps += invoker.runner_only_bundle_deps
    }
  }
}

set_defaults("ios_xcuitest_test") {
  configs = default_executable_configs
}

[Dauer der Verarbeitung: 0.50 Sekunden]