Source code
Revision control
Copy as Markdown
Other Tools
# 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("//chromium/build/config/apple/mobile_config.gni")
import("//chromium/build/toolchain/rbe.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 = "//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]
}
}
_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",
"xcasset_compiler_flags",
"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 = "//chromium/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 = "//chromium/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) ]
}
}
}
}