| Index: build/config/ios/rules.gni
|
| diff --git a/build/config/ios/rules.gni b/build/config/ios/rules.gni
|
| index 219b580be3c0e7beb6ade0a48bdcf603bb6942a1..511171cd1dc49ab9fbe0edea4b8729389a9000bd 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 thin build (i.e. when multi_arch_target_cpus is an empty list),
|
| + # 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 thin build.
|
| + #
|
| + # The rest of the build, including the codesigning step, are the same for
|
| + # thin 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 thin build or the default toolchain of a fat-build.
|
| + # 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_out_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 thin 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_out_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_out_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_out_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_out_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.
|
|
|