| # Copyright 2015 The Chromium Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import("//build/apple/apple_info_plist.gni") |
| import("//build/config/apple/symbols.gni") |
| import("//build/config/ios/ios_sdk.gni") |
| import("//build/toolchain/goma.gni") |
| import("//build/toolchain/toolchain.gni") |
| import("//build_overrides/build.gni") |
| |
| declare_args() { |
| # Set to true if an Xcode project is generated for this build. Set this to |
| # false if you do not plan to run `gn gen --ide=xcode` in this directory. |
| # This will speed up the generation at the cost of generating an invalid |
| # Xcode project if `gn gen --ide=xcode` is used. Defaults to true (favor |
| # correctness over speed). |
| ios_set_attributes_for_xcode_project_generation = true |
| } |
| |
| # Constants corresponding to the bundle type identifiers use application, |
| # application extension, XCTest and XCUITest targets respectively. |
| _ios_xcode_app_bundle_id = "com.apple.product-type.application" |
| _ios_xcode_appex_bundle_id = "com.apple.product-type.app-extension" |
| _ios_xcode_xctest_bundle_id = "com.apple.product-type.bundle.unit-test" |
| _ios_xcode_xcuitest_bundle_id = "com.apple.product-type.bundle.ui-testing" |
| |
| # Invokes lipo on multiple arch-specific binaries to create a fat binary. |
| # |
| # Arguments |
| # |
| # arch_binary_target |
| # name of the target generating the arch-specific binaries, they must |
| # be named $target_out_dir/$toolchain_cpu/$arch_binary_output. |
| # |
| # arch_binary_output |
| # (optional, defaults to the name of $arch_binary_target) base name of |
| # the arch-specific binary generated by arch_binary_target. |
| # |
| # output_name |
| # (optional, defaults to $target_name) base name of the target output, |
| # the full path will be $target_out_dir/$output_name. |
| # |
| # configs |
| # (optional) a list of configurations, this is used to check whether |
| # the binary should be stripped, when "enable_stripping" is true. |
| # |
| template("lipo_binary") { |
| assert(defined(invoker.arch_binary_target), |
| "arch_binary_target must be defined for $target_name") |
| |
| _target_name = target_name |
| _output_name = target_name |
| if (defined(invoker.output_name)) { |
| _output_name = invoker.output_name |
| } |
| |
| _all_target_cpu = [ current_cpu ] + additional_target_cpus |
| _all_toolchains = [ current_toolchain ] + additional_toolchains |
| |
| _arch_binary_target = invoker.arch_binary_target |
| _arch_binary_output = get_label_info(_arch_binary_target, "name") |
| if (defined(invoker.arch_binary_output)) { |
| _arch_binary_output = invoker.arch_binary_output |
| } |
| |
| action(_target_name) { |
| forward_variables_from(invoker, |
| "*", |
| [ |
| "arch_binary_output", |
| "arch_binary_target", |
| "configs", |
| "output_name", |
| ]) |
| |
| script = "//build/toolchain/apple/linker_driver.py" |
| |
| # http://crbug.com/762840. Fix for bots running out of memory. |
| pool = "//build/toolchain:link_pool($default_toolchain)" |
| |
| outputs = [ "$target_out_dir/$_output_name" ] |
| |
| deps = [] |
| _index = 0 |
| inputs = [] |
| foreach(_cpu, _all_target_cpu) { |
| _toolchain = _all_toolchains[_index] |
| _index = _index + 1 |
| |
| inputs += |
| [ get_label_info("$_arch_binary_target($_toolchain)", |
| "target_out_dir") + "/$_cpu/$_arch_binary_output" ] |
| |
| deps += [ "$_arch_binary_target($_toolchain)" ] |
| } |
| |
| args = [ |
| "xcrun", |
| "lipo", |
| "-create", |
| "-output", |
| rebase_path("$target_out_dir/$_output_name", root_build_dir), |
| ] + rebase_path(inputs, root_build_dir) |
| |
| if (enable_dsyms) { |
| _dsyms_output_dir = "$root_out_dir/$_output_name.dSYM" |
| outputs += [ |
| "$_dsyms_output_dir/", |
| "$_dsyms_output_dir/Contents/Info.plist", |
| "$_dsyms_output_dir/Contents/Resources/DWARF/$_output_name", |
| ] |
| args += [ "-Wcrl,dsym," + rebase_path("$root_out_dir/.", root_build_dir) ] |
| if (!use_xcode_clang) { |
| args += [ "-Wcrl,dsymutilpath," + |
| rebase_path("//tools/clang/dsymutil/bin/dsymutil", |
| root_build_dir) ] |
| } |
| } |
| |
| if (enable_stripping) { |
| args += [ "-Wcrl,strip,-x,-S" ] |
| if (save_unstripped_output) { |
| outputs += [ "$root_out_dir/$_output_name.unstripped" ] |
| args += [ "-Wcrl,unstripped," + |
| rebase_path("$root_out_dir/.", root_build_dir) ] |
| } |
| } |
| } |
| } |
| |
| # Wrapper around create_bundle taking care of code signature settings. |
| # |
| # Arguments |
| # |
| # product_type |
| # string, product type for the generated Xcode project. |
| # |
| # bundle_gen_dir |
| # (optional) directory where the bundle is generated; must be below |
| # root_out_dir and defaults to root_out_dir if omitted. |
| # |
| # bundle_deps |
| # (optional) list of additional dependencies. |
| # |
| # bundle_deps_filter |
| # (optional) list of dependencies to filter (for more information |
| # see "gn help bundle_deps_filter"). |
| # |
| # bundle_extension |
| # string, extension of the bundle, used to generate bundle name. |
| # |
| # bundle_binary_target |
| # (optional) string, label of the target generating the bundle main |
| # binary. This target and bundle_binary_path are mutually exclusive. |
| # |
| # bundle_binary_output |
| # (optional) string, base name of the binary generated by the |
| # bundle_binary_target target, defaults to the target name. |
| # |
| # bundle_binary_path |
| # (optional) string, path to the bundle main binary. This target and |
| # bundle_binary_target are mutually exclusive. |
| # |
| # output_name: |
| # (optional) string, name of the generated application, if omitted, |
| # defaults to the target_name. |
| # |
| # extra_system_frameworks |
| # (optional) list of system framework to copy to the bundle. |
| # |
| # enable_code_signing |
| # (optional) boolean, control whether code signing is enabled or not, |
| # default to ios_enable_code_signing if not defined. |
| # |
| # 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. |
| # |
| # has_public_headers: |
| # (optional) boolean, defaults to false; only meaningful if the bundle |
| # is a framework bundle; if true, then the frameworks includes public |
| # headers |
| # |
| # disable_entitlements |
| # (optional, defaults to false) boolean, control whether entitlements willi |
| # be embedded in the application during signature. If false and no |
| # entitlements are provided, default empty entitlements will be used. |
| # |
| # disable_embedded_mobileprovision |
| # (optional, default to false) boolean, control whether mobile provisions |
| # will be embedded in the bundle. If true, the existing |
| # embedded.mobileprovision will be deleted. |
| # |
| # xcode_extra_attributes |
| # (optional) scope, extra attributes for Xcode projects. |
| # |
| # xcode_test_application_name: |
| # (optional) string, name of the test application for Xcode unit or ui |
| # test target. |
| # |
| # xcode_product_bundle_id: |
| # (optional) string, the bundle ID that will be added in the XCode |
| # attributes to enable some features when debugging (e.g. MetricKit). |
| # |
| # primary_info_plist: |
| # (optional) path to Info.plist to merge with the $partial_info_plist |
| # generated by the compilation of the asset catalog. |
| # |
| # partial_info_plist: |
| # (optional) path to the partial Info.plist generated by the asset |
| # catalog compiler; if defined $primary_info_plist must also be defined. |
| # |
| template("create_signed_bundle") { |
| assert(defined(invoker.product_type), |
| "product_type must be defined for $target_name") |
| assert(defined(invoker.bundle_extension), |
| "bundle_extension must be defined for $target_name") |
| assert(defined(invoker.bundle_binary_target) != |
| defined(invoker.bundle_binary_path), |
| "Only one of bundle_binary_target or bundle_binary_path may be " + |
| "specified for $target_name") |
| assert(!defined(invoker.partial_info_plist) || |
| defined(invoker.primary_info_plist), |
| "primary_info_plist must be defined when partial_info_plist is " + |
| "defined for $target_name") |
| |
| if (defined(invoker.xcode_test_application_name)) { |
| assert( |
| invoker.product_type == _ios_xcode_xctest_bundle_id || |
| invoker.product_type == _ios_xcode_xcuitest_bundle_id, |
| "xcode_test_application_name can be only defined for Xcode unit or ui test target.") |
| } |
| |
| _target_name = target_name |
| _output_name = target_name |
| if (defined(invoker.output_name)) { |
| _output_name = invoker.output_name |
| } |
| |
| if (defined(invoker.bundle_binary_path)) { |
| _bundle_binary_path = invoker.bundle_binary_path |
| } else { |
| _bundle_binary_target = invoker.bundle_binary_target |
| _bundle_binary_output = get_label_info(_bundle_binary_target, "name") |
| if (defined(invoker.bundle_binary_output)) { |
| _bundle_binary_output = invoker.bundle_binary_output |
| } |
| _bundle_binary_path = |
| get_label_info(_bundle_binary_target, "target_out_dir") + |
| "/$_bundle_binary_output" |
| } |
| |
| _bundle_gen_dir = root_out_dir |
| if (defined(invoker.bundle_gen_dir)) { |
| _bundle_gen_dir = invoker.bundle_gen_dir |
| } |
| |
| _bundle_extension = invoker.bundle_extension |
| |
| _enable_embedded_mobileprovision = true |
| if (defined(invoker.disable_embedded_mobileprovision)) { |
| _enable_embedded_mobileprovision = !invoker.disable_embedded_mobileprovision |
| } |
| |
| if (target_environment == "catalyst") { |
| _enable_embedded_mobileprovision = false |
| } |
| |
| _enable_entitlements = true |
| if (defined(invoker.disable_entitlements)) { |
| _enable_entitlements = !invoker.disable_entitlements |
| } |
| |
| if (_enable_entitlements) { |
| if (!defined(invoker.entitlements_target)) { |
| _entitlements_path = "//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] |
| } |
| } |
| |
| _enable_code_signing = ios_enable_code_signing |
| if (defined(invoker.enable_code_signing)) { |
| _enable_code_signing = invoker.enable_code_signing |
| } |
| |
| if (!ios_set_attributes_for_xcode_project_generation) { |
| not_needed(invoker, |
| [ |
| "xcode_product_bundle_id", |
| "xcode_extra_attributes", |
| ]) |
| } |
| |
| create_bundle(_target_name) { |
| forward_variables_from(invoker, |
| [ |
| "bundle_deps_filter", |
| "data_deps", |
| "deps", |
| "partial_info_plist", |
| "product_type", |
| "public_configs", |
| "public_deps", |
| "testonly", |
| "visibility", |
| "xcode_test_application_name", |
| ]) |
| |
| bundle_root_dir = "$_bundle_gen_dir/$_output_name$_bundle_extension" |
| if (target_environment == "simulator" || target_environment == "device") { |
| bundle_contents_dir = bundle_root_dir |
| bundle_resources_dir = bundle_contents_dir |
| bundle_executable_dir = bundle_contents_dir |
| } else if (target_environment == "catalyst") { |
| if (_bundle_extension != ".framework") { |
| bundle_contents_dir = "$bundle_root_dir/Contents" |
| bundle_resources_dir = "$bundle_contents_dir/Resources" |
| bundle_executable_dir = "$bundle_contents_dir/MacOS" |
| } else { |
| bundle_contents_dir = "$bundle_root_dir/Versions/A" |
| bundle_resources_dir = "$bundle_contents_dir/Resources" |
| bundle_executable_dir = bundle_contents_dir |
| } |
| } |
| |
| if (!defined(public_deps)) { |
| public_deps = [] |
| } |
| |
| if (ios_set_attributes_for_xcode_project_generation) { |
| _xcode_product_bundle_id = "" |
| if (defined(invoker.xcode_product_bundle_id)) { |
| _xcode_product_bundle_id = invoker.xcode_product_bundle_id |
| } |
| |
| if (_xcode_product_bundle_id != "") { |
| _ios_provisioning_profile_info = |
| exec_script("//build/config/ios/codesign.py", |
| [ |
| "find-provisioning-profile", |
| "-b=" + _xcode_product_bundle_id, |
| ], |
| "json") |
| } |
| |
| xcode_extra_attributes = { |
| IPHONEOS_DEPLOYMENT_TARGET = ios_deployment_target |
| if (_xcode_product_bundle_id != "") { |
| CODE_SIGN_IDENTITY = "iPhone Developer" |
| DEVELOPMENT_TEAM = _ios_provisioning_profile_info.team_identifier |
| PRODUCT_BUNDLE_IDENTIFIER = _xcode_product_bundle_id |
| PROVISIONING_PROFILE_SPECIFIER = _ios_provisioning_profile_info.name |
| } |
| |
| # If invoker has defined extra attributes, they override the defaults. |
| if (defined(invoker.xcode_extra_attributes)) { |
| forward_variables_from(invoker.xcode_extra_attributes, "*") |
| } |
| } |
| } |
| |
| if (defined(invoker.bundle_binary_target)) { |
| public_deps += [ invoker.bundle_binary_target ] |
| } |
| |
| if (defined(invoker.bundle_deps)) { |
| if (!defined(deps)) { |
| deps = [] |
| } |
| deps += invoker.bundle_deps |
| } |
| if (!defined(deps)) { |
| deps = [] |
| } |
| |
| code_signing_script = "//build/config/ios/codesign.py" |
| code_signing_sources = [ _bundle_binary_path ] |
| if (_enable_entitlements) { |
| if (defined(invoker.entitlements_target)) { |
| deps += [ invoker.entitlements_target ] |
| } |
| code_signing_sources += [ _entitlements_path ] |
| } |
| code_signing_outputs = [ "$bundle_executable_dir/$_output_name" ] |
| if (_enable_code_signing) { |
| code_signing_outputs += |
| [ "$bundle_contents_dir/_CodeSignature/CodeResources" ] |
| } |
| if (ios_code_signing_identity != "" && target_environment == "device" && |
| _enable_embedded_mobileprovision) { |
| code_signing_outputs += |
| [ "$bundle_contents_dir/embedded.mobileprovision" ] |
| } |
| if (_bundle_extension == ".framework") { |
| if (target_environment == "catalyst") { |
| code_signing_outputs += [ |
| "$bundle_root_dir/Versions/Current", |
| "$bundle_root_dir/$_output_name", |
| ] |
| |
| if (defined(invoker.has_public_headers) && invoker.has_public_headers) { |
| code_signing_outputs += [ |
| "$bundle_root_dir/Headers", |
| "$bundle_root_dir/Modules", |
| ] |
| } |
| } else { |
| not_needed(invoker, [ "has_public_headers" ]) |
| } |
| } |
| |
| if (defined(invoker.extra_system_frameworks)) { |
| foreach(_framework, invoker.extra_system_frameworks) { |
| code_signing_outputs += [ "$bundle_contents_dir/Frameworks/" + |
| get_path_info(_framework, "file") ] |
| } |
| } |
| |
| code_signing_args = [ |
| "code-sign-bundle", |
| "-t=" + ios_sdk_name, |
| "-i=" + ios_code_signing_identity, |
| "-b=" + rebase_path(_bundle_binary_path, root_build_dir), |
| ] |
| if (_enable_entitlements) { |
| code_signing_args += |
| [ "-e=" + rebase_path(_entitlements_path, root_build_dir) ] |
| } |
| if (!_enable_embedded_mobileprovision) { |
| code_signing_args += [ "--disable-embedded-mobileprovision" ] |
| } |
| code_signing_args += [ rebase_path(bundle_root_dir, root_build_dir) ] |
| if (!_enable_code_signing) { |
| code_signing_args += [ "--disable-code-signature" ] |
| } |
| if (defined(invoker.extra_system_frameworks)) { |
| # All framework in extra_system_frameworks are expected to be system |
| # framework and the path to be already system absolute so do not use |
| # rebase_path here unless using Goma RBE and system Xcode (as in that |
| # case the system framework are found via a symlink in root_build_dir). |
| foreach(_framework, invoker.extra_system_frameworks) { |
| if (use_system_xcode && use_goma) { |
| _framework_path = rebase_path(_framework, root_build_dir) |
| } else { |
| _framework_path = _framework |
| } |
| code_signing_args += [ "-F=$_framework_path" ] |
| } |
| } |
| if (defined(invoker.partial_info_plist)) { |
| _partial_info_plists = [ |
| invoker.primary_info_plist, |
| invoker.partial_info_plist, |
| ] |
| |
| _plist_compiler_path = "//build/apple/plist_util.py" |
| |
| code_signing_sources += _partial_info_plists |
| code_signing_sources += [ _plist_compiler_path ] |
| if (target_environment != "catalyst" || |
| _bundle_extension != ".framework") { |
| code_signing_outputs += [ "$bundle_contents_dir/Info.plist" ] |
| } else { |
| code_signing_outputs += [ "$bundle_resources_dir/Info.plist" ] |
| } |
| |
| code_signing_args += |
| [ "-P=" + rebase_path(_plist_compiler_path, root_build_dir) ] |
| foreach(_partial_info_plist, _partial_info_plists) { |
| code_signing_args += |
| [ "-p=" + rebase_path(_partial_info_plist, root_build_dir) ] |
| } |
| } |
| } |
| } |
| |
| # Generates Info.plist files for Mac 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 = [] |
| if (defined(invoker.extra_substitutions)) { |
| extra_substitutions = invoker.extra_substitutions |
| } |
| 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", |
| ] |
| plist_templates = [ |
| "//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. |
| # |
| # xcode_product_bundle_id: |
| # (optional) string, the bundle ID that will be added in the XCode |
| # attributes to enable some features when debugging (e.g. MetricKit). |
| # defaults to "$ios_app_bundle_id_prefix.$output_name". |
| # |
| # 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 |
| } |
| |
| _primary_toolchain = current_toolchain |
| if (is_fat_secondary_toolchain) { |
| _primary_toolchain = primary_fat_toolchain_name |
| } |
| |
| assert( |
| !defined(invoker.bundle_extension), |
| "bundle_extension must not be set for ios_app_bundle template for $target_name") |
| |
| _xcode_product_bundle_id = "$ios_app_bundle_id_prefix.$_output_name" |
| if (defined(invoker.xcode_product_bundle_id)) { |
| _xcode_product_bundle_id = invoker.xcode_product_bundle_id |
| _xcode_product_bundle_id = |
| "$ios_app_bundle_id_prefix.$_xcode_product_bundle_id" |
| } else if (defined(invoker.bundle_id)) { |
| _xcode_product_bundle_id = invoker.bundle_id |
| } |
| |
| # Bundle ID should respect rfc1034 and replace _ with -. |
| _xcode_product_bundle_id = |
| string_replace("$_xcode_product_bundle_id", "_", "-") |
| |
| _arch_executable_source = _target_name + "_arch_executable_sources" |
| _arch_executable_target = _target_name + "_arch_executable" |
| _lipo_executable_target = _target_name + "_executable" |
| |
| 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] |
| |
| source_set(_arch_executable_source) { |
| 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", |
| "visibility", |
| "xcode_extra_attributes", |
| ]) |
| |
| visibility = [ ":$_arch_executable_target" ] |
| } |
| |
| if (!is_fat_secondary_toolchain || target_environment == "simulator") { |
| _generate_entitlements_target = _target_name + "_gen_entitlements" |
| _generate_entitlements_output = |
| get_label_info(":$_generate_entitlements_target($_primary_toolchain)", |
| "target_out_dir") + "/$_output_name.xcent" |
| } |
| |
| _product_type = _ios_xcode_app_bundle_id |
| if (defined(invoker.product_type)) { |
| _product_type = invoker.product_type |
| } |
| |
| if (_product_type == _ios_xcode_app_bundle_id) { |
| _bundle_extension = ".app" |
| } else if (_product_type == _ios_xcode_appex_bundle_id) { |
| _bundle_extension = ".appex" |
| } else { |
| assert(false, "unknown product_type \"$product_type\" for $_target_name") |
| } |
| |
| _is_app_bundle = _product_type == _ios_xcode_app_bundle_id |
| |
| executable(_arch_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", |
| "sources", |
| "visibility", |
| "xcode_extra_attributes", |
| ]) |
| |
| visibility = [ ":$_lipo_executable_target($_primary_toolchain)" ] |
| if (is_fat_secondary_toolchain) { |
| visibility += [ ":$_target_name" ] |
| } |
| |
| if (!defined(deps)) { |
| deps = [] |
| } |
| deps += [ ":$_arch_executable_source" ] |
| |
| if (!defined(frameworks)) { |
| frameworks = [] |
| } |
| frameworks += [ "UIKit.framework" ] |
| |
| if (target_environment == "simulator") { |
| deps += [ ":$_generate_entitlements_target($_primary_toolchain)" ] |
| |
| 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/$current_cpu" |
| } |
| |
| if (is_fat_secondary_toolchain) { |
| # For fat builds, only the default toolchain will generate an application |
| # bundle. For the other toolchains, the template is only used for building |
| # the arch-specific binary, thus the default target is just a group(). |
| |
| group(_target_name) { |
| forward_variables_from(invoker, |
| [ |
| "visibility", |
| "testonly", |
| ]) |
| public_deps = [ ":$_arch_executable_target" ] |
| } |
| } else { |
| lipo_binary(_lipo_executable_target) { |
| forward_variables_from(invoker, |
| [ |
| "configs", |
| "testonly", |
| ]) |
| |
| visibility = [] |
| foreach(_variant, _variants) { |
| visibility += [ ":${_variant.target_name}" ] |
| } |
| |
| output_name = _output_name |
| arch_binary_target = ":$_arch_executable_target" |
| arch_binary_output = _output_name |
| } |
| |
| _generate_info_plist = target_name + "_generate_info_plist" |
| ios_info_plist(_generate_info_plist) { |
| forward_variables_from(invoker, |
| [ |
| "extra_substitutions", |
| "info_plist", |
| "info_plist_target", |
| ]) |
| |
| executable_name = _output_name |
| } |
| |
| if (!is_fat_secondary_toolchain) { |
| if (!defined(invoker.entitlements_target)) { |
| _entitlements_path = "//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 = "//build/config/ios/codesign.py" |
| deps = [ ":$_generate_info_plist" ] |
| if (defined(invoker.entitlements_target)) { |
| deps += [ invoker.entitlements_target ] |
| } |
| sources = [ |
| _entitlements_path, |
| _info_plist_path, |
| ] |
| outputs = [ _generate_entitlements_output ] |
| |
| args = [ |
| "generate-entitlements", |
| "-e=" + rebase_path(_entitlements_path, root_build_dir), |
| "-p=" + rebase_path(_info_plist_path, root_build_dir), |
| ] + 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 = "//build/apple/write_pkg_info.py" |
| inputs = [ "//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) { |
| 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", |
| "visibility", |
| "xcode_extra_attributes", |
| ]) |
| |
| output_name = _output_name |
| bundle_gen_dir = _variant.bundle_gen_dir |
| bundle_binary_target = ":$_lipo_executable_target" |
| bundle_binary_output = _output_name |
| bundle_extension = _bundle_extension |
| product_type = _product_type |
| xcode_product_bundle_id = _xcode_product_bundle_id |
| |
| _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 (target_environment == "simulator") { |
| if (!defined(data_deps)) { |
| data_deps = [] |
| } |
| data_deps += [ "//testing/iossim" ] |
| } |
| } |
| } |
| |
| if (_default_variant.name != "") { |
| _bundle_short_name = "$_output_name$_bundle_extension" |
| action(_target_name) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| script = "//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 = rebase_path(sources, root_build_dir) + |
| rebase_path(outputs, root_build_dir) |
| } |
| } |
| } |
| |
| if (is_fat_secondary_toolchain) { |
| not_needed("*") |
| } |
| } |
| |
| 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") { |
| ios_app_bundle(target_name) { |
| forward_variables_from(invoker, |
| "*", |
| [ |
| "bundle_extension", |
| "product_type", |
| ]) |
| product_type = _ios_xcode_appex_bundle_id |
| } |
| } |
| |
| set_defaults("ios_appex_bundle") { |
| configs = [ "//build/config/ios:ios_extension_executable_flags" ] |
| } |
| |
| # Template to compile .xib and .storyboard files. |
| # |
| # Arguments |
| # |
| # sources: |
| # list of string, sources to compile |
| # |
| # ibtool_flags: |
| # (optional) list of string, additional flags to pass to the ibtool |
| template("compile_ib_files") { |
| action_foreach(target_name) { |
| forward_variables_from(invoker, |
| [ |
| "testonly", |
| "visibility", |
| ]) |
| assert(defined(invoker.sources), |
| "sources must be specified for $target_name") |
| assert(defined(invoker.output_extension), |
| "output_extension must be specified for $target_name") |
| |
| ibtool_flags = [] |
| if (defined(invoker.ibtool_flags)) { |
| ibtool_flags = invoker.ibtool_flags |
| } |
| |
| _output_extension = invoker.output_extension |
| |
| script = "//build/config/ios/compile_ib_files.py" |
| sources = invoker.sources |
| outputs = [ |
| "$target_gen_dir/$target_name/{{source_name_part}}.$_output_extension", |
| ] |
| args = [ |
| "--input", |
| "{{source}}", |
| "--output", |
| rebase_path( |
| "$target_gen_dir/$target_name/{{source_name_part}}.$_output_extension", |
| root_build_dir), |
| ] |
| args += ibtool_flags |
| } |
| } |
| |
| # Compile a xib or storyboard file and add it to a bundle_data so that it is |
| # available at runtime in the bundle. |
| # |
| # Arguments |
| # |
| # source: |
| # string, path of the xib or storyboard to compile. |
| # |
| # Forwards all variables to the bundle_data target. |
| template("bundle_data_ib_file") { |
| assert(defined(invoker.source), "source needs to be defined for $target_name") |
| |
| _source_extension = get_path_info(invoker.source, "extension") |
| assert(_source_extension == "xib" || _source_extension == "storyboard", |
| "source must be a .xib or .storyboard for $target_name") |
| |
| _target_name = target_name |
| if (_source_extension == "xib") { |
| _compile_ib_file = target_name + "_compile_xib" |
| _output_extension = "nib" |
| } else { |
| _compile_ib_file = target_name + "_compile_storyboard" |
| _output_extension = "storyboardc" |
| } |
| |
| compile_ib_files(_compile_ib_file) { |
| sources = [ invoker.source ] |
| output_extension = _output_extension |
| visibility = [ ":$_target_name" ] |
| ibtool_flags = [ |
| "--minimum-deployment-target", |
| ios_deployment_target, |
| "--auto-activate-custom-fonts", |
| "--target-device", |
| "iphone", |
| "--target-device", |
| "ipad", |
| ] |
| } |
| |
| bundle_data(_target_name) { |
| forward_variables_from(invoker, "*", [ "source" ]) |
| |
| if (!defined(public_deps)) { |
| public_deps = [] |
| } |
| public_deps += [ ":$_compile_ib_file" ] |
| |
| sources = get_target_outputs(":$_compile_ib_file") |
| |
| outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ] |
| } |
| } |
| |
| # Compile a strings file and add it to a bundle_data so that it is available |
| # at runtime in the bundle. |
| # |
| # Arguments |
| # |
| # source: |
| # string, path of the strings file to compile. |
| # |
| # output: |
| # string, path of the compiled file in the final bundle. |
| # |
| # Forwards all variables to the bundle_data target. |
| template("bundle_data_strings") { |
| assert(defined(invoker.source), "source needs to be defined for $target_name") |
| assert(defined(invoker.output), "output needs to be defined for $target_name") |
| |
| _source_extension = get_path_info(invoker.source, "extension") |
| assert(_source_extension == "strings", |
| "source must be a .strings for $target_name") |
| |
| _target_name = target_name |
| _convert_target = target_name + "_compile_strings" |
| |
| convert_plist(_convert_target) { |
| visibility = [ ":$_target_name" ] |
| source = invoker.source |
| output = |
| "$target_gen_dir/$_target_name/" + get_path_info(invoker.source, "file") |
| format = "binary1" |
| } |
| |
| bundle_data(_target_name) { |
| forward_variables_from(invoker, |
| "*", |
| [ |
| "source", |
| "output", |
| ]) |
| |
| if (!defined(public_deps)) { |
| public_deps = [] |
| } |
| public_deps += [ ":$_convert_target" ] |
| |
| sources = get_target_outputs(":$_convert_target") |
| |
| outputs = [ invoker.output ] |
| } |
| } |
| |
| # 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. |
| # |
| # 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 |
| } |
| |
| _has_public_headers = |
| defined(invoker.public_headers) && invoker.public_headers != [] |
| |
| _primary_toolchain = current_toolchain |
| if (is_fat_secondary_toolchain) { |
| _primary_toolchain = primary_fat_toolchain_name |
| } |
| |
| # Public configs are not propagated across toolchain (see crbug.com/675224) |
| # so some configs have to be defined for both default_toolchain and all others |
| # toolchains when performing a fat build. Use "get_label_info" to construct |
| # the path since they need to be relative to the default_toolchain. |
| |
| _default_toolchain_root_out_dir = |
| get_label_info("$_target_name($_primary_toolchain)", "root_out_dir") |
| |
| _arch_shared_library_source = _target_name + "_arch_shared_library_sources" |
| _arch_shared_library_target = _target_name + "_arch_shared_library" |
| _lipo_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($_primary_toolchain)", "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 = [ |
| ":${_arch_shared_library_source}", |
| ":${_target_name}_signed_bundle", |
| ] |
| include_dirs = [ _header_map_filename ] |
| } |
| } |
| |
| _framework_headers_config = _target_name + "_framework_headers_config" |
| config(_framework_headers_config) { |
| framework_dirs = [ _default_toolchain_root_out_dir ] |
| } |
| |
| _framework_public_config = _target_name + "_public_config" |
| config(_framework_public_config) { |
| configs = [ ":$_framework_headers_config" ] |
| frameworks = [ "$_output_name.framework" ] |
| } |
| |
| source_set(_arch_shared_library_source) { |
| 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", |
| "visibility", |
| ]) |
| |
| visibility = [ ":$_arch_shared_library_target" ] |
| |
| if (_has_public_headers) { |
| configs += [ ":$_headers_map_config" ] |
| |
| if (!defined(deps)) { |
| deps = [] |
| } |
| deps += [ ":$_framework_headers_target($_primary_toolchain)" ] |
| } |
| } |
| |
| shared_library(_arch_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", |
| "sources", |
| "public_configs", |
| "visibility", |
| ]) |
| |
| visibility = [ ":$_lipo_shared_library_target($_primary_toolchain)" ] |
| if (is_fat_secondary_toolchain) { |
| visibility += [ |
| ":${_target_name}", |
| ":${_target_name}_signed_bundle", |
| ] |
| } |
| |
| if (!defined(deps)) { |
| deps = [] |
| } |
| deps += [ ":$_arch_shared_library_source" ] |
| if (_has_public_headers) { |
| deps += [ ":$_framework_headers_target($_primary_toolchain)" ] |
| } |
| if (!defined(ldflags)) { |
| ldflags = [] |
| } |
| ldflags += |
| [ "-Wl,-install_name,@rpath/$_output_name.framework/$_output_name" ] |
| |
| output_extension = "" |
| output_name = _output_name |
| output_prefix_override = true |
| output_dir = "$target_out_dir/$current_cpu" |
| } |
| |
| if (is_fat_secondary_toolchain) { |
| # For fat builds, only the default toolchain will generate a framework |
| # bundle. For the other toolchains, the template is only used for building |
| # the arch-specific binary, thus the default target is just a group(). |
| |
| group(_target_name) { |
| forward_variables_from(invoker, |
| [ |
| "visibility", |
| "testonly", |
| ]) |
| public_deps = [ ":$_arch_shared_library_target" ] |
| } |
| |
| group(_link_target_name) { |
| forward_variables_from(invoker, |
| [ |
| "public_configs", |
| "visibility", |
| "testonly", |
| ]) |
| public_deps = [ ":$_link_target_name($_primary_toolchain)" ] |
| |
| if (_has_public_headers) { |
| if (!defined(public_configs)) { |
| public_configs = [] |
| } |
| public_configs += [ ":$_framework_headers_config" ] |
| } |
| if (!defined(all_dependent_configs)) { |
| all_dependent_configs = [] |
| } |
| all_dependent_configs += [ ":$_framework_public_config" ] |
| } |
| |
| group("$_target_name+bundle") { |
| forward_variables_from(invoker, [ "testonly" ]) |
| public_deps = [ ":$_target_name+bundle($_primary_toolchain)" ] |
| } |
| |
| not_needed(invoker, "*") |
| } else { |
| 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 = "//build/config/ios/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 = [] |
| foreach(_source, invoker.sources) { |
| if (get_path_info(_source, "extension") == "h") { |
| sources += [ _source ] |
| } |
| } |
| |
| args = [ |
| rebase_path(_header_map_filename), |
| 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 = "//build/config/ios/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" ] |
| } |
| } |
| |
| lipo_binary(_lipo_shared_library_target) { |
| forward_variables_from(invoker, |
| [ |
| "configs", |
| "testonly", |
| ]) |
| |
| visibility = [ ":${_target_name}_signed_bundle" ] |
| output_name = _output_name |
| arch_binary_target = ":$_arch_shared_library_target" |
| arch_binary_output = _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, |
| [ |
| "extra_substitutions", |
| "info_plist", |
| "info_plist_target", |
| ]) |
| } |
| |
| 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" ] |
| |
| if (target_environment != "catalyst") { |
| outputs = [ "{{bundle_contents_dir}}/Info.plist" ] |
| } else { |
| outputs = [ "{{bundle_resources_dir}}/Info.plist" ] |
| } |
| } |
| |
| 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", |
| "visibility", |
| ]) |
| |
| product_type = "com.apple.product-type.framework" |
| bundle_extension = ".framework" |
| |
| output_name = _output_name |
| bundle_binary_target = ":$_lipo_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 == _ios_xcode_xctest_bundle_id || |
| invoker.product_type == _ios_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") |
| |
| # Silence "assignment had no effect" error for non-default toolchains as |
| # following variables are only used in the expansion of the template for the |
| # default toolchain. |
| if (is_fat_secondary_toolchain) { |
| not_needed(invoker, "*") |
| } |
| |
| _target_name = target_name |
| _output_name = target_name |
| |
| if (defined(invoker.output_name)) { |
| _output_name = invoker.output_name |
| } |
| |
| _arch_loadable_module_source = _target_name + "_arch_loadable_module_source" |
| _arch_loadable_module_target = _target_name + "_arch_loadable_module" |
| _lipo_loadable_module_target = _target_name + "_loadable_module" |
| |
| _primary_toolchain = current_toolchain |
| if (is_fat_secondary_toolchain) { |
| _primary_toolchain = primary_fat_toolchain_name |
| } |
| |
| source_set(_arch_loadable_module_source) { |
| forward_variables_from(invoker, [ "deps" ]) |
| |
| testonly = true |
| visibility = [ ":$_arch_loadable_module_target" ] |
| } |
| |
| loadable_module(_arch_loadable_module_target) { |
| testonly = true |
| visibility = [ ":$_lipo_loadable_module_target($_primary_toolchain)" ] |
| if (is_fat_secondary_toolchain) { |
| visibility += [ ":$_target_name" ] |
| } |
| |
| deps = [ ":$_arch_loadable_module_source" ] |
| configs += [ "//build/config/ios:xctest_config" ] |
| |
| output_dir = "$target_out_dir/$current_cpu" |
| output_name = _output_name |
| output_prefix_override = true |
| output_extension = "" |
| } |
| |
| if (is_fat_secondary_toolchain) { |
| # For fat builds, only the default toolchain will generate a test bundle. |
| # For the other toolchains, the template is only used for building the |
| # arch-specific binary, thus the default target is just a group(). |
| group(_target_name) { |
| forward_variables_from(invoker, [ "visibility" ]) |
| testonly = true |
| |
| public_deps = [ ":$_arch_loadable_module_target" ] |
| } |
| |
| not_needed(invoker, "*") |
| } else { |
| _info_plist_target = _target_name + "_info_plist" |
| _info_plist_bundle = _target_name + "_info_plist_bundle" |
| |
| ios_info_plist(_info_plist_target) { |
| testonly = true |
| visibility = [ ":$_info_plist_bundle" ] |
| |
| info_plist = "//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}", |
| "MODULE_BUNDLE_ID=gtest.$_output_name", |
| ] |
| } |
| |
| 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" ] |
| } |
| |
| lipo_binary(_lipo_loadable_module_target) { |
| forward_variables_from(invoker, [ "configs" ]) |
| |
| testonly = true |
| visibility = [ ":$_target_name" ] |
| |
| output_name = _output_name |
| arch_binary_target = ":$_arch_loadable_module_target" |
| arch_binary_output = _output_name |
| } |
| |
| _xctest_bundle = _target_name + "_bundle" |
| create_signed_bundle(_target_name) { |
| forward_variables_from(invoker, |
| [ |
| "bundle_id", |
| "data_deps", |
| "enable_code_signing", |
| "product_type", |
| "xcode_test_application_name", |
| ]) |
| |
| testonly = true |
| visibility = [ ":$_xctest_bundle" ] |
| |
| bundle_extension = ".xctest" |
| |
| output_name = _output_name |
| bundle_binary_target = ":$_lipo_loadable_module_target" |
| bundle_binary_output = _output_name |
| |
| if (ios_set_attributes_for_xcode_project_generation) { |
| _xcode_product_bundle_id = |
| "$ios_app_bundle_id_prefix.gtest.$_output_name" |
| |
| _ios_provisioning_profile_info = |
| exec_script("//build/config/ios/codesign.py", |
| [ |
| "find-provisioning-profile", |
| "-b=" + _xcode_product_bundle_id, |
| ], |
| "json") |
| |
| xcode_extra_attributes = { |
| IPHONEOS_DEPLOYMENT_TARGET = ios_deployment_target |
| CODE_SIGN_IDENTITY = "iPhone Developer" |
| DEVELOPMENT_TEAM = _ios_provisioning_profile_info.team_identifier |
| PRODUCT_BUNDLE_IDENTIFIER = _xcode_product_bundle_id |
| PROVISIONING_PROFILE_SPECIFIER = _ios_provisioning_profile_info.name |
| |
| # For XCUITest, Xcode requires specifying the host application name |
| # via the TEST_TARGET_NAME attribute. |
| if (invoker.product_type == _ios_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 == _ios_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}" |
| } |
| } |
| } else { |
| not_needed(invoker, |
| [ |
| "xcode_test_application_name", |
| "xcode_test_application_output_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 = [ "//build/config/ios/xctest_shell.mm" ] |
| |
| configs += [ "//build/config/ios:xctest_config" ] |
| } |
| } |
| |
| ios_xctest_bundle(_xctest_target) { |
| forward_variables_from(invoker, [ "data_deps" ]) |
| output_name = _xctest_output |
| product_type = _ios_xcode_xctest_bundle_id |
| host_target = _host_target |
| |
| # TODO(crbug.com/1056328) 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 += [ "//build/config/ios:xctest_config" ] |
| |
| if (!defined(invoker.info_plist) && !defined(invoker.info_plist_target)) { |
| info_plist = "//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", |
| ] |
| |
| _xctest_bundle = _xctest_target + "_bundle" |
| if (!is_fat_secondary_toolchain) { |
| 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 |
| } |
| |
| _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 = "//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". |
| "//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 (use_system_xcode && use_goma) { |
| deps = [ "//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" |
| } |
| |
| 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 (use_system_xcode && use_goma) { |
| public_deps = [ "//build/config/ios:copy_xctrunner_app" ] |
| } |
| } |
| |
| _xctest_bundle = invoker.xctest_bundle |
| create_signed_bundle(_target_name) { |
| testonly = true |
| |
| bundle_binary_target = "//build/config/ios:xctest_runner_without_arm64e" |
| bundle_binary_output = "XCTRunner" |
| bundle_extension = ".app" |
| product_type = _ios_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", |
| ] |
| |
| 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. |
| # |
| # 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, |
| [ |
| "xcode_test_application_name", |
| "xctest_bundle_principal_class", |
| "data_deps", |
| ]) |
| |
| product_type = _ios_xcode_xcuitest_bundle_id |
| host_target = _xcuitest_runner_target |
| output_name = _xcuitest_module_output |
| |
| deps = invoker.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" |
| forward_variables_from(invoker, [ "bundle_deps" ]) |
| } |
| } |
| |
| set_defaults("ios_xcuitest_test") { |
| configs = default_executable_configs |
| } |