1# Copyright 2024 The Chromium Authors 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import("//build/config/apple/mobile_config.gni") 6import("//build_overrides/build.gni") 7 8# Constants corresponding to the bundle type identifiers use application, 9# application extension, XCTest and XCUITest targets respectively. 10apple_mobile_xcode_app_bundle_id = "com.apple.product-type.application" 11apple_mobile_xcode_appex_bundle_id = "com.apple.product-type.app-extension" 12apple_mobile_xcode_xctest_bundle_id = "com.apple.product-type.bundle.unit-test" 13apple_mobile_xcode_xcuitest_bundle_id = 14 "com.apple.product-type.bundle.ui-testing" 15 16# Wrapper around create_bundle taking care of code signature settings. 17# 18# Arguments 19# 20# product_type 21# string, product type for the generated Xcode project. 22# 23# platform_sdk_name 24# string, the name of the platform SDK 25# 26# bundle_gen_dir 27# (optional) directory where the bundle is generated; must be below 28# root_out_dir and defaults to root_out_dir if omitted. 29# 30# bundle_deps 31# (optional) list of additional dependencies. 32# 33# bundle_deps_filter 34# (optional) list of dependencies to filter (for more information 35# see "gn help bundle_deps_filter"). 36# 37# bundle_extension 38# string, extension of the bundle, used to generate bundle name. 39# 40# bundle_binary_target 41# (optional) string, label of the target generating the bundle main 42# binary. This target and bundle_binary_path are mutually exclusive. 43# 44# bundle_binary_output 45# (optional) string, base name of the binary generated by the 46# bundle_binary_target target, defaults to the target name. 47# 48# bundle_binary_path 49# (optional) string, path to the bundle main binary. This target and 50# bundle_binary_target are mutually exclusive. 51# 52# output_name: 53# (optional) string, name of the generated application, if omitted, 54# defaults to the target_name. 55# 56# extra_system_frameworks 57# (optional) list of system framework to copy to the bundle. 58# 59# enable_code_signing 60# (optional) boolean, control whether code signing is enabled or not, 61# default to ios_enable_code_signing if not defined. 62# 63# entitlements_path: 64# (optional) path to the template to use to generate the application 65# entitlements by performing variable substitutions, defaults to 66# //build/config/ios/entitlements.plist. 67# 68# entitlements_target: 69# (optional) label of the target generating the application 70# entitlements (must generate a single file as output); cannot be 71# defined if entitlements_path is set. 72# 73# has_public_headers: 74# (optional) boolean, defaults to false; only meaningful if the bundle 75# is a framework bundle; if true, then the frameworks includes public 76# headers 77# 78# disable_entitlements 79# (optional, defaults to false) boolean, control whether entitlements willi 80# be embedded in the application during signature. If false and no 81# entitlements are provided, default empty entitlements will be used. 82# 83# disable_embedded_mobileprovision 84# (optional, default to false) boolean, control whether mobile provisions 85# will be embedded in the bundle. If true, the existing 86# embedded.mobileprovision will be deleted. 87# 88# xcode_extra_attributes 89# (optional) scope, extra attributes for Xcode projects. 90# 91# xcode_test_application_name: 92# (optional) string, name of the test application for Xcode unit or ui 93# test target. 94# 95# xcode_product_bundle_id: 96# (optional) string, the bundle ID that will be added in the XCode 97# attributes to enable some features when debugging (e.g. MetricKit). 98# 99# primary_info_plist: 100# (optional) path to Info.plist to merge with the $partial_info_plist 101# generated by the compilation of the asset catalog. 102# 103# partial_info_plist: 104# (optional) path to the partial Info.plist generated by the asset 105# catalog compiler; if defined $primary_info_plist must also be defined. 106# 107# transparent 108# (optional) boolean, whether the bundle is "transparent"; defaults to 109# "false" if omitted; a bundle is considered "transparent" if it does 110# not package the "bundle_data" deps but forward them to all targets 111# the depend on it (unless the "bundle_data" target sets "product_type" 112# to the same value as the "create_signed_bundle" target). 113# 114template("apple_mobile_create_signed_bundle") { 115 assert(defined(invoker.product_type), 116 "product_type must be defined for $target_name") 117 assert(defined(invoker.platform_sdk_name), 118 "platform_sdk_name must be defined for $target_name") 119 assert(defined(invoker.bundle_extension), 120 "bundle_extension must be defined for $target_name") 121 assert(defined(invoker.bundle_binary_target) != 122 defined(invoker.bundle_binary_path), 123 "Only one of bundle_binary_target or bundle_binary_path may be " + 124 "specified for $target_name") 125 assert(!defined(invoker.partial_info_plist) || 126 defined(invoker.primary_info_plist), 127 "primary_info_plist must be defined when partial_info_plist is " + 128 "defined for $target_name") 129 130 if (defined(invoker.xcode_test_application_name)) { 131 assert( 132 invoker.product_type == apple_mobile_xcode_xctest_bundle_id || 133 invoker.product_type == apple_mobile_xcode_xcuitest_bundle_id, 134 "xcode_test_application_name can be only defined for Xcode unit or ui test target.") 135 } 136 137 _target_name = target_name 138 _output_name = target_name 139 if (defined(invoker.output_name)) { 140 _output_name = invoker.output_name 141 } 142 143 if (defined(invoker.bundle_binary_path)) { 144 _bundle_binary_path = invoker.bundle_binary_path 145 } else { 146 _bundle_binary_target = invoker.bundle_binary_target 147 _bundle_binary_output = get_label_info(_bundle_binary_target, "name") 148 if (defined(invoker.bundle_binary_output)) { 149 _bundle_binary_output = invoker.bundle_binary_output 150 } 151 _bundle_binary_path = 152 get_label_info(_bundle_binary_target, "target_out_dir") + 153 "/$_bundle_binary_output" 154 } 155 156 _bundle_gen_dir = root_out_dir 157 if (defined(invoker.bundle_gen_dir)) { 158 _bundle_gen_dir = invoker.bundle_gen_dir 159 } 160 161 _bundle_extension = invoker.bundle_extension 162 163 _enable_embedded_mobileprovision = true 164 if (defined(invoker.disable_embedded_mobileprovision)) { 165 _enable_embedded_mobileprovision = !invoker.disable_embedded_mobileprovision 166 } 167 168 if (target_environment == "catalyst") { 169 _enable_embedded_mobileprovision = false 170 } 171 172 _enable_entitlements = true 173 if (defined(invoker.disable_entitlements)) { 174 _enable_entitlements = !invoker.disable_entitlements 175 } 176 177 if (_enable_entitlements) { 178 if (!defined(invoker.entitlements_target)) { 179 _entitlements_path = "//build/config/ios/entitlements.plist" 180 if (defined(invoker.entitlements_path)) { 181 _entitlements_path = invoker.entitlements_path 182 } 183 } else { 184 assert(!defined(invoker.entitlements_path), 185 "Cannot define both entitlements_path and entitlements_target " + 186 "for $target_name") 187 188 _entitlements_target_outputs = 189 get_target_outputs(invoker.entitlements_target) 190 _entitlements_path = _entitlements_target_outputs[0] 191 } 192 } 193 194 _enable_code_signing = ios_enable_code_signing 195 if (defined(invoker.enable_code_signing)) { 196 _enable_code_signing = invoker.enable_code_signing 197 } 198 199 create_bundle(_target_name) { 200 forward_variables_from(invoker, 201 [ 202 "bundle_deps_filter", 203 "data_deps", 204 "deps", 205 "partial_info_plist", 206 "product_type", 207 "public_configs", 208 "public_deps", 209 "testonly", 210 "transparent", 211 "visibility", 212 "xcode_test_application_name", 213 ]) 214 215 bundle_root_dir = "$_bundle_gen_dir/$_output_name$_bundle_extension" 216 if (target_environment == "simulator" || target_environment == "device") { 217 bundle_contents_dir = bundle_root_dir 218 bundle_resources_dir = bundle_contents_dir 219 bundle_executable_dir = bundle_contents_dir 220 } else if (target_environment == "catalyst") { 221 if (_bundle_extension != ".framework") { 222 bundle_contents_dir = "$bundle_root_dir/Contents" 223 bundle_resources_dir = "$bundle_contents_dir/Resources" 224 bundle_executable_dir = "$bundle_contents_dir/MacOS" 225 } else { 226 bundle_contents_dir = "$bundle_root_dir/Versions/A" 227 bundle_resources_dir = "$bundle_contents_dir/Resources" 228 bundle_executable_dir = bundle_contents_dir 229 } 230 } 231 232 if (!defined(public_deps)) { 233 public_deps = [] 234 } 235 236 _bundle_identifier = "" 237 if (defined(invoker.xcode_product_bundle_id)) { 238 _bundle_identifier = invoker.xcode_product_bundle_id 239 assert(_bundle_identifier == string_replace(_bundle_identifier, "_", "-"), 240 "$target_name: bundle_identifier does not respect rfc1034: " + 241 _bundle_identifier) 242 } 243 244 xcode_extra_attributes = { 245 PRODUCT_BUNDLE_IDENTIFIER = _bundle_identifier 246 CODE_SIGNING_REQUIRED = "NO" 247 CODE_SIGNING_ALLOWED = "NO" 248 CODE_SIGN_IDENTITY = "" 249 DONT_GENERATE_INFOPLIST_FILE = "YES" 250 251 # If invoker has defined extra attributes, they override the defaults. 252 if (defined(invoker.xcode_extra_attributes)) { 253 forward_variables_from(invoker.xcode_extra_attributes, "*") 254 } 255 } 256 257 if (defined(invoker.bundle_binary_target)) { 258 public_deps += [ invoker.bundle_binary_target ] 259 } 260 261 if (defined(invoker.bundle_deps)) { 262 if (!defined(deps)) { 263 deps = [] 264 } 265 deps += invoker.bundle_deps 266 } 267 if (!defined(deps)) { 268 deps = [] 269 } 270 271 post_processing_script = "//build/config/apple/codesign.py" 272 post_processing_sources = [ _bundle_binary_path ] 273 if (_enable_entitlements) { 274 if (defined(invoker.entitlements_target)) { 275 deps += [ invoker.entitlements_target ] 276 } 277 post_processing_sources += [ _entitlements_path ] 278 } 279 post_processing_outputs = [ "$bundle_executable_dir/$_output_name" ] 280 if (_enable_code_signing) { 281 post_processing_outputs += 282 [ "$bundle_contents_dir/_CodeSignature/CodeResources" ] 283 } 284 if (ios_code_signing_identity != "" && target_environment == "device" && 285 _enable_embedded_mobileprovision) { 286 post_processing_outputs += 287 [ "$bundle_contents_dir/embedded.mobileprovision" ] 288 } 289 if (_bundle_extension == ".framework") { 290 if (target_environment == "catalyst") { 291 post_processing_outputs += [ 292 "$bundle_root_dir/Versions/Current", 293 "$bundle_root_dir/$_output_name", 294 ] 295 296 if (defined(invoker.has_public_headers) && invoker.has_public_headers) { 297 post_processing_outputs += [ 298 "$bundle_root_dir/Headers", 299 "$bundle_root_dir/Modules", 300 ] 301 } 302 } else { 303 not_needed(invoker, [ "has_public_headers" ]) 304 } 305 } 306 307 if (defined(invoker.extra_system_frameworks)) { 308 foreach(_framework, invoker.extra_system_frameworks) { 309 post_processing_outputs += [ "$bundle_contents_dir/Frameworks/" + 310 get_path_info(_framework, "file") ] 311 } 312 } 313 314 post_processing_args = [ 315 "code-sign-bundle", 316 "-t=" + invoker.platform_sdk_name, 317 "-i=" + ios_code_signing_identity, 318 "-b=" + rebase_path(_bundle_binary_path, root_build_dir), 319 ] 320 foreach(mobileprovision, ios_mobileprovision_files) { 321 post_processing_args += 322 [ "-m=" + rebase_path(mobileprovision, root_build_dir) ] 323 } 324 post_processing_sources += ios_mobileprovision_files 325 if (_enable_entitlements) { 326 post_processing_args += 327 [ "-e=" + rebase_path(_entitlements_path, root_build_dir) ] 328 } 329 if (!_enable_embedded_mobileprovision) { 330 post_processing_args += [ "--disable-embedded-mobileprovision" ] 331 } 332 post_processing_args += [ rebase_path(bundle_root_dir, root_build_dir) ] 333 if (!_enable_code_signing) { 334 post_processing_args += [ "--disable-code-signature" ] 335 } 336 if (defined(invoker.extra_system_frameworks)) { 337 # All framework in extra_system_frameworks are expected to be system 338 # framework and the path to be already system absolute so do not use 339 # rebase_path here unless using RBE and system Xcode (as in that 340 # case the system framework are found via a symlink in root_build_dir). 341 foreach(_framework, invoker.extra_system_frameworks) { 342 if (use_system_xcode && use_remoteexec) { 343 _framework_path = rebase_path(_framework, root_build_dir) 344 } else { 345 _framework_path = _framework 346 } 347 post_processing_args += [ "-F=$_framework_path" ] 348 } 349 } 350 if (defined(invoker.partial_info_plist)) { 351 _partial_info_plists = [ 352 invoker.primary_info_plist, 353 invoker.partial_info_plist, 354 ] 355 356 _plist_compiler_path = "//build/apple/plist_util.py" 357 358 post_processing_sources += _partial_info_plists 359 post_processing_sources += [ _plist_compiler_path ] 360 if (target_environment != "catalyst" || 361 _bundle_extension != ".framework") { 362 post_processing_outputs += [ "$bundle_contents_dir/Info.plist" ] 363 } else { 364 post_processing_outputs += [ "$bundle_resources_dir/Info.plist" ] 365 } 366 367 post_processing_args += 368 [ "-P=" + rebase_path(_plist_compiler_path, root_build_dir) ] 369 foreach(_partial_info_plist, _partial_info_plists) { 370 post_processing_args += 371 [ "-p=" + rebase_path(_partial_info_plist, root_build_dir) ] 372 } 373 } 374 } 375} 376