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