Chromium Code Reviews| Index: build/config/ios/rules.gni |
| diff --git a/build/config/ios/rules.gni b/build/config/ios/rules.gni |
| index 219b580be3c0e7beb6ade0a48bdcf603bb6942a1..3da9e9b3bd6d1f9b6377ea5ac9fce771342ae56b 100644 |
| --- a/build/config/ios/rules.gni |
| +++ b/build/config/ios/rules.gni |
| @@ -70,10 +70,6 @@ template("ios_info_plist") { |
| } |
| } |
| -# TODO(crbug.com/297668): refactor this template to extract common behaviour |
| -# between OS X and iOS bundle generation, then create a generic "app" template |
| -# that forward to "executable" on all platform except iOS/OS X. |
| - |
| # Template to build an application bundle for iOS. |
| # |
| # This should be used instead of "executable" built-in target type on iOS. |
| @@ -122,156 +118,324 @@ template("ios_app_bundle") { |
| _output_name = invoker.output_name |
| } |
| - _generate_info_plist = target_name + "_generate_info_plist" |
| - _bundle_data_info_plist = target_name + "_bundle_data_info_plist" |
| - |
| - ios_info_plist(_generate_info_plist) { |
| - executable_name = _output_name |
| - forward_variables_from(invoker, |
| - [ |
| - "extra_substitutions", |
| - "info_plist", |
| - "info_plist_target", |
| - ]) |
| - } |
| - |
| - bundle_data(_bundle_data_info_plist) { |
| - forward_variables_from(invoker, [ "testonly" ]) |
| - visibility = [ ":$_target_name" ] |
| - sources = get_target_outputs(":$_generate_info_plist") |
| - outputs = [ |
| - "{{bundle_root_dir}}/Info.plist", |
| - ] |
| - public_deps = [ |
| - ":$_generate_info_plist", |
| - ] |
| - } |
| - |
| - _generate_executable = target_name + "_generate_executable" |
| - if (!ios_enable_code_signing) { |
| - _bundle_data_executable = target_name + "_bundle_data_executable" |
| + # This template expands to multiple targets with some differences between |
| + # the the different build configuration. |
| + # |
| + # For a regular build (i.e. when multi_arch_target_cpus is an empty list), |
|
Robert Sesek
2016/07/08 18:17:54
Maybe use "thin" instead of "regular" as that's th
sdefresne
2016/07/11 13:44:38
Done.
|
| + # it compiles the final application binary with an "executable" target, |
| + # performs variable expansions on the Info.plist, defines some "bundle_data" |
| + # target to pack Info.plist and the executable into the .app bundle, and |
| + # finally a "create_bundle" target that packs everything the bundle. If the |
| + # bundle needs to be signed, then the binary is copied into the bundle by |
| + # the "create_bundle" target and the intermediate "bundle_data" target is |
| + # not generated. |
| + # |
| + # For a multi-architecture build (aka fat-build), the template expands to |
| + # a simple "executable" target for non-default toolchain. This is because |
| + # the real application bundle will contains a single binary that supports |
| + # all the architectures and creating a separate .app bundle for every |
| + # architecture would be a waste of time. |
| + # |
| + # The target for the default toolchain of a multi-architecture build will |
| + # build the executable for current_cpu in a temporary location. The real |
| + # fat binary will be created by "lipo" command from all those "executable" |
| + # target (including those of the non-default toolchains). This additional |
| + # target has the same role as the "executable" target of a regular build. |
| + # |
| + # The rest of the build, including the codesigning step, are the same for |
| + # regular and fat builds. |
| + |
| + _is_fat_build = multi_arch_toolchains != [] |
| + if (_is_fat_build) { |
| + _is_fat_build_main_target = current_toolchain == default_toolchain |
| } |
| - executable(_generate_executable) { |
| - if (ios_enable_code_signing) { |
| - visibility = [ ":$_target_name" ] |
| - } else { |
| - visibility = [ ":$_bundle_data_executable" ] |
| - } |
| - forward_variables_from(invoker, |
| - "*", |
| - [ |
| - "bundle_extension", |
| - "data_deps", |
| - "entitlements_path", |
| - "info_plist", |
| - "info_plist_target", |
| - "output_name", |
| - "product_type", |
| - "visibility", |
| - ]) |
| + if (_is_fat_build && !_is_fat_build_main_target) { |
| + # For the non-default toolchain of a fat-build, the template expands to a |
| + # single "executable" target that creates "$root_out_dir/$_output_name". |
| + executable(_target_name) { |
| + forward_variables_from(invoker, |
| + "*", |
| + [ |
| + "bundle_extension", |
| + "entitlements_path", |
| + "extra_substitutions", |
| + "info_plist", |
| + "info_plist_target", |
| + "output_name", |
| + "product_type", |
| + ]) |
| - output_name = rebase_path("$target_gen_dir/$_output_name", root_out_dir) |
| - output_prefix_override = true |
| + if (defined(visibility)) { |
| + visibility += [ ":*($default_toolchain)" ] |
| + } |
| - if (!defined(libs)) { |
| - libs = [] |
| + output_name = _output_name |
| + if (!defined(libs)) { |
| + libs = [] |
| + } |
| + libs += [ "UIKit.framework" ] |
| + if (!defined(ldflags)) { |
| + ldflags = [] |
| + } |
| + ldflags += [ "-ObjC" ] |
| } |
| - libs += [ "UIKit.framework" ] |
| - if (!defined(ldflags)) { |
| - ldflags = [] |
| + } else { |
| + # This is either a regular build or the default toolchain of a fat-build. |
|
Robert Sesek
2016/07/08 18:17:54
regular -> thin
sdefresne
2016/07/11 13:44:37
Done.
|
| + # The template will expand in many different target ($target_name is the |
| + # create_bundle target) used as input to the create_bundle target. |
| + _generate_info_plist = target_name + "_generate_info_plist" |
| + _bundle_data_info_plist = target_name + "_bundle_data_info_plist" |
| + |
| + ios_info_plist(_generate_info_plist) { |
| + visibility = [ ":$_bundle_data_info_plist" ] |
| + executable_name = _output_name |
| + forward_variables_from(invoker, |
| + [ |
| + "extra_substitutions", |
| + "info_plist", |
| + "info_plist_target", |
| + ]) |
| } |
| - ldflags += [ "-ObjC" ] |
| - } |
| - if (!ios_enable_code_signing) { |
| - bundle_data(_bundle_data_executable) { |
| - forward_variables_from(invoker, [ "testonly" ]) |
| + bundle_data(_bundle_data_info_plist) { |
| visibility = [ ":$_target_name" ] |
| - sources = [ |
| - "$target_gen_dir/$_output_name", |
| - ] |
| + forward_variables_from(invoker, [ "testonly" ]) |
| + sources = get_target_outputs(":$_generate_info_plist") |
| outputs = [ |
| - "{{bundle_executable_dir}}/$_output_name", |
| + "{{bundle_root_dir}}/Info.plist", |
| ] |
| public_deps = [ |
| - ":$_generate_executable", |
| + ":$_generate_info_plist", |
| ] |
| } |
| - } |
| - create_bundle(target_name) { |
| - forward_variables_from(invoker, |
| - [ |
| - "data_deps", |
| - "deps", |
| - "public_deps", |
| - "testonly", |
| - "visibility", |
| - ]) |
| + _link_executable = _target_name + "_link_executable" |
| + _executable_path = "$target_gen_dir/$_output_name" |
| - if (!defined(deps)) { |
| - deps = [] |
| - } |
| - deps += [ ":$_bundle_data_info_plist" ] |
| if (ios_enable_code_signing) { |
| - deps += [ ":$_generate_executable" ] |
| + _link_executable_visibility = [ ":$_target_name" ] |
| } else { |
| - deps += [ ":$_bundle_data_executable" ] |
| + _bundle_data_executable = target_name + "_bundle_data_executable" |
| + _link_executable_visibility = [ ":$_bundle_data_executable" ] |
| } |
| - if (use_ios_simulator) { |
| - if (!defined(data_deps)) { |
| - data_deps = [] |
| + # For a fat-build, the different "executable" outputs will be used to |
| + # create the final binary using "lipo". As the corresponding target has |
| + # the same role as the "executable" target in a regular build, copy the |
| + # visibility and redefine some variables. |
| + if (_is_fat_build) { |
| + _lipo_executable = _target_name + "_lipo_executable" |
| + _lipo_executable_visibility = _link_executable_visibility |
| + |
| + _link_executable_visibility = [] |
| + _link_executable_visibility = [ ":$_lipo_executable" ] |
| + |
| + _arch_executable_path = "$target_gen_dir/$current_cpu/$_output_name" |
| + } |
| + |
| + executable(_link_executable) { |
| + forward_variables_from(invoker, |
| + "*", |
| + [ |
| + "bundle_extension", |
| + "data_deps", |
| + "entitlements_path", |
| + "extra_substitutions", |
| + "info_plist", |
| + "info_plist_target", |
| + "output_name", |
| + "product_type", |
| + "visibility", |
| + ]) |
| + |
| + visibility = _link_executable_visibility |
| + |
| + output_prefix_override = true |
| + if (_is_fat_build) { |
| + output_name = rebase_path(_arch_executable_path, root_build_dir) |
| + } else { |
| + output_name = rebase_path(_executable_path, root_build_dir) |
| + } |
| + |
| + if (!defined(libs)) { |
| + libs = [] |
| + } |
| + libs += [ "UIKit.framework" ] |
| + if (!defined(ldflags)) { |
| + ldflags = [] |
| } |
| - data_deps += [ "//testing/iossim" ] |
| + ldflags += [ "-ObjC" ] |
| } |
| - if (defined(invoker.product_type)) { |
| - product_type = invoker.product_type |
| - } else { |
| - product_type = "com.apple.product-type.application" |
| + if (_is_fat_build) { |
| + # Create the multi-architecture binary from all the single architecture |
| + # binaries using "lipo". This target exists for the default toolchain |
| + # of a fat-build only and depends on the expansion of "ios_app_bundle" |
| + # for the other toolchains (i.e. a single "executable" target). |
| + # |
| + # This action only happens once per "ios_app_bundle" template (for the |
| + # main toolchain). |
| + action(_lipo_executable) { |
| + forward_variables_from(invoker, [ "testonly" ]) |
| + visibility = _lipo_executable_visibility |
| + script = "//build/config/mac/xcrun.py" |
| + outputs = [ |
| + _executable_path, |
| + ] |
| + inputs = [ |
| + _arch_executable_path, |
| + ] |
| + deps = [ |
| + ":$_link_executable", |
| + ] |
| + foreach(_toolchain, multi_arch_toolchains) { |
| + _toolchain_target = "$_target_name($_toolchain)" |
| + deps += [ ":$_toolchain_target" ] |
| + inputs += [ get_label_info(_toolchain_target, "root_out_dir") + |
| + "/$_output_name" ] |
| + } |
| + args = [ |
| + "lipo", |
| + "-create", |
| + "-output", |
| + rebase_path(outputs[0], root_build_dir), |
| + ] + rebase_path(inputs, root_build_dir) |
| + } |
| } |
| - if (defined(invoker.bundle_extension)) { |
| - _bundle_extension = invoker.bundle_extension |
| - } else { |
| - _bundle_extension = ".app" |
| + if (!ios_enable_code_signing) { |
| + # If codesigning is enabled, the binary will be copied into the bundle |
| + # by the codesigning script (as the binary is updated by the signature). |
| + # Otherwise, this "bundle_data" declares the location of the binary in |
| + # the .app bundle. |
| + bundle_data(_bundle_data_executable) { |
| + forward_variables_from(invoker, [ "testonly" ]) |
| + visibility = [ ":$_target_name" ] |
| + outputs = [ |
| + "{{bundle_executable_dir}}/$_output_name", |
| + ] |
| + if (_is_fat_build) { |
| + public_deps = [ |
| + ":$_lipo_executable", |
| + ] |
| + } else { |
| + public_deps = [ |
| + ":$_link_executable", |
| + ] |
| + } |
| + sources = [ |
| + "$target_gen_dir/$_output_name", |
| + ] |
| + } |
| } |
| - bundle_root_dir = "$root_out_dir/$_output_name$_bundle_extension" |
| - bundle_resources_dir = bundle_root_dir |
| - bundle_executable_dir = bundle_root_dir |
| - bundle_plugins_dir = "$bundle_root_dir/PlugIns" |
| + create_bundle(target_name) { |
| + forward_variables_from(invoker, |
| + [ |
| + "data_deps", |
| + "deps", |
| + "public_deps", |
| + "testonly", |
| + "visibility", |
| + ]) |
| - if (defined(invoker.entitlements_path)) { |
| - _entitlements_path = invoker.entitlements_path |
| - } else { |
| - _entitlements_path = "$ios_sdk_path/Entitlements.plist" |
| - } |
| + if (!defined(deps)) { |
| + deps = [] |
| + } |
| + deps += [ ":$_bundle_data_info_plist" ] |
| + if (ios_enable_code_signing) { |
| + if (_is_fat_build) { |
| + deps += [ ":$_lipo_executable" ] |
| + } else { |
| + deps += [ ":$_link_executable" ] |
| + } |
| + } else { |
| + deps += [ ":$_bundle_data_executable" ] |
| + } |
| - if (ios_enable_code_signing) { |
| - code_signing_script = "//build/config/ios/codesign.py" |
| - code_signing_sources = [ |
| - _entitlements_path, |
| - "$target_gen_dir/$_output_name", |
| - ] |
| - code_signing_outputs = [ |
| - "$bundle_root_dir/$_output_name", |
| - "$bundle_root_dir/_CodeSignature/CodeResources", |
| - "$bundle_root_dir/embedded.mobileprovision", |
| - ] |
| - code_signing_args = [ |
| - "-i=" + ios_code_signing_identity, |
| - "-b=" + rebase_path("$target_gen_dir/$_output_name", root_build_dir), |
| - "-e=" + rebase_path(_entitlements_path, root_build_dir), |
| - rebase_path(bundle_root_dir, root_build_dir), |
| - ] |
| - } else { |
| - assert(_entitlements_path != "", |
| - "force usage of _entitlements_path to avoid unused variable error") |
| + if (use_ios_simulator) { |
| + if (!defined(data_deps)) { |
| + data_deps = [] |
| + } |
| + data_deps += [ "//testing/iossim" ] |
| + } |
| + |
| + if (defined(invoker.product_type)) { |
| + product_type = invoker.product_type |
| + } else { |
| + product_type = "com.apple.product-type.application" |
| + } |
| + |
| + if (defined(invoker.bundle_extension)) { |
| + _bundle_extension = invoker.bundle_extension |
| + } else { |
| + _bundle_extension = ".app" |
| + } |
| + |
| + bundle_root_dir = "$root_out_dir/$_output_name$_bundle_extension" |
| + bundle_resources_dir = bundle_root_dir |
| + bundle_executable_dir = bundle_root_dir |
| + bundle_plugins_dir = "$bundle_root_dir/PlugIns" |
| + |
| + if (ios_enable_code_signing) { |
| + _entitlements_path = "$ios_sdk_path/Entitlements.plist" |
| + if (defined(invoker.entitlements_path)) { |
| + _entitlements_path = invoker.entitlements_path |
| + } |
| + |
| + code_signing_script = "//build/config/ios/codesign.py" |
| + code_signing_sources = [ |
| + _entitlements_path, |
| + "$target_gen_dir/$_output_name", |
| + ] |
| + code_signing_outputs = [ |
| + "$bundle_root_dir/$_output_name", |
| + "$bundle_root_dir/_CodeSignature/CodeResources", |
| + "$bundle_root_dir/embedded.mobileprovision", |
| + ] |
| + code_signing_args = [ |
| + "-i=" + ios_code_signing_identity, |
| + "-b=" + rebase_path("$target_gen_dir/$_output_name", root_build_dir), |
| + "-e=" + rebase_path(_entitlements_path, root_build_dir), |
| + rebase_path(bundle_root_dir, root_build_dir), |
| + ] |
| + } |
| } |
| } |
| + |
| + # TODO(crbug.com/395883): ensure those variables are marked as used to |
| + # avoid errors while running "gn gen". |
| + if (defined(invoker.entitlements_path)) { |
| + assert(invoker.entitlements_path != "", |
| + "mark invoker.entitlements_path as used") |
| + } |
| + if (defined(invoker.bundle_extension)) { |
| + assert(invoker.bundle_extension != "", |
| + "mark invoker.bundle_extension as used") |
| + } |
| + if (defined(invoker.bundle_extension)) { |
| + assert(invoker.bundle_extension != "", |
| + "mark invoker.bundle_extension as used") |
| + } |
| + if (defined(invoker.entitlements_path)) { |
| + assert(invoker.entitlements_path != "", |
| + "mark invoker.entitlements_path as used") |
| + } |
| + if (defined(invoker.extra_substitutions)) { |
| + assert(invoker.extra_substitutions != [], |
| + "mark invoker.extra_substitutions as used") |
| + } |
| + if (defined(invoker.info_plist)) { |
| + assert(invoker.info_plist != "", "mark invoker.info_plist as used") |
| + } |
| + if (defined(invoker.info_plist_target)) { |
| + assert(invoker.info_plist_target != "", |
| + "mark invoker.info_plist_target as used") |
| + } |
| + if (defined(invoker.product_type)) { |
| + assert(invoker.product_type != "", "mark product_type as used") |
| + } |
| } |
| # Template to build an application extension bundle for iOS. |