# Copyright 2024 The Chromium Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. import("//build/config/apple/mobile_config.gni") import("//build_overrides/build.gni") # Constants corresponding to the bundle type identifiers use application, # application extension, XCTest and XCUITest targets respectively. apple_mobile_xcode_app_bundle_id = "com.apple.product-type.application" apple_mobile_xcode_appex_bundle_id = "com.apple.product-type.app-extension" apple_mobile_xcode_xctest_bundle_id = "com.apple.product-type.bundle.unit-test" apple_mobile_xcode_xcuitest_bundle_id = "com.apple.product-type.bundle.ui-testing" # Wrapper around create_bundle taking care of code signature settings. # # Arguments # # product_type # string, product type for the generated Xcode project. # # platform_sdk_name # string, the name of the platform SDK # # 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. # # 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 "create_signed_bundle" target). # template("apple_mobile_create_signed_bundle") { assert(defined(invoker.product_type), "product_type must be defined for $target_name") assert(defined(invoker.platform_sdk_name), "platform_sdk_name 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 == apple_mobile_xcode_xctest_bundle_id || invoker.product_type == apple_mobile_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 } create_bundle(_target_name) { forward_variables_from(invoker, [ "bundle_deps_filter", "data_deps", "deps", "partial_info_plist", "product_type", "public_configs", "public_deps", "testonly", "transparent", "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 = [] } _bundle_identifier = "" if (defined(invoker.xcode_product_bundle_id)) { _bundle_identifier = invoker.xcode_product_bundle_id assert(_bundle_identifier == string_replace(_bundle_identifier, "_", "-"), "$target_name: bundle_identifier does not respect rfc1034: " + _bundle_identifier) } xcode_extra_attributes = { PRODUCT_BUNDLE_IDENTIFIER = _bundle_identifier CODE_SIGNING_REQUIRED = "NO" CODE_SIGNING_ALLOWED = "NO" CODE_SIGN_IDENTITY = "" DONT_GENERATE_INFOPLIST_FILE = "YES" # 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 = [] } post_processing_script = "//build/config/apple/codesign.py" post_processing_sources = [ _bundle_binary_path ] if (_enable_entitlements) { if (defined(invoker.entitlements_target)) { deps += [ invoker.entitlements_target ] } post_processing_sources += [ _entitlements_path ] } post_processing_outputs = [ "$bundle_executable_dir/$_output_name" ] if (_enable_code_signing) { post_processing_outputs += [ "$bundle_contents_dir/_CodeSignature/CodeResources" ] } if (ios_code_signing_identity != "" && target_environment == "device" && _enable_embedded_mobileprovision) { post_processing_outputs += [ "$bundle_contents_dir/embedded.mobileprovision" ] } if (_bundle_extension == ".framework") { if (target_environment == "catalyst") { post_processing_outputs += [ "$bundle_root_dir/Versions/Current", "$bundle_root_dir/$_output_name", ] if (defined(invoker.has_public_headers) && invoker.has_public_headers) { post_processing_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) { post_processing_outputs += [ "$bundle_contents_dir/Frameworks/" + get_path_info(_framework, "file") ] } } post_processing_args = [ "code-sign-bundle", "-t=" + invoker.platform_sdk_name, "-i=" + ios_code_signing_identity, "-b=" + rebase_path(_bundle_binary_path, root_build_dir), ] foreach(mobileprovision, ios_mobileprovision_files) { post_processing_args += [ "-m=" + rebase_path(mobileprovision, root_build_dir) ] } post_processing_sources += ios_mobileprovision_files if (_enable_entitlements) { post_processing_args += [ "-e=" + rebase_path(_entitlements_path, root_build_dir) ] } if (!_enable_embedded_mobileprovision) { post_processing_args += [ "--disable-embedded-mobileprovision" ] } post_processing_args += [ rebase_path(bundle_root_dir, root_build_dir) ] if (!_enable_code_signing) { post_processing_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 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_remoteexec) { _framework_path = rebase_path(_framework, root_build_dir) } else { _framework_path = _framework } post_processing_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" post_processing_sources += _partial_info_plists post_processing_sources += [ _plist_compiler_path ] if (target_environment != "catalyst" || _bundle_extension != ".framework") { post_processing_outputs += [ "$bundle_contents_dir/Info.plist" ] } else { post_processing_outputs += [ "$bundle_resources_dir/Info.plist" ] } post_processing_args += [ "-P=" + rebase_path(_plist_compiler_path, root_build_dir) ] foreach(_partial_info_plist, _partial_info_plists) { post_processing_args += [ "-p=" + rebase_path(_partial_info_plist, root_build_dir) ] } } } }