Index: build/config/ios/rules.gni |
diff --git a/build/config/ios/rules.gni b/build/config/ios/rules.gni |
index aa787158cf49adcc60dd0cc646c61adac39745f9..d3afc12f38c6e76d158975d7066fc960d41438cb 100644 |
--- a/build/config/ios/rules.gni |
+++ b/build/config/ios/rules.gni |
@@ -6,6 +6,13 @@ import("//build/config/ios/ios_sdk.gni") |
import("//build/config/mac/base_rules.gni") |
import("//build/config/mac/symbols.gni") |
+_toolchain_suffix = "" |
+_is_fat_build = additional_toolchains != [] |
+if (_is_fat_build) { |
+ _toolchain_suffix = "($default_toolchain)" |
+ _is_fat_build_main_target = current_toolchain == default_toolchain |
+} |
+ |
# Generates Info.plist files for Mac apps and frameworks. |
# |
# Arguments |
@@ -146,11 +153,6 @@ template("ios_app_bundle") { |
# The rest of the build, including the codesigning step, are the same for |
# thin and fat builds. |
- _is_fat_build = additional_toolchains != [] |
- if (_is_fat_build) { |
- _is_fat_build_main_target = current_toolchain == default_toolchain |
- } |
- |
_executable_extra_deps = [] |
_executable_extra_inputs = [] |
_executable_extra_ldflags = [] |
@@ -161,11 +163,6 @@ template("ios_app_bundle") { |
# |
# As the generation of the entitlement depends on the |
if (use_ios_simulator) { |
- _toolchain_suffix = "" |
- if (_is_fat_build && !_is_fat_build_main_target) { |
- _toolchain_suffix = "($default_toolchain)" |
- } |
- |
_generate_entitlements_target = _target_name + "_gen_entitlements" |
_generate_entitlements_target_with_toolchain_suffix = |
"$_generate_entitlements_target$_toolchain_suffix" |
@@ -763,12 +760,11 @@ template("bundle_data_strings") { |
# Template to package a shared library into an iOS framework bundle. |
# |
-# This template provides two targets to control whether the framework is |
-# merely built when targets depend on it, or whether it is linked as well: |
-# "$target_name" and "$target_name+link". |
-# |
-# See the //build/config/mac/base_rules.gni:framework_bundle for a discussion |
-# and examples. |
+# By default, the bundle target this template generates does not link the |
+# resulting framework into anything that depends on it. If a dependency wants |
+# a link-time (as well as build-time) dependency on the framework bundle, |
+# depend against "$target_name+link". If only the build-time dependency is |
+# required (e.g., for copying into another bundle), then use "$target_name". |
# |
# Arguments |
# |
@@ -791,6 +787,70 @@ template("bundle_data_strings") { |
# (optional) list of files. Needs to be defined and non-empty if |
# public_headers is defined and non-empty. |
# |
+# This template provides two targets for the resulting framework bundle. The |
+# link-time behavior varies depending on which of the two targets below is |
+# added as a dependency: |
+# - $target_name only adds a build-time dependency. Targets that depend on |
+# it will not link against the framework. |
+# - $target_name+link adds a build-time and link-time dependency. Targets |
+# that depend on it will link against the framework. |
+# |
+# The build-time-only dependency is used for when a target needs to use the |
+# framework either only for resources, or because the target loads it at run- |
+# time, via dlopen() or NSBundle. The link-time dependency will cause the |
+# dependee to have the framework loaded by dyld at launch. |
+# |
+# Example of build-time only dependency: |
+# |
+# framework_bundle("CoreTeleportation") { |
+# sources = [ ... ] |
+# } |
+# |
+# bundle_data("core_teleportation_bundle_data") { |
+# deps = [ ":CoreTeleportation" ] |
+# sources = [ "$root_out_dir/CoreTeleportation.framework" ] |
+# outputs = [ "{{bundle_root_dir}}/Frameworks/{{source_file_part}}" ] |
+# } |
+# |
+# app_bundle("GoatTeleporter") { |
+# sources = [ ... ] |
+# deps = [ |
+# ":core_teleportation_bundle_data", |
+# ] |
+# } |
+# |
+# The GoatTeleporter.app will not directly link against |
+# CoreTeleportation.framework, but it will be included in the bundle's |
+# Frameworks directory. |
+# |
+# Example of link-time dependency: |
+# |
+# framework_bundle("CoreTeleportation") { |
+# sources = [ ... ] |
+# ldflags = [ |
+# "-install_name", |
+# "@executable_path/../Frameworks/$target_name.framework" |
+# ] |
+# } |
+# |
+# bundle_data("core_teleportation_bundle_data") { |
+# deps = [ ":CoreTeleportation+link" ] |
+# sources = [ "$root_out_dir/CoreTeleportation.framework" ] |
+# outputs = [ "{{bundle_root_dir}}/Frameworks/{{source_file_part}}" ] |
+# } |
+# |
+# app_bundle("GoatTeleporter") { |
+# sources = [ ... ] |
+# deps = [ |
+# ":core_teleportation_bundle_data", |
+# ] |
+# } |
+# |
+# Note that the framework is still copied to the app's bundle, but dyld will |
+# load this library when the app is launched because it uses the "+link" |
+# target as a dependency. This also requires that the framework set its |
+# install_name so that dyld can locate it. |
+# |
# See "gn help shared_library" for more information on arguments supported |
# by shared library target. |
template("ios_framework_bundle") { |
@@ -799,38 +859,80 @@ template("ios_framework_bundle") { |
if (defined(invoker.output_name)) { |
_output_name = invoker.output_name |
} |
- _framework_target = _target_name |
_has_public_headers = |
defined(invoker.public_headers) && invoker.public_headers != [] |
- _is_fat_build = additional_toolchains != [] |
- if (_is_fat_build) { |
- _is_fat_build_main_target = current_toolchain == default_toolchain |
+ if (_has_public_headers) { |
+ _framework_headers_target = _target_name + "_framework_headers" |
+ _framework_headers_config = _target_name + "_framework_headers_config" |
+ _headers_map_config = _target_name + "_headers_map" |
} |
- # This template has a different expansion depending on whether public headers |
- # are defined or not. If no public headers are speficied, then is forwards to |
- # the generic "framework_bundle" target, otherwise if expands to targets that |
- # create header map mapping and corresponding config and configure them as |
- # dependencies of the generic "framework_bundle" target. |
+ # The expansion of the template is different for fat and thin builds. For |
+ # thin build (and default toolchain of a fat build), the template expands |
+ # to a "shared_library" target to create the bundle shared library and a |
+ # "create_bundle" target (the main target) to create the bundle structure. |
# |
- # The expansion is a bit different for multi-architecture builds (aka fat |
- # binary builds). Then the targets build for the non-default toolchain uses |
- # the same header map (if available) as the one used by the default toolchain. |
+ # For a fat build, the template just expands to the "shared_library" target |
+ # for the non-default toolchain, while the final library is created using |
+ # "lipo" in the expansion of the template for the default toolchain. |
+ # |
+ # The "$target_name+link" group for the non-default toolchain depends on the |
+ # target of the same name from the default toolchain as this is the target |
+ # that defines the real framework bundle (it will support the current cpu |
+ # as it is a fat framework). |
- _toolchain_suffix = "" |
if (_is_fat_build && !_is_fat_build_main_target) { |
- _toolchain_suffix = "($default_toolchain)" |
- } |
+ shared_library(_target_name) { |
+ forward_variables_from(invoker, |
+ "*", |
+ [ |
+ "assert_no_deps", |
+ "bundle_deps", |
+ "code_signing_enabled", |
+ "data_deps", |
+ "info_plist", |
+ "info_plist_target", |
+ "output_name", |
+ ]) |
+ if (defined(visibility)) { |
+ visibility += [ ":${_target_name}_shared_library($default_toolchain)" ] |
+ } |
+ output_name = _output_name |
+ output_prefix_override = true |
+ output_extension = "" |
+ output_dir = "$target_out_dir/$_target_name" |
- if (_has_public_headers) { |
- _framework_headers_target = _target_name + "_framework_headers" |
- _framework_public_config = _target_name + "_ios_public_config" |
- _framework_target = target_name + "_internal" |
- _headers_map_config = _target_name + "_headers_map" |
+ if (_has_public_headers) { |
+ configs += [ |
+ ":$_framework_headers_config$_toolchain_suffix", |
+ ":$_headers_map_config$_toolchain_suffix", |
+ ] |
- if (!_is_fat_build || _is_fat_build_main_target) { |
+ if (!defined(deps)) { |
+ deps = [] |
+ } |
+ deps += [ ":$_framework_headers_target$_toolchain_suffix" ] |
+ } |
+ } |
+ |
+ group(_target_name + "+link") { |
+ forward_variables_from(invoker, |
+ [ |
+ "visibility", |
+ "testonly", |
+ ]) |
+ public_deps = [ |
+ ":$_target_name+link($default_toolchain)", |
+ ] |
+ } |
+ |
+ if (defined(invoker.bundle_deps)) { |
+ assert(invoker.bundle_deps != [], "mark bundle_deps as used") |
+ } |
+ } else { |
+ if (_has_public_headers) { |
_public_headers = invoker.public_headers |
_framework_name = _output_name + ".framework" |
_framework_root = "$root_out_dir/$_framework_name" |
@@ -901,7 +1003,7 @@ template("ios_framework_bundle") { |
] |
} |
- config(_framework_public_config) { |
+ config(_framework_headers_config) { |
# The link settings are inherited from the framework_bundle config. |
cflags = [ |
"-F", |
@@ -909,9 +1011,178 @@ template("ios_framework_bundle") { |
] |
} |
} |
- } |
- if (!_is_fat_build || _is_fat_build_main_target) { |
+ _code_signing_enabled = ios_enable_code_signing |
+ if (defined(invoker.code_signing_enabled)) { |
+ _code_signing_enabled = |
+ invoker.code_signing_enabled && _code_signing_enabled |
+ } |
+ |
+ # If the framework is unversioned, the final _target_name will be the |
+ # create_bundle(_framework_target), otherwise an action with the name |
+ # _target_name will depends on the the create_bundle() in order to prepare |
+ # the versioned directory structure. |
+ _framework_target = _target_name |
+ _framework_name = _output_name + ".framework" |
+ _framework_root_dir = "$root_out_dir/$_framework_name" |
+ if (defined(invoker.framework_version) && invoker.framework_version != "") { |
+ _framework_version = invoker.framework_version |
+ _framework_root_dir += "/Versions/$_framework_version" |
+ _framework_target = _target_name + "_create_bundle" |
+ } |
+ |
+ _link_shared_library_target = target_name + "_shared_library" |
+ _shared_library_dir = "$target_out_dir/$_link_shared_library_target" |
+ |
+ if (_code_signing_enabled) { |
+ _link_shared_library_visibility = [ ":$_framework_target" ] |
+ } else { |
+ _shared_library_bundle_data = target_name + "_shared_library_bundle_data" |
+ _link_shared_library_visibility = [ ":$_shared_library_bundle_data" ] |
+ } |
+ |
+ if (_is_fat_build) { |
+ _lipo_shared_library_target = _link_shared_library_target |
+ _lipo_shared_library_visibility = _link_shared_library_visibility |
+ |
+ _link_shared_library_visibility = [] |
+ _link_shared_library_visibility = [ ":$_lipo_shared_library_target" ] |
+ _link_shared_library_target = target_name + "_arch_shared_library" |
+ |
+ _arch_shared_library_dir = "$target_out_dir/$_link_shared_library_target" |
+ _shared_library_dir = "$target_out_dir/$_lipo_shared_library_target" |
+ } |
+ |
+ shared_library(_link_shared_library_target) { |
+ forward_variables_from(invoker, |
+ "*", |
+ [ |
+ "assert_no_deps", |
+ "bundle_deps", |
+ "code_signing_enabled", |
+ "data_deps", |
+ "info_plist", |
+ "info_plist_target", |
+ "output_name", |
+ "visibility", |
+ ]) |
+ visibility = _link_shared_library_visibility |
+ output_name = _output_name |
+ output_prefix_override = true |
+ output_extension = "" |
+ |
+ if (!_is_fat_build) { |
+ output_dir = _shared_library_dir |
+ } else { |
+ output_dir = _arch_shared_library_dir |
+ } |
+ |
+ if (_has_public_headers) { |
+ configs += [ ":$_headers_map_config$_toolchain_suffix" ] |
+ |
+ if (!defined(deps)) { |
+ deps = [] |
+ } |
+ deps += [ ":$_framework_headers_target$_toolchain_suffix" ] |
+ } |
+ } |
+ |
+ if (_is_fat_build) { |
+ action(_lipo_shared_library_target) { |
+ forward_variables_from(invoker, [ "testonly" ]) |
+ visibility = _lipo_shared_library_visibility |
+ script = "//build/toolchain/mac/linker_driver.py" |
+ outputs = [ |
+ "$_shared_library_dir/$_output_name", |
+ ] |
+ inputs = [ |
+ "$_arch_shared_library_dir/$_output_name", |
+ ] |
+ deps = [ |
+ ":$_link_shared_library_target", |
+ ] |
+ foreach(_additional_toolchain, additional_toolchains) { |
+ _additional_toolchain_target = "$_target_name($_additional_toolchain)" |
+ deps += [ ":$_additional_toolchain_target" ] |
+ inputs += [ get_label_info(_additional_toolchain_target, |
+ "target_out_dir") + "/$_output_name" ] |
+ } |
+ args = [ |
+ "xcrun", |
+ "lipo", |
+ "-create", |
+ "-output", |
+ rebase_path(outputs[0], root_build_dir), |
+ ] + rebase_path(inputs, root_build_dir) |
+ |
+ if (enable_dsyms) { |
+ outputs += [ "$root_out_dir/$_output_name.dSYM/" ] |
+ args += |
+ [ "-Wcrl,dsym," + rebase_path("$root_out_dir/.", root_build_dir) ] |
+ } |
+ |
+ if (enable_stripping) { |
+ # Check whether //build/config/mac:strip_all has been removed from |
+ # the configs variable (as this is how stripping is disabled for a |
+ # single target). |
+ _strip_all_in_config = false |
+ if (defined(invoker.configs)) { |
+ foreach(_config, invoker.configs) { |
+ if (_config == "//build/config/mac:strip_all") { |
+ _strip_all_in_config = true |
+ } |
+ } |
+ } |
+ |
+ if (_strip_all_in_config) { |
+ args += [ "-Wcrl,strip,-x,-S" ] |
+ |
+ if (save_unstripped_output) { |
+ outputs += [ outputs[0] + ".unstripped" ] |
+ args += [ "-Wcrl,unstripped," + |
+ rebase_path(get_path_info(outputs[0], "dir"), |
+ root_build_dir) ] |
+ } |
+ } |
+ } |
+ } |
+ } |
+ |
+ if (!_code_signing_enabled) { |
+ bundle_data(_shared_library_bundle_data) { |
+ visibility = [ ":$_framework_target" ] |
+ forward_variables_from(invoker, [ "testonly" ]) |
+ sources = [ |
+ "$_shared_library_dir/$_output_name", |
+ ] |
+ outputs = [ |
+ "{{bundle_executable_dir}}/$_output_name", |
+ ] |
+ if (_is_fat_build) { |
+ public_deps = [ |
+ ":$_lipo_shared_library_target", |
+ ] |
+ } else { |
+ public_deps = [ |
+ ":$_link_shared_library_target", |
+ ] |
+ } |
+ } |
+ } |
+ |
+ _framework_public_config = _target_name + "_public_config" |
+ config(_framework_public_config) { |
+ # TODO(sdefresne): should we have a framework_dirs similar to lib_dirs |
+ # and include_dirs to avoid duplicate values on the command-line. |
+ visibility = [ ":$_framework_target" ] |
+ ldflags = [ |
+ "-F", |
+ rebase_path("$root_out_dir/.", root_build_dir), |
+ ] |
+ lib_dirs = [ root_out_dir ] |
+ libs = [ _framework_name ] |
+ } |
+ |
_info_plist_target = _target_name + "_info_plist" |
_info_plist_bundle = _target_name + "_info_plist_bundle" |
ios_info_plist(_info_plist_target) { |
@@ -926,7 +1197,7 @@ template("ios_framework_bundle") { |
} |
bundle_data(_info_plist_bundle) { |
- visibility = [ ":$_framework_target" ] |
+ visibility = [ ":$_target_name" ] |
forward_variables_from(invoker, [ "testonly" ]) |
sources = get_target_outputs(":$_info_plist_target") |
outputs = [ |
@@ -936,83 +1207,131 @@ template("ios_framework_bundle") { |
":$_info_plist_target", |
] |
} |
- } |
- framework_bundle(_framework_target) { |
- forward_variables_from(invoker, |
- "*", |
- [ |
- "output_name", |
- "public_headers", |
- "visibility", |
- ]) |
- output_name = _output_name |
+ create_bundle(_framework_target) { |
+ forward_variables_from(invoker, |
+ [ |
+ "data_deps", |
+ "deps", |
+ "public_configs", |
+ "public_deps", |
+ "testonly", |
+ ]) |
- if (!_is_fat_build || _is_fat_build_main_target) { |
- if (!defined(bundle_deps)) { |
- bundle_deps = [] |
+ if (defined(_framework_version)) { |
+ visibility = [ ":$_target_name" ] |
+ } else { |
+ if (defined(invoker.visibility)) { |
+ visibility = invoker.visibility |
+ visibility += [ ":$_target_name+link" ] |
+ } |
} |
- bundle_deps += [ ":$_info_plist_bundle" ] |
- } |
- if (_has_public_headers) { |
- if (!defined(public_configs)) { |
- public_configs = [] |
+ if (!defined(deps)) { |
+ deps = [] |
} |
- public_configs += [ ":$_framework_public_config$_toolchain_suffix" ] |
- } |
+ deps += [ ":$_info_plist_bundle" ] |
- if (_has_public_headers) { |
- visibility = [ |
- ":$_target_name$_toolchain_suffix", |
- ":$_target_name+link$_toolchain_suffix", |
- ":$_target_name+bundle$_toolchain_suffix", |
- ] |
- configs += [ ":$_headers_map_config$_toolchain_suffix" ] |
+ if (defined(invoker.bundle_deps)) { |
+ if (!defined(deps)) { |
+ deps = [] |
+ } |
+ deps += invoker.bundle_deps |
+ } |
- if (!defined(deps)) { |
- deps = [] |
+ if (!_code_signing_enabled) { |
+ if (!defined(public_deps)) { |
+ public_deps = [] |
+ } |
+ public_deps += [ ":$_shared_library_bundle_data" ] |
} |
- deps += [ ":$_framework_headers_target$_toolchain_suffix" ] |
- } else { |
- if (defined(invoker.visibility)) { |
- visibility = invoker.visibility |
- visibility += [ ":$_target_name+link$_toolchain_suffix" ] |
+ |
+ bundle_root_dir = _framework_root_dir |
+ bundle_resources_dir = "$bundle_root_dir/Resources" |
+ bundle_executable_dir = "$bundle_root_dir" |
+ |
+ if (_code_signing_enabled) { |
+ if (!defined(deps)) { |
+ deps = [] |
+ } |
+ |
+ if (_is_fat_build) { |
+ deps += [ ":$_lipo_shared_library_target" ] |
+ } else { |
+ deps += [ ":$_link_shared_library_target" ] |
+ } |
+ |
+ _entitlements_path = "//build/config/ios/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, |
+ "$_shared_library_dir/$_output_name", |
+ ] |
+ code_signing_outputs = [ |
+ "$bundle_root_dir/$_output_name", |
+ "$bundle_root_dir/_CodeSignature/CodeResources", |
+ "$bundle_root_dir/embedded.mobileprovision", |
+ ] |
+ code_signing_args = [ |
+ "-e=" + rebase_path(_entitlements_path, root_build_dir), |
+ "code-sign-bundle", |
+ "-i=" + ios_code_signing_identity, |
+ "-b=" + |
+ rebase_path("$_shared_library_dir/$_output_name", root_build_dir), |
+ rebase_path(bundle_root_dir, root_build_dir), |
+ ] |
} |
} |
- } |
- if (_has_public_headers) { |
- group(_target_name) { |
- forward_variables_from(invoker, |
- [ |
- "testonly", |
- "public_configs", |
- ]) |
+ if (defined(_framework_version)) { |
+ action(_target_name) { |
+ forward_variables_from(invoker, [ "testonly" ]) |
- if (defined(invoker.visibility)) { |
- visibility = invoker.visibility |
- visibility += [ ":$_target_name+link" ] |
- } |
+ if (defined(invoker.visibility)) { |
+ visibility = invoker.visibility |
+ visibility += [ ":$_target_name+link" ] |
+ } |
- public_deps = [ |
- ":$_framework_target$_toolchain_suffix", |
- ] |
+ script = "//build/config/mac/package_framework.py" |
+ outputs = [ |
+ "$root_out_dir/$_framework_name/Versions/Current", |
+ ] |
+ args = [ |
+ "$_framework_name", |
+ "$_framework_version", |
+ ] |
+ public_deps = [ |
+ ":$_framework_target", |
+ ] |
+ } |
} |
group(_target_name + "+link") { |
forward_variables_from(invoker, |
[ |
+ "public_deps", |
+ "public_configs", |
"testonly", |
"visibility", |
]) |
- public_deps = [ |
- ":$_framework_target+link$_toolchain_suffix", |
- ] |
+ if (!defined(public_deps)) { |
+ public_deps = [] |
+ } |
+ public_deps += [ ":$_target_name" ] |
+ if (!defined(public_configs)) { |
+ public_configs = [] |
+ } |
+ public_configs += [ ":$_framework_public_config" ] |
+ |
+ if (_has_public_headers) { |
+ public_configs += [ ":$_framework_headers_config" ] |
+ } |
} |
- } |
- if (!_is_fat_build || _is_fat_build_main_target) { |
bundle_data(_target_name + "+bundle") { |
forward_variables_from(invoker, |
[ |
@@ -1020,7 +1339,7 @@ template("ios_framework_bundle") { |
"visibility", |
]) |
public_deps = [ |
- ":$_framework_target", |
+ ":$_target_name", |
] |
sources = [ |
"$root_out_dir/$_output_name.framework", |
@@ -1047,11 +1366,6 @@ template("ios_xctest_test") { |
_output_name = invoker.output_name |
} |
- _is_fat_build = additional_toolchains != [] |
- if (_is_fat_build) { |
- _is_fat_build_main_target = current_toolchain == default_toolchain |
- } |
- |
_xctest_target = _target_name |
_xctest_output = _output_name |