summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/build/config/ios
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
commit43a97878ce14b72f0981164f87f2e35e14151312 (patch)
tree620249daf56c0258faa40cbdcf9cfba06de2a846 /third_party/libwebrtc/build/config/ios
parentInitial commit. (diff)
downloadfirefox-43a97878ce14b72f0981164f87f2e35e14151312.tar.xz
firefox-43a97878ce14b72f0981164f87f2e35e14151312.zip
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/libwebrtc/build/config/ios')
-rw-r--r--third_party/libwebrtc/build/config/ios/BUILD.gn264
-rw-r--r--third_party/libwebrtc/build/config/ios/BuildInfo.plist35
-rw-r--r--third_party/libwebrtc/build/config/ios/Host-Info.plist126
-rw-r--r--third_party/libwebrtc/build/config/ios/Module-Info.plist26
-rw-r--r--third_party/libwebrtc/build/config/ios/OWNERS1
-rw-r--r--third_party/libwebrtc/build/config/ios/asset_catalog.gni150
-rw-r--r--third_party/libwebrtc/build/config/ios/codesign.py691
-rw-r--r--third_party/libwebrtc/build/config/ios/compile_ib_files.py57
-rw-r--r--third_party/libwebrtc/build/config/ios/compile_xcassets_unittests.py141
-rw-r--r--third_party/libwebrtc/build/config/ios/config.gni28
-rw-r--r--third_party/libwebrtc/build/config/ios/dummy.py15
-rw-r--r--third_party/libwebrtc/build/config/ios/entitlements.plist12
-rw-r--r--third_party/libwebrtc/build/config/ios/find_signing_identity.py89
-rw-r--r--third_party/libwebrtc/build/config/ios/generate_umbrella_header.py75
-rw-r--r--third_party/libwebrtc/build/config/ios/hardlink.py71
-rw-r--r--third_party/libwebrtc/build/config/ios/ios_sdk.gni185
-rw-r--r--third_party/libwebrtc/build/config/ios/ios_sdk_overrides.gni17
-rw-r--r--third_party/libwebrtc/build/config/ios/ios_test_runner_wrapper.gni143
-rw-r--r--third_party/libwebrtc/build/config/ios/resources/XCTRunnerAddition+Info.plist12
-rw-r--r--third_party/libwebrtc/build/config/ios/rules.gni2173
-rw-r--r--third_party/libwebrtc/build/config/ios/strip_arm64e.py70
-rw-r--r--third_party/libwebrtc/build/config/ios/write_framework_hmap.py103
-rw-r--r--third_party/libwebrtc/build/config/ios/write_framework_modulemap.py28
-rw-r--r--third_party/libwebrtc/build/config/ios/xctest_shell.mm19
24 files changed, 4531 insertions, 0 deletions
diff --git a/third_party/libwebrtc/build/config/ios/BUILD.gn b/third_party/libwebrtc/build/config/ios/BUILD.gn
new file mode 100644
index 0000000000..525c439e7e
--- /dev/null
+++ b/third_party/libwebrtc/build/config/ios/BUILD.gn
@@ -0,0 +1,264 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/ios/ios_sdk.gni")
+import("//build/toolchain/goma.gni")
+import("//build/toolchain/toolchain.gni")
+import("//build_overrides/build.gni")
+
+declare_args() {
+ # Enabling this option makes clang compile to an intermediate
+ # representation ("bitcode"), and not to native code. This is preferred
+ # when including WebRTC in the apps that will be sent to Apple's App Store
+ # and mandatory for the apps that run on watchOS or tvOS.
+ # The option only works when building with Xcode (use_xcode_clang = true).
+ # Mimicking how Xcode handles it, the production builds (is_debug = false)
+ # get real bitcode sections added, while the debug builds (is_debug = true)
+ # only get bitcode-section "markers" added in them.
+ enable_ios_bitcode = false
+}
+
+# This is included by reference in the //build/config/compiler config that
+# is applied to all targets. It is here to separate out the logic.
+config("compiler") {
+ # These flags are shared between the C compiler and linker.
+ common_flags = []
+
+ # CPU architecture.
+ if (target_cpu == "x64") {
+ triplet_cpu = "x86_64"
+ } else if (target_cpu == "x86") {
+ triplet_cpu = "i386"
+ } else if (target_cpu == "arm" || target_cpu == "armv7") {
+ triplet_cpu = "armv7"
+ } else if (target_cpu == "arm64") {
+ triplet_cpu = "arm64"
+ } else {
+ assert(false, "unsupported cpu: $target_cpu")
+ }
+
+ # Environment.
+ if (target_environment == "simulator") {
+ triplet_environment = "-simulator"
+ } else if (target_environment == "device") {
+ triplet_environment = ""
+ } else if (target_environment == "catalyst") {
+ triplet_environment = "-macabi"
+ } else {
+ assert(false, "unsupported environment: $target_environment")
+ }
+
+ # OS.
+ triplet_os = "apple-ios"
+
+ # Set target.
+ common_flags = [
+ "-target",
+ "$triplet_cpu-$triplet_os$ios_deployment_target$triplet_environment",
+ ]
+
+ # This is here so that all files get recompiled after an Xcode update.
+ # (defines are passed via the command line, and build system rebuild things
+ # when their commandline changes). Nothing should ever read this define.
+ defines = [ "CR_XCODE_VERSION=$xcode_version" ]
+
+ asmflags = common_flags
+ cflags = common_flags
+ swiftflags = common_flags
+
+ swiftflags += [
+ "-swift-version",
+ "5",
+ ]
+
+ # Without this, the constructors and destructors of a C++ object inside
+ # an Objective C struct won't be called, which is very bad.
+ cflags_objcc = [ "-fobjc-call-cxx-cdtors" ]
+
+ ldflags = common_flags
+}
+
+# This is included by reference in the //build/config/compiler:runtime_library
+# config that is applied to all targets. It is here to separate out the logic
+# that is iOS-only. Please see that target for advice on what should go in
+# :runtime_library vs. :compiler.
+config("runtime_library") {
+ # The variable ios_sdk_path is relative to root_build_dir when using Goma RBE
+ # and system Xcode (since Goma RBE only supports paths relative to source).
+ # Rebase the value in that case since gn does not convert paths in compiler
+ # flags (since it is not aware they are paths).
+ _sdk_root = ios_sdk_path
+ if (use_system_xcode && use_goma) {
+ _sdk_root = rebase_path(ios_sdk_path, root_build_dir)
+ }
+
+ common_flags = [
+ "-isysroot",
+ _sdk_root,
+ ]
+ swiftflags = [
+ "-sdk",
+ _sdk_root,
+ ]
+
+ if (target_environment == "catalyst") {
+ common_flags += [
+ "-isystem",
+ "$_sdk_root/System/iOSSupport/usr/include",
+ "-iframework",
+ "$_sdk_root/System/iOSSupport/System/Library/Frameworks",
+ ]
+ }
+
+ if (use_xcode_clang && enable_ios_bitcode) {
+ if (is_debug) {
+ common_flags += [ "-fembed-bitcode-marker" ]
+ } else {
+ common_flags += [ "-fembed-bitcode" ]
+ }
+ }
+
+ asmflags = common_flags
+ cflags = common_flags
+ ldflags = common_flags
+}
+
+config("ios_executable_flags") {
+ ldflags = []
+
+ # On "catalyst", the bundle structure is different (uses the same structure
+ # as a regular macOS app), so an additional -rpath is required.
+ if (target_environment == "catalyst") {
+ ldflags += [ "-Wl,-rpath,@loader_path/../Frameworks" ]
+ }
+
+ ldflags += [ "-Wl,-rpath,@executable_path/Frameworks" ]
+}
+
+config("ios_extension_executable_flags") {
+ configs = default_executable_configs
+
+ ldflags = [
+ "-e",
+ "_NSExtensionMain",
+ "-fapplication-extension",
+ ]
+
+ # On "catalyst", the bundle structure is different (uses the same structure
+ # as a regular macOS app), so an additional -rpath is required.
+ if (target_environment == "catalyst") {
+ ldflags += [ "-Wl,-rpath,@loader_path/../../../../Frameworks" ]
+ }
+
+ ldflags += [ "-Wl,-rpath,@executable_path/../../Frameworks" ]
+}
+
+config("ios_dynamic_flags") {
+ ldflags = [
+ # Always load Objective-C categories and class.
+ "-Wl,-ObjC",
+ ]
+
+ # The path to the Swift compatibility libraries (required to run code built
+ # with version N of the SDK on older version of the OS) is relative to the
+ # toolchains directory and changes with the environment.
+ _swift_compatibility_libs_dir_prefix = "$ios_toolchains_path/usr/lib/swift"
+ if (target_environment == "simulator") {
+ _swift_compatibility_libs_dir =
+ "$_swift_compatibility_libs_dir_prefix/iphonesimulator"
+ } else if (target_environment == "device") {
+ _swift_compatibility_libs_dir =
+ "$_swift_compatibility_libs_dir_prefix/iphoneos"
+ } else if (target_environment == "catalyst") {
+ _swift_compatibility_libs_dir =
+ "$_swift_compatibility_libs_dir_prefix/maccatalyst"
+ }
+
+ lib_dirs = [
+ "$ios_sdk_path/usr/lib/swift",
+ _swift_compatibility_libs_dir,
+ ]
+}
+
+config("ios_shared_library_flags") {
+ ldflags = [
+ "-Wl,-rpath,@executable_path/Frameworks",
+ "-Wl,-rpath,@loader_path/Frameworks",
+ ]
+}
+
+config("disable_implicit_retain_self_warning") {
+ cflags_objc = [ "-Wno-implicit-retain-self" ]
+ cflags_objcc = cflags_objc
+}
+
+config("xctest_config") {
+ # Use -iframework for XCTest.framework so that the compiler will treat it as a
+ # system framework and ignore warnings in XCTest framework headers.
+ common_flags = [
+ "-iframework",
+ rebase_path("$ios_sdk_platform_path/Developer/Library/Frameworks",
+ root_build_dir),
+ ]
+ cflags = common_flags
+ ldflags = common_flags
+
+ frameworks = [
+ "Foundation.framework",
+ "XCTest.framework",
+ ]
+}
+
+group("xctest") {
+ public_configs = [ ":xctest_config" ]
+}
+
+_xctrunner_path =
+ "$ios_sdk_platform_path/Developer/Library/Xcode/Agents/XCTRunner.app"
+
+# When building with Goma RBE, $ios_sdk_platform_path corresponds to a symlink
+# below $root_build_dir that points to the real SDK to use. Because the files
+# are below $root_build_dir, it is not possible to list them as a target input
+# without gn complaining (as it can't find a target creating those files).
+#
+# The symlinks are created by //build/config/apple/sdk_info.py script invoked
+# via exec_script() from //build/config/{ios/ios_sdk.gni,mac/mac_sdk.gni}.
+# As the invocation is done by exec_script, there is no target that can list
+# those files as output.
+#
+# To workaround this, add a target that pretends to create those files
+# (but does nothing). See https://crbug.com/1061487 for why this is needed.
+if (use_system_xcode && use_goma) {
+ action("copy_xctrunner_app") {
+ testonly = true
+ script = "//build/noop.py"
+ outputs = [
+ "$_xctrunner_path/Info.plist",
+ "$_xctrunner_path/PkgInfo",
+ "$_xctrunner_path/XCTRunner",
+ ]
+ }
+}
+
+# When creating the test runner for an XCUITest, the arm64e slice of the binary
+# must be removed (at least until the app ships with arm64e slice which is not
+# yet supported by Apple).
+action("xctest_runner_without_arm64e") {
+ testonly = true
+ script = "//build/config/ios/strip_arm64e.py"
+ sources = [ "$_xctrunner_path/XCTRunner" ]
+ outputs = [ "$target_out_dir/XCTRunner" ]
+ args = [
+ "--output",
+ rebase_path(outputs[0], root_build_dir),
+ "--input",
+ rebase_path(sources[0], root_build_dir),
+ "--xcode-version",
+ xcode_version,
+ ]
+
+ if (use_system_xcode && use_goma) {
+ deps = [ ":copy_xctrunner_app" ]
+ }
+}
diff --git a/third_party/libwebrtc/build/config/ios/BuildInfo.plist b/third_party/libwebrtc/build/config/ios/BuildInfo.plist
new file mode 100644
index 0000000000..3595e5aefb
--- /dev/null
+++ b/third_party/libwebrtc/build/config/ios/BuildInfo.plist
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>BuildMachineOSBuild</key>
+ <string>${BUILD_MACHINE_OS_BUILD}</string>
+ <key>CFBundleSupportedPlatforms</key>
+ <array>
+ <string>${IOS_SUPPORTED_PLATFORM}</string>
+ </array>
+ <key>DTCompiler</key>
+ <string>${GCC_VERSION}</string>
+ <key>DTPlatformName</key>
+ <string>${IOS_PLATFORM_NAME}</string>
+ <key>DTPlatformVersion</key>
+ <string>${IOS_PLATFORM_VERSION}</string>
+ <key>DTPlatformBuild</key>
+ <string>${IOS_PLATFORM_BUILD}</string>
+ <key>DTSDKBuild</key>
+ <string>${IOS_SDK_BUILD}</string>
+ <key>DTSDKName</key>
+ <string>${IOS_SDK_NAME}</string>
+ <key>MinimumOSVersion</key>
+ <string>${IOS_DEPLOYMENT_TARGET}</string>
+ <key>DTXcode</key>
+ <string>${XCODE_VERSION}</string>
+ <key>DTXcodeBuild</key>
+ <string>${XCODE_BUILD}</string>
+ <key>UIDeviceFamily</key>
+ <array>
+ <integer>1</integer>
+ <integer>2</integer>
+ </array>
+</dict>
+</plist>
diff --git a/third_party/libwebrtc/build/config/ios/Host-Info.plist b/third_party/libwebrtc/build/config/ios/Host-Info.plist
new file mode 100644
index 0000000000..9f6f5deef9
--- /dev/null
+++ b/third_party/libwebrtc/build/config/ios/Host-Info.plist
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleDisplayName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIdentifier</key>
+ <string>${IOS_BUNDLE_ID_PREFIX}.test.${EXECUTABLE_NAME:rfc1034identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>LSRequiresIPhoneOS</key>
+ <true/>
+ <key>NSAppTransportSecurity</key>
+ <dict>
+ <key>NSAllowsArbitraryLoads</key>
+ <true/>
+ </dict>
+ <key>UIRequiredDeviceCapabilities</key>
+ <array>
+ <string>armv7</string>
+ </array>
+ <key>UILaunchImages</key>
+ <array>
+ <dict>
+ <key>UILaunchImageMinimumOSVersion</key>
+ <string>7.0</string>
+ <key>UILaunchImageName</key>
+ <string>Default</string>
+ <key>UILaunchImageOrientation</key>
+ <string>Portrait</string>
+ <key>UILaunchImageSize</key>
+ <string>{320, 480}</string>
+ </dict>
+ <dict>
+ <key>UILaunchImageMinimumOSVersion</key>
+ <string>7.0</string>
+ <key>UILaunchImageName</key>
+ <string>Default</string>
+ <key>UILaunchImageOrientation</key>
+ <string>Portrait</string>
+ <key>UILaunchImageSize</key>
+ <string>{320, 568}</string>
+ </dict>
+ <dict>
+ <key>UILaunchImageMinimumOSVersion</key>
+ <string>8.0</string>
+ <key>UILaunchImageName</key>
+ <string>Default</string>
+ <key>UILaunchImageOrientation</key>
+ <string>Portrait</string>
+ <key>UILaunchImageSize</key>
+ <string>{375, 667}</string>
+ </dict>
+ <dict>
+ <key>UILaunchImageMinimumOSVersion</key>
+ <string>8.0</string>
+ <key>UILaunchImageName</key>
+ <string>Default</string>
+ <key>UILaunchImageOrientation</key>
+ <string>Portrait</string>
+ <key>UILaunchImageSize</key>
+ <string>{414, 736}</string>
+ </dict>
+ <dict>
+ <key>UILaunchImageMinimumOSVersion</key>
+ <string>8.0</string>
+ <key>UILaunchImageName</key>
+ <string>Default</string>
+ <key>UILaunchImageOrientation</key>
+ <string>Landscape</string>
+ <key>UILaunchImageSize</key>
+ <string>{414, 736}</string>
+ </dict>
+ </array>
+ <key>UILaunchImages~ipad</key>
+ <array>
+ <dict>
+ <key>UILaunchImageMinimumOSVersion</key>
+ <string>7.0</string>
+ <key>UILaunchImageName</key>
+ <string>Default</string>
+ <key>UILaunchImageOrientation</key>
+ <string>Portrait</string>
+ <key>UILaunchImageSize</key>
+ <string>{768, 1024}</string>
+ </dict>
+ <dict>
+ <key>UILaunchImageMinimumOSVersion</key>
+ <string>7.0</string>
+ <key>UILaunchImageName</key>
+ <string>Default</string>
+ <key>UILaunchImageOrientation</key>
+ <string>Landscape</string>
+ <key>UILaunchImageSize</key>
+ <string>{768, 1024}</string>
+ </dict>
+ </array>
+ <key>UISupportedInterfaceOrientations</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ </array>
+ <key>UISupportedInterfaceOrientations~ipad</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ <string>UIInterfaceOrientationPortraitUpsideDown</string>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ </array>
+</dict>
+</plist>
diff --git a/third_party/libwebrtc/build/config/ios/Module-Info.plist b/third_party/libwebrtc/build/config/ios/Module-Info.plist
new file mode 100644
index 0000000000..d1bf77faf0
--- /dev/null
+++ b/third_party/libwebrtc/build/config/ios/Module-Info.plist
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIdentifier</key>
+ <string>${IOS_BUNDLE_ID_PREFIX}.${MODULE_BUNDLE_ID:rfc1034identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>BNDL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>NSPrincipalClass</key>
+ <string>${XCTEST_BUNDLE_PRINCIPAL_CLASS}</string>
+</dict>
+</plist>
diff --git a/third_party/libwebrtc/build/config/ios/OWNERS b/third_party/libwebrtc/build/config/ios/OWNERS
new file mode 100644
index 0000000000..6f3324f07c
--- /dev/null
+++ b/third_party/libwebrtc/build/config/ios/OWNERS
@@ -0,0 +1 @@
+file://build/apple/OWNERS
diff --git a/third_party/libwebrtc/build/config/ios/asset_catalog.gni b/third_party/libwebrtc/build/config/ios/asset_catalog.gni
new file mode 100644
index 0000000000..84dd92cce2
--- /dev/null
+++ b/third_party/libwebrtc/build/config/ios/asset_catalog.gni
@@ -0,0 +1,150 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/ios/ios_sdk.gni")
+
+# This template declares a bundle_data target that references an asset
+# catalog so that it is compiled to the asset catalog of the generated
+# bundle.
+#
+# The create_bundle target requires that all asset catalogs are part of an
+# .xcasset bundle. This requirement comes from actool that only receives
+# the path to the .xcasset bundle directory and not to the individual
+# .imageset directories.
+#
+# The requirement is a bit problematic as it prevents compiling only a
+# subset of the asset catakig that are contained in a .xcasset. This template
+# fixes that by instead copying the content of the asset catalog to temporary
+# .xcasset directory (below $root_out_dir) and defining a bundle_data
+# target that refers to those copies (this is efficient as the "copy" is
+# implemented by hardlinking if possible on macOS).
+#
+# Since the create_data target will only refer to the .xcasset directory
+# and additional "action" target that runs a dummy script is defined. It
+# does nothing but pretends to generate the .xcassets directory (while
+# it is really created as a side-effect of the "copy" step). This allows
+# to workaround the check in "gn" that all inputs below $root_out_dir have
+# to be outputs of another target with a public dependency path.
+#
+# This template also ensures that the file are only copied once when the
+# build targets multiple architectures at the same time (aka "fat build").
+#
+# Arguments
+#
+# sources:
+# required, list of strings, paths to the file contained in the
+# asset catalog directory; this must contain the Contents.json file
+# and all the image referenced by it (not enforced by the template).
+#
+# asset_type:
+# required, string, type of the asset catalog, that is the extension
+# of the directory containing the images and the Contents.json file.
+#
+template("asset_catalog") {
+ assert(defined(invoker.sources) && invoker.sources != [],
+ "sources must be defined and not empty for $target_name")
+
+ assert(defined(invoker.asset_type) && invoker.asset_type != "",
+ "asset_type must be defined and not empty for $target_name")
+
+ if (is_fat_secondary_toolchain) {
+ group(target_name) {
+ public_deps = [ ":$target_name($primary_fat_toolchain_name)" ]
+ }
+ } else {
+ _copy_target_name = target_name + "__copy"
+ _data_target_name = target_name
+
+ _sources = invoker.sources
+ _outputs = []
+
+ # The compilation of resources into Assets.car is enabled automatically
+ # by the "create_bundle" target if any of the "bundle_data" sources's
+ # path is in a .xcassets directory and matches one of the know asset
+ # catalog type.
+ _xcassets_dir = "$target_gen_dir/${target_name}.xcassets"
+ _output_dir = "$_xcassets_dir/" +
+ get_path_info(get_path_info(_sources[0], "dir"), "file")
+
+ foreach(_source, invoker.sources) {
+ _dir = get_path_info(_source, "dir")
+ _outputs += [ "$_output_dir/" + get_path_info(_source, "file") ]
+
+ assert(get_path_info(_dir, "extension") == invoker.asset_type,
+ "$_source dirname must have .${invoker.asset_type} extension")
+ }
+
+ action(_copy_target_name) {
+ # Forward "deps", "public_deps" and "testonly" in case some of the
+ # source files are generated.
+ forward_variables_from(invoker,
+ [
+ "deps",
+ "public_deps",
+ "testonly",
+ ])
+
+ script = "//build/config/ios/hardlink.py"
+
+ visibility = [ ":$_data_target_name" ]
+ sources = _sources
+ outputs = _outputs + [ _xcassets_dir ]
+
+ args = [
+ rebase_path(get_path_info(_sources[0], "dir"), root_build_dir),
+ rebase_path(_output_dir, root_build_dir),
+ ]
+ }
+
+ bundle_data(_data_target_name) {
+ forward_variables_from(invoker,
+ "*",
+ [
+ "deps",
+ "outputs",
+ "public_deps",
+ "sources",
+ ])
+
+ sources = _outputs
+ outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ]
+ public_deps = [ ":$_copy_target_name" ]
+ }
+ }
+}
+
+# Those templates are specialisation of the asset_catalog template for known
+# types of asset catalog types (imageset, launchimage, appiconset).
+#
+# Arguments
+#
+# sources:
+# required, list of strings, paths to the file contained in the
+# asset catalog directory; this must contain the Contents.json file
+# and all the image referenced by it (not enforced by the template).
+#
+template("appiconset") {
+ asset_catalog(target_name) {
+ forward_variables_from(invoker, "*", [ "asset_type" ])
+ asset_type = "appiconset"
+ }
+}
+template("colorset") {
+ asset_catalog(target_name) {
+ forward_variables_from(invoker, "*", [ "asset_type" ])
+ asset_type = "colorset"
+ }
+}
+template("imageset") {
+ asset_catalog(target_name) {
+ forward_variables_from(invoker, "*", [ "asset_type" ])
+ asset_type = "imageset"
+ }
+}
+template("launchimage") {
+ asset_catalog(target_name) {
+ forward_variables_from(invoker, "*", [ "asset_type" ])
+ asset_type = "launchimage"
+ }
+}
diff --git a/third_party/libwebrtc/build/config/ios/codesign.py b/third_party/libwebrtc/build/config/ios/codesign.py
new file mode 100644
index 0000000000..15d25a78df
--- /dev/null
+++ b/third_party/libwebrtc/build/config/ios/codesign.py
@@ -0,0 +1,691 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from __future__ import print_function
+
+import argparse
+import codecs
+import datetime
+import fnmatch
+import glob
+import json
+import os
+import plistlib
+import shutil
+import subprocess
+import sys
+import tempfile
+
+if sys.version_info.major < 3:
+ basestring_compat = basestring
+else:
+ basestring_compat = str
+
+
+def GetProvisioningProfilesDir():
+ """Returns the location of the installed mobile provisioning profiles.
+
+ Returns:
+ The path to the directory containing the installed mobile provisioning
+ profiles as a string.
+ """
+ return os.path.join(
+ os.environ['HOME'], 'Library', 'MobileDevice', 'Provisioning Profiles')
+
+
+def ReadPlistFromString(plist_bytes):
+ """Parse property list from given |plist_bytes|.
+
+ Args:
+ plist_bytes: contents of property list to load. Must be bytes in python 3.
+
+ Returns:
+ The contents of property list as a python object.
+ """
+ if sys.version_info.major == 2:
+ return plistlib.readPlistFromString(plist_bytes)
+ else:
+ return plistlib.loads(plist_bytes)
+
+
+def LoadPlistFile(plist_path):
+ """Loads property list file at |plist_path|.
+
+ Args:
+ plist_path: path to the property list file to load.
+
+ Returns:
+ The content of the property list file as a python object.
+ """
+ if sys.version_info.major == 2:
+ return plistlib.readPlistFromString(
+ subprocess.check_output(
+ ['xcrun', 'plutil', '-convert', 'xml1', '-o', '-', plist_path]))
+ else:
+ with open(plist_path, 'rb') as fp:
+ return plistlib.load(fp)
+
+
+def CreateSymlink(value, location):
+ """Creates symlink with value at location if the target exists."""
+ target = os.path.join(os.path.dirname(location), value)
+ if os.path.exists(location):
+ os.unlink(location)
+ os.symlink(value, location)
+
+
+class Bundle(object):
+ """Wraps a bundle."""
+
+ def __init__(self, bundle_path, platform):
+ """Initializes the Bundle object with data from bundle Info.plist file."""
+ self._path = bundle_path
+ self._kind = Bundle.Kind(platform, os.path.splitext(bundle_path)[-1])
+ self._data = None
+
+ def Load(self):
+ self._data = LoadPlistFile(self.info_plist_path)
+
+ @staticmethod
+ def Kind(platform, extension):
+ if platform == 'iphonesimulator' or platform == 'iphoneos':
+ return 'ios'
+ if platform == 'macosx':
+ if extension == '.framework':
+ return 'mac_framework'
+ return 'mac'
+ raise ValueError('unknown bundle type %s for %s' % (extension, platform))
+
+ @property
+ def kind(self):
+ return self._kind
+
+ @property
+ def path(self):
+ return self._path
+
+ @property
+ def contents_dir(self):
+ if self._kind == 'mac':
+ return os.path.join(self.path, 'Contents')
+ if self._kind == 'mac_framework':
+ return os.path.join(self.path, 'Versions/A')
+ return self.path
+
+ @property
+ def executable_dir(self):
+ if self._kind == 'mac':
+ return os.path.join(self.contents_dir, 'MacOS')
+ return self.contents_dir
+
+ @property
+ def resources_dir(self):
+ if self._kind == 'mac' or self._kind == 'mac_framework':
+ return os.path.join(self.contents_dir, 'Resources')
+ return self.path
+
+ @property
+ def info_plist_path(self):
+ if self._kind == 'mac_framework':
+ return os.path.join(self.resources_dir, 'Info.plist')
+ return os.path.join(self.contents_dir, 'Info.plist')
+
+ @property
+ def signature_dir(self):
+ return os.path.join(self.contents_dir, '_CodeSignature')
+
+ @property
+ def identifier(self):
+ return self._data['CFBundleIdentifier']
+
+ @property
+ def binary_name(self):
+ return self._data['CFBundleExecutable']
+
+ @property
+ def binary_path(self):
+ return os.path.join(self.executable_dir, self.binary_name)
+
+ def Validate(self, expected_mappings):
+ """Checks that keys in the bundle have the expected value.
+
+ Args:
+ expected_mappings: a dictionary of string to object, each mapping will
+ be looked up in the bundle data to check it has the same value (missing
+ values will be ignored)
+
+ Returns:
+ A dictionary of the key with a different value between expected_mappings
+ and the content of the bundle (i.e. errors) so that caller can format the
+ error message. The dictionary will be empty if there are no errors.
+ """
+ errors = {}
+ for key, expected_value in expected_mappings.items():
+ if key in self._data:
+ value = self._data[key]
+ if value != expected_value:
+ errors[key] = (value, expected_value)
+ return errors
+
+
+class ProvisioningProfile(object):
+ """Wraps a mobile provisioning profile file."""
+
+ def __init__(self, provisioning_profile_path):
+ """Initializes the ProvisioningProfile with data from profile file."""
+ self._path = provisioning_profile_path
+ self._data = ReadPlistFromString(
+ subprocess.check_output([
+ 'xcrun', 'security', 'cms', '-D', '-u', 'certUsageAnyCA', '-i',
+ provisioning_profile_path
+ ]))
+
+ @property
+ def path(self):
+ return self._path
+
+ @property
+ def team_identifier(self):
+ return self._data.get('TeamIdentifier', [''])[0]
+
+ @property
+ def name(self):
+ return self._data.get('Name', '')
+
+ @property
+ def application_identifier_pattern(self):
+ return self._data.get('Entitlements', {}).get('application-identifier', '')
+
+ @property
+ def application_identifier_prefix(self):
+ return self._data.get('ApplicationIdentifierPrefix', [''])[0]
+
+ @property
+ def entitlements(self):
+ return self._data.get('Entitlements', {})
+
+ @property
+ def expiration_date(self):
+ return self._data.get('ExpirationDate', datetime.datetime.now())
+
+ def ValidToSignBundle(self, bundle_identifier):
+ """Checks whether the provisioning profile can sign bundle_identifier.
+
+ Args:
+ bundle_identifier: the identifier of the bundle that needs to be signed.
+
+ Returns:
+ True if the mobile provisioning profile can be used to sign a bundle
+ with the corresponding bundle_identifier, False otherwise.
+ """
+ return fnmatch.fnmatch(
+ '%s.%s' % (self.application_identifier_prefix, bundle_identifier),
+ self.application_identifier_pattern)
+
+ def Install(self, installation_path):
+ """Copies mobile provisioning profile info to |installation_path|."""
+ shutil.copy2(self.path, installation_path)
+
+
+class Entitlements(object):
+ """Wraps an Entitlement plist file."""
+
+ def __init__(self, entitlements_path):
+ """Initializes Entitlements object from entitlement file."""
+ self._path = entitlements_path
+ self._data = LoadPlistFile(self._path)
+
+ @property
+ def path(self):
+ return self._path
+
+ def ExpandVariables(self, substitutions):
+ self._data = self._ExpandVariables(self._data, substitutions)
+
+ def _ExpandVariables(self, data, substitutions):
+ if isinstance(data, basestring_compat):
+ for key, substitution in substitutions.items():
+ data = data.replace('$(%s)' % (key,), substitution)
+ return data
+
+ if isinstance(data, dict):
+ for key, value in data.items():
+ data[key] = self._ExpandVariables(value, substitutions)
+ return data
+
+ if isinstance(data, list):
+ for i, value in enumerate(data):
+ data[i] = self._ExpandVariables(value, substitutions)
+
+ return data
+
+ def LoadDefaults(self, defaults):
+ for key, value in defaults.items():
+ if key not in self._data:
+ self._data[key] = value
+
+ def WriteTo(self, target_path):
+ with open(target_path, 'wb') as fp:
+ if sys.version_info.major == 2:
+ plistlib.writePlist(self._data, fp)
+ else:
+ plistlib.dump(self._data, fp)
+
+
+def FindProvisioningProfile(bundle_identifier, required):
+ """Finds mobile provisioning profile to use to sign bundle.
+
+ Args:
+ bundle_identifier: the identifier of the bundle to sign.
+
+ Returns:
+ The ProvisioningProfile object that can be used to sign the Bundle
+ object or None if no matching provisioning profile was found.
+ """
+ provisioning_profile_paths = glob.glob(
+ os.path.join(GetProvisioningProfilesDir(), '*.mobileprovision'))
+
+ # Iterate over all installed mobile provisioning profiles and filter those
+ # that can be used to sign the bundle, ignoring expired ones.
+ now = datetime.datetime.now()
+ valid_provisioning_profiles = []
+ one_hour = datetime.timedelta(0, 3600)
+ for provisioning_profile_path in provisioning_profile_paths:
+ provisioning_profile = ProvisioningProfile(provisioning_profile_path)
+ if provisioning_profile.expiration_date - now < one_hour:
+ sys.stderr.write(
+ 'Warning: ignoring expired provisioning profile: %s.\n' %
+ provisioning_profile_path)
+ continue
+ if provisioning_profile.ValidToSignBundle(bundle_identifier):
+ valid_provisioning_profiles.append(provisioning_profile)
+
+ if not valid_provisioning_profiles:
+ if required:
+ sys.stderr.write(
+ 'Error: no mobile provisioning profile found for "%s".\n' %
+ bundle_identifier)
+ sys.exit(1)
+ return None
+
+ # Select the most specific mobile provisioning profile, i.e. the one with
+ # the longest application identifier pattern (prefer the one with the latest
+ # expiration date as a secondary criteria).
+ selected_provisioning_profile = max(
+ valid_provisioning_profiles,
+ key=lambda p: (len(p.application_identifier_pattern), p.expiration_date))
+
+ one_week = datetime.timedelta(7)
+ if selected_provisioning_profile.expiration_date - now < 2 * one_week:
+ sys.stderr.write(
+ 'Warning: selected provisioning profile will expire soon: %s' %
+ selected_provisioning_profile.path)
+ return selected_provisioning_profile
+
+
+def CodeSignBundle(bundle_path, identity, extra_args):
+ process = subprocess.Popen(
+ ['xcrun', 'codesign', '--force', '--sign', identity, '--timestamp=none'] +
+ list(extra_args) + [bundle_path],
+ stderr=subprocess.PIPE,
+ universal_newlines=True)
+ _, stderr = process.communicate()
+ if process.returncode:
+ sys.stderr.write(stderr)
+ sys.exit(process.returncode)
+ for line in stderr.splitlines():
+ if line.endswith(': replacing existing signature'):
+ # Ignore warning about replacing existing signature as this should only
+ # happen when re-signing system frameworks (and then it is expected).
+ continue
+ sys.stderr.write(line)
+ sys.stderr.write('\n')
+
+
+def InstallSystemFramework(framework_path, bundle_path, args):
+ """Install framework from |framework_path| to |bundle| and code-re-sign it."""
+ installed_framework_path = os.path.join(
+ bundle_path, 'Frameworks', os.path.basename(framework_path))
+
+ if os.path.isfile(framework_path):
+ shutil.copy(framework_path, installed_framework_path)
+ elif os.path.isdir(framework_path):
+ if os.path.exists(installed_framework_path):
+ shutil.rmtree(installed_framework_path)
+ shutil.copytree(framework_path, installed_framework_path)
+
+ CodeSignBundle(installed_framework_path, args.identity,
+ ['--deep', '--preserve-metadata=identifier,entitlements,flags'])
+
+
+def GenerateEntitlements(path, provisioning_profile, bundle_identifier):
+ """Generates an entitlements file.
+
+ Args:
+ path: path to the entitlements template file
+ provisioning_profile: ProvisioningProfile object to use, may be None
+ bundle_identifier: identifier of the bundle to sign.
+ """
+ entitlements = Entitlements(path)
+ if provisioning_profile:
+ entitlements.LoadDefaults(provisioning_profile.entitlements)
+ app_identifier_prefix = \
+ provisioning_profile.application_identifier_prefix + '.'
+ else:
+ app_identifier_prefix = '*.'
+ entitlements.ExpandVariables({
+ 'CFBundleIdentifier': bundle_identifier,
+ 'AppIdentifierPrefix': app_identifier_prefix,
+ })
+ return entitlements
+
+
+def GenerateBundleInfoPlist(bundle, plist_compiler, partial_plist):
+ """Generates the bundle Info.plist for a list of partial .plist files.
+
+ Args:
+ bundle: a Bundle instance
+ plist_compiler: string, path to the Info.plist compiler
+ partial_plist: list of path to partial .plist files to merge
+ """
+
+ # Filter empty partial .plist files (this happens if an application
+ # does not compile any asset catalog, in which case the partial .plist
+ # file from the asset catalog compilation step is just a stamp file).
+ filtered_partial_plist = []
+ for plist in partial_plist:
+ plist_size = os.stat(plist).st_size
+ if plist_size:
+ filtered_partial_plist.append(plist)
+
+ # Invoke the plist_compiler script. It needs to be a python script.
+ subprocess.check_call([
+ 'python',
+ plist_compiler,
+ 'merge',
+ '-f',
+ 'binary1',
+ '-o',
+ bundle.info_plist_path,
+ ] + filtered_partial_plist)
+
+
+class Action(object):
+ """Class implementing one action supported by the script."""
+
+ @classmethod
+ def Register(cls, subparsers):
+ parser = subparsers.add_parser(cls.name, help=cls.help)
+ parser.set_defaults(func=cls._Execute)
+ cls._Register(parser)
+
+
+class CodeSignBundleAction(Action):
+ """Class implementing the code-sign-bundle action."""
+
+ name = 'code-sign-bundle'
+ help = 'perform code signature for a bundle'
+
+ @staticmethod
+ def _Register(parser):
+ parser.add_argument(
+ '--entitlements', '-e', dest='entitlements_path',
+ help='path to the entitlements file to use')
+ parser.add_argument(
+ 'path', help='path to the iOS bundle to codesign')
+ parser.add_argument(
+ '--identity', '-i', required=True,
+ help='identity to use to codesign')
+ parser.add_argument(
+ '--binary', '-b', required=True,
+ help='path to the iOS bundle binary')
+ parser.add_argument(
+ '--framework', '-F', action='append', default=[], dest='frameworks',
+ help='install and resign system framework')
+ parser.add_argument(
+ '--disable-code-signature', action='store_true', dest='no_signature',
+ help='disable code signature')
+ parser.add_argument(
+ '--disable-embedded-mobileprovision', action='store_false',
+ default=True, dest='embedded_mobileprovision',
+ help='disable finding and embedding mobileprovision')
+ parser.add_argument(
+ '--platform', '-t', required=True,
+ help='platform the signed bundle is targeting')
+ parser.add_argument(
+ '--partial-info-plist', '-p', action='append', default=[],
+ help='path to partial Info.plist to merge to create bundle Info.plist')
+ parser.add_argument(
+ '--plist-compiler-path', '-P', action='store',
+ help='path to the plist compiler script (for --partial-info-plist)')
+ parser.set_defaults(no_signature=False)
+
+ @staticmethod
+ def _Execute(args):
+ if not args.identity:
+ args.identity = '-'
+
+ bundle = Bundle(args.path, args.platform)
+
+ if args.partial_info_plist:
+ GenerateBundleInfoPlist(bundle, args.plist_compiler_path,
+ args.partial_info_plist)
+
+ # The bundle Info.plist may have been updated by GenerateBundleInfoPlist()
+ # above. Load the bundle information from Info.plist after the modification
+ # have been written to disk.
+ bundle.Load()
+
+ # According to Apple documentation, the application binary must be the same
+ # as the bundle name without the .app suffix. See crbug.com/740476 for more
+ # information on what problem this can cause.
+ #
+ # To prevent this class of error, fail with an error if the binary name is
+ # incorrect in the Info.plist as it is not possible to update the value in
+ # Info.plist at this point (the file has been copied by a different target
+ # and ninja would consider the build dirty if it was updated).
+ #
+ # Also checks that the name of the bundle is correct too (does not cause the
+ # build to be considered dirty, but still terminate the script in case of an
+ # incorrect bundle name).
+ #
+ # Apple documentation is available at:
+ # https://developer.apple.com/library/content/documentation/CoreFoundation/Conceptual/CFBundles/BundleTypes/BundleTypes.html
+ bundle_name = os.path.splitext(os.path.basename(bundle.path))[0]
+ errors = bundle.Validate({
+ 'CFBundleName': bundle_name,
+ 'CFBundleExecutable': bundle_name,
+ })
+ if errors:
+ for key in sorted(errors):
+ value, expected_value = errors[key]
+ sys.stderr.write('%s: error: %s value incorrect: %s != %s\n' % (
+ bundle.path, key, value, expected_value))
+ sys.stderr.flush()
+ sys.exit(1)
+
+ # Delete existing embedded mobile provisioning.
+ embedded_provisioning_profile = os.path.join(
+ bundle.path, 'embedded.mobileprovision')
+ if os.path.isfile(embedded_provisioning_profile):
+ os.unlink(embedded_provisioning_profile)
+
+ # Delete existing code signature.
+ if os.path.exists(bundle.signature_dir):
+ shutil.rmtree(bundle.signature_dir)
+
+ # Install system frameworks if requested.
+ for framework_path in args.frameworks:
+ InstallSystemFramework(framework_path, args.path, args)
+
+ # Copy main binary into bundle.
+ if not os.path.isdir(bundle.executable_dir):
+ os.makedirs(bundle.executable_dir)
+ shutil.copy(args.binary, bundle.binary_path)
+
+ if bundle.kind == 'mac_framework':
+ # Create Versions/Current -> Versions/A symlink
+ CreateSymlink('A', os.path.join(bundle.path, 'Versions/Current'))
+
+ # Create $binary_name -> Versions/Current/$binary_name symlink
+ CreateSymlink(os.path.join('Versions/Current', bundle.binary_name),
+ os.path.join(bundle.path, bundle.binary_name))
+
+ # Create optional symlinks.
+ for name in ('Headers', 'Resources', 'Modules'):
+ target = os.path.join(bundle.path, 'Versions/A', name)
+ if os.path.exists(target):
+ CreateSymlink(os.path.join('Versions/Current', name),
+ os.path.join(bundle.path, name))
+ else:
+ obsolete_path = os.path.join(bundle.path, name)
+ if os.path.exists(obsolete_path):
+ os.unlink(obsolete_path)
+
+ if args.no_signature:
+ return
+
+ codesign_extra_args = []
+
+ if args.embedded_mobileprovision:
+ # Find mobile provisioning profile and embeds it into the bundle (if a
+ # code signing identify has been provided, fails if no valid mobile
+ # provisioning is found).
+ provisioning_profile_required = args.identity != '-'
+ provisioning_profile = FindProvisioningProfile(
+ bundle.identifier, provisioning_profile_required)
+ if provisioning_profile and args.platform != 'iphonesimulator':
+ provisioning_profile.Install(embedded_provisioning_profile)
+
+ if args.entitlements_path is not None:
+ temporary_entitlements_file = \
+ tempfile.NamedTemporaryFile(suffix='.xcent')
+ codesign_extra_args.extend(
+ ['--entitlements', temporary_entitlements_file.name])
+
+ entitlements = GenerateEntitlements(
+ args.entitlements_path, provisioning_profile, bundle.identifier)
+ entitlements.WriteTo(temporary_entitlements_file.name)
+
+ CodeSignBundle(bundle.path, args.identity, codesign_extra_args)
+
+
+class CodeSignFileAction(Action):
+ """Class implementing code signature for a single file."""
+
+ name = 'code-sign-file'
+ help = 'code-sign a single file'
+
+ @staticmethod
+ def _Register(parser):
+ parser.add_argument(
+ 'path', help='path to the file to codesign')
+ parser.add_argument(
+ '--identity', '-i', required=True,
+ help='identity to use to codesign')
+ parser.add_argument(
+ '--output', '-o',
+ help='if specified copy the file to that location before signing it')
+ parser.set_defaults(sign=True)
+
+ @staticmethod
+ def _Execute(args):
+ if not args.identity:
+ args.identity = '-'
+
+ install_path = args.path
+ if args.output:
+
+ if os.path.isfile(args.output):
+ os.unlink(args.output)
+ elif os.path.isdir(args.output):
+ shutil.rmtree(args.output)
+
+ if os.path.isfile(args.path):
+ shutil.copy(args.path, args.output)
+ elif os.path.isdir(args.path):
+ shutil.copytree(args.path, args.output)
+
+ install_path = args.output
+
+ CodeSignBundle(install_path, args.identity,
+ ['--deep', '--preserve-metadata=identifier,entitlements'])
+
+
+class GenerateEntitlementsAction(Action):
+ """Class implementing the generate-entitlements action."""
+
+ name = 'generate-entitlements'
+ help = 'generate entitlements file'
+
+ @staticmethod
+ def _Register(parser):
+ parser.add_argument(
+ '--entitlements', '-e', dest='entitlements_path',
+ help='path to the entitlements file to use')
+ parser.add_argument(
+ 'path', help='path to the entitlements file to generate')
+ parser.add_argument(
+ '--info-plist', '-p', required=True,
+ help='path to the bundle Info.plist')
+
+ @staticmethod
+ def _Execute(args):
+ info_plist = LoadPlistFile(args.info_plist)
+ bundle_identifier = info_plist['CFBundleIdentifier']
+ provisioning_profile = FindProvisioningProfile(bundle_identifier, False)
+ entitlements = GenerateEntitlements(
+ args.entitlements_path, provisioning_profile, bundle_identifier)
+ entitlements.WriteTo(args.path)
+
+
+class FindProvisioningProfileAction(Action):
+ """Class implementing the find-codesign-identity action."""
+
+ name = 'find-provisioning-profile'
+ help = 'find provisioning profile for use by Xcode project generator'
+
+ @staticmethod
+ def _Register(parser):
+ parser.add_argument('--bundle-id',
+ '-b',
+ required=True,
+ help='bundle identifier')
+
+ @staticmethod
+ def _Execute(args):
+ provisioning_profile_info = {}
+ provisioning_profile = FindProvisioningProfile(args.bundle_id, False)
+ for key in ('team_identifier', 'name'):
+ if provisioning_profile:
+ provisioning_profile_info[key] = getattr(provisioning_profile, key)
+ else:
+ provisioning_profile_info[key] = ''
+ print(json.dumps(provisioning_profile_info))
+
+
+def Main():
+ # Cache this codec so that plistlib can find it. See
+ # https://crbug.com/999461#c12 for more details.
+ codecs.lookup('utf-8')
+
+ parser = argparse.ArgumentParser('codesign iOS bundles')
+ subparsers = parser.add_subparsers()
+
+ actions = [
+ CodeSignBundleAction,
+ CodeSignFileAction,
+ GenerateEntitlementsAction,
+ FindProvisioningProfileAction,
+ ]
+
+ for action in actions:
+ action.Register(subparsers)
+
+ args = parser.parse_args()
+ args.func(args)
+
+
+if __name__ == '__main__':
+ sys.exit(Main())
diff --git a/third_party/libwebrtc/build/config/ios/compile_ib_files.py b/third_party/libwebrtc/build/config/ios/compile_ib_files.py
new file mode 100644
index 0000000000..84781c1773
--- /dev/null
+++ b/third_party/libwebrtc/build/config/ios/compile_ib_files.py
@@ -0,0 +1,57 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from __future__ import print_function
+
+import argparse
+import logging
+import os
+import re
+import subprocess
+import sys
+
+
+def main():
+ parser = argparse.ArgumentParser(
+ description='A script to compile xib and storyboard.',
+ fromfile_prefix_chars='@')
+ parser.add_argument('-o', '--output', required=True,
+ help='Path to output bundle.')
+ parser.add_argument('-i', '--input', required=True,
+ help='Path to input xib or storyboard.')
+ args, unknown_args = parser.parse_known_args()
+
+ ibtool_args = [
+ 'xcrun', 'ibtool',
+ '--errors', '--warnings', '--notices',
+ '--output-format', 'human-readable-text'
+ ]
+ ibtool_args += unknown_args
+ ibtool_args += [
+ '--compile',
+ os.path.abspath(args.output),
+ os.path.abspath(args.input)
+ ]
+
+ ibtool_section_re = re.compile(r'/\*.*\*/')
+ ibtool_re = re.compile(r'.*note:.*is clipping its content')
+ try:
+ stdout = subprocess.check_output(ibtool_args)
+ except subprocess.CalledProcessError as e:
+ print(e.output)
+ raise
+ current_section_header = None
+ for line in stdout.splitlines():
+ if ibtool_section_re.match(line):
+ current_section_header = line
+ elif not ibtool_re.match(line):
+ if current_section_header:
+ print(current_section_header)
+ current_section_header = None
+ print(line)
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/third_party/libwebrtc/build/config/ios/compile_xcassets_unittests.py b/third_party/libwebrtc/build/config/ios/compile_xcassets_unittests.py
new file mode 100644
index 0000000000..7655df8c05
--- /dev/null
+++ b/third_party/libwebrtc/build/config/ios/compile_xcassets_unittests.py
@@ -0,0 +1,141 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+import compile_xcassets
+
+
+class TestFilterCompilerOutput(unittest.TestCase):
+
+ relative_paths = {
+ '/Users/janedoe/chromium/src/Chromium.xcassets':
+ '../../Chromium.xcassets',
+ '/Users/janedoe/chromium/src/out/Default/Chromium.app/Assets.car':
+ 'Chromium.app/Assets.car',
+ }
+
+ def testNoError(self):
+ self.assertEquals(
+ '',
+ compile_xcassets.FilterCompilerOutput(
+ '/* com.apple.actool.compilation-results */\n'
+ '/Users/janedoe/chromium/src/out/Default/Chromium.app/Assets.car\n',
+ self.relative_paths))
+
+ def testNoErrorRandomMessages(self):
+ self.assertEquals(
+ '',
+ compile_xcassets.FilterCompilerOutput(
+ '2017-07-04 04:59:19.460 ibtoold[23487:41214] CoreSimulator is att'
+ 'empting to unload a stale CoreSimulatorService job. Existing'
+ ' job (com.apple.CoreSimulator.CoreSimulatorService.179.1.E8tt'
+ 'yeDeVgWK) is from an older version and is being removed to pr'
+ 'event problems.\n'
+ '/* com.apple.actool.compilation-results */\n'
+ '/Users/janedoe/chromium/src/out/Default/Chromium.app/Assets.car\n',
+ self.relative_paths))
+
+ def testWarning(self):
+ self.assertEquals(
+ '/* com.apple.actool.document.warnings */\n'
+ '../../Chromium.xcassets:./image1.imageset/[universal][][][1x][][][]['
+ '][][]: warning: The file "image1.png" for the image set "image1"'
+ ' does not exist.\n',
+ compile_xcassets.FilterCompilerOutput(
+ '/* com.apple.actool.document.warnings */\n'
+ '/Users/janedoe/chromium/src/Chromium.xcassets:./image1.imageset/['
+ 'universal][][][1x][][][][][][]: warning: The file "image1.png'
+ '" for the image set "image1" does not exist.\n'
+ '/* com.apple.actool.compilation-results */\n'
+ '/Users/janedoe/chromium/src/out/Default/Chromium.app/Assets.car\n',
+ self.relative_paths))
+
+ def testError(self):
+ self.assertEquals(
+ '/* com.apple.actool.errors */\n'
+ '../../Chromium.xcassets: error: The output directory "/Users/janedoe/'
+ 'chromium/src/out/Default/Chromium.app" does not exist.\n',
+ compile_xcassets.FilterCompilerOutput(
+ '/* com.apple.actool.errors */\n'
+ '/Users/janedoe/chromium/src/Chromium.xcassets: error: The output '
+ 'directory "/Users/janedoe/chromium/src/out/Default/Chromium.a'
+ 'pp" does not exist.\n'
+ '/* com.apple.actool.compilation-results */\n',
+ self.relative_paths))
+
+ def testSpurious(self):
+ self.assertEquals(
+ '/* com.apple.actool.document.warnings */\n'
+ '../../Chromium.xcassets:./AppIcon.appiconset: warning: A 1024x1024 ap'
+ 'p store icon is required for iOS apps\n',
+ compile_xcassets.FilterCompilerOutput(
+ '/* com.apple.actool.document.warnings */\n'
+ '/Users/janedoe/chromium/src/Chromium.xcassets:./AppIcon.appiconse'
+ 't: warning: A 1024x1024 app store icon is required for iOS ap'
+ 'ps\n'
+ '/* com.apple.actool.document.notices */\n'
+ '/Users/janedoe/chromium/src/Chromium.xcassets:./AppIcon.appiconse'
+ 't/[][ipad][76x76][][][1x][][]: notice: (null)\n',
+ self.relative_paths))
+
+ def testComplexError(self):
+ self.assertEquals(
+ '/* com.apple.actool.errors */\n'
+ ': error: Failed to find a suitable device for the type SimDeviceType '
+ ': com.apple.dt.Xcode.IBSimDeviceType.iPad-2x with runtime SimRunt'
+ 'ime : 10.3.1 (14E8301) - com.apple.CoreSimulator.SimRuntime.iOS-1'
+ '0-3\n'
+ ' Failure Reason: Failed to create SimDeviceSet at path /Users/jane'
+ 'doe/Library/Developer/Xcode/UserData/IB Support/Simulator Devices'
+ '. You\'ll want to check the logs in ~/Library/Logs/CoreSimulator '
+ 'to see why creating the SimDeviceSet failed.\n'
+ ' Underlying Errors:\n'
+ ' Description: Failed to initialize simulator device set.\n'
+ ' Failure Reason: Failed to subscribe to notifications from Cor'
+ 'eSimulatorService.\n'
+ ' Underlying Errors:\n'
+ ' Description: Error returned in reply to notification requ'
+ 'est: Connection invalid\n'
+ ' Failure Reason: Software caused connection abort\n',
+ compile_xcassets.FilterCompilerOutput(
+ '2017-07-07 10:37:27.367 ibtoold[88538:12553239] CoreSimulator det'
+ 'ected Xcode.app relocation or CoreSimulatorService version ch'
+ 'ange. Framework path (/Applications/Xcode.app/Contents/Devel'
+ 'oper/Library/PrivateFrameworks/CoreSimulator.framework) and v'
+ 'ersion (375.21) does not match existing job path (/Library/De'
+ 'veloper/PrivateFrameworks/CoreSimulator.framework/Versions/A/'
+ 'XPCServices/com.apple.CoreSimulator.CoreSimulatorService.xpc)'
+ ' and version (459.13). Attempting to remove the stale servic'
+ 'e in order to add the expected version.\n'
+ '2017-07-07 10:37:27.625 ibtoold[88538:12553256] CoreSimulatorServ'
+ 'ice connection interrupted. Resubscribing to notifications.\n'
+ '2017-07-07 10:37:27.632 ibtoold[88538:12553264] CoreSimulatorServ'
+ 'ice connection became invalid. Simulator services will no lo'
+ 'nger be available.\n'
+ '2017-07-07 10:37:27.642 ibtoold[88538:12553274] CoreSimulatorServ'
+ 'ice connection became invalid. Simulator services will no lo'
+ 'nger be available.\n'
+ '/* com.apple.actool.errors */\n'
+ ': error: Failed to find a suitable device for the type SimDeviceT'
+ 'ype : com.apple.dt.Xcode.IBSimDeviceType.iPad-2x with runtime'
+ ' SimRuntime : 10.3.1 (14E8301) - com.apple.CoreSimulator.SimR'
+ 'untime.iOS-10-3\n'
+ ' Failure Reason: Failed to create SimDeviceSet at path /Users/'
+ 'janedoe/Library/Developer/Xcode/UserData/IB Support/Simulator'
+ ' Devices. You\'ll want to check the logs in ~/Library/Logs/Co'
+ 'reSimulator to see why creating the SimDeviceSet failed.\n'
+ ' Underlying Errors:\n'
+ ' Description: Failed to initialize simulator device set.\n'
+ ' Failure Reason: Failed to subscribe to notifications from'
+ ' CoreSimulatorService.\n'
+ ' Underlying Errors:\n'
+ ' Description: Error returned in reply to notification '
+ 'request: Connection invalid\n'
+ ' Failure Reason: Software caused connection abort\n'
+ '/* com.apple.actool.compilation-results */\n',
+ self.relative_paths))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/third_party/libwebrtc/build/config/ios/config.gni b/third_party/libwebrtc/build/config/ios/config.gni
new file mode 100644
index 0000000000..358c7ccd2a
--- /dev/null
+++ b/third_party/libwebrtc/build/config/ios/config.gni
@@ -0,0 +1,28 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+declare_args() {
+ # Configure the environment for which to build. Could be either "device",
+ # "simulator" or "catalyst". If unspecified, then it will be assumed to be
+ # "simulator" if the target_cpu is "x68" or "x64", "device" otherwise. The
+ # default is only there for compatibility reasons and will be removed (see
+ # crbug.com/1138425 for more details).
+ target_environment = ""
+
+ # Control whether cronet is built (this is usually set by the script
+ # components/cronet/tools/cr_cronet.py as cronet requires specific
+ # gn args to build correctly).
+ is_cronet_build = false
+}
+
+if (target_environment == "") {
+ if (target_cpu == "x86" || target_cpu == "x64") {
+ target_environment = "simulator"
+ } else {
+ target_environment = "device"
+ }
+}
+
+assert(target_environment == "simulator" || target_environment == "device" ||
+ target_environment == "catalyst")
diff --git a/third_party/libwebrtc/build/config/ios/dummy.py b/third_party/libwebrtc/build/config/ios/dummy.py
new file mode 100644
index 0000000000..b23b7dab96
--- /dev/null
+++ b/third_party/libwebrtc/build/config/ios/dummy.py
@@ -0,0 +1,15 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Empty script that does nothing and return success error code.
+
+This script is used by some gn targets that pretend creating some output
+but instead depend on another target creating the output indirectly (in
+general this output is a directory that is used as input by a bundle_data
+target).
+
+It ignores all parameters and terminate with a success error code. It
+does the same thing as the unix command "true", but gn can only invoke
+python scripts.
+"""
diff --git a/third_party/libwebrtc/build/config/ios/entitlements.plist b/third_party/libwebrtc/build/config/ios/entitlements.plist
new file mode 100644
index 0000000000..429762e3a3
--- /dev/null
+++ b/third_party/libwebrtc/build/config/ios/entitlements.plist
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>application-identifier</key>
+ <string>$(AppIdentifierPrefix)$(CFBundleIdentifier)</string>
+ <key>keychain-access-groups</key>
+ <array>
+ <string>$(AppIdentifierPrefix)$(CFBundleIdentifier)</string>
+ </array>
+</dict>
+</plist>
diff --git a/third_party/libwebrtc/build/config/ios/find_signing_identity.py b/third_party/libwebrtc/build/config/ios/find_signing_identity.py
new file mode 100644
index 0000000000..d508e2bb46
--- /dev/null
+++ b/third_party/libwebrtc/build/config/ios/find_signing_identity.py
@@ -0,0 +1,89 @@
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from __future__ import print_function
+
+import argparse
+import os
+import subprocess
+import sys
+import re
+
+
+def Redact(value, from_nth_char=5):
+ """Redact value past the N-th character."""
+ return value[:from_nth_char] + '*' * (len(value) - from_nth_char)
+
+
+class Identity(object):
+ """Represents a valid identity."""
+
+ def __init__(self, identifier, name, team):
+ self.identifier = identifier
+ self.name = name
+ self.team = team
+
+ def redacted(self):
+ return Identity(Redact(self.identifier), self.name, Redact(self.team))
+
+ def format(self):
+ return '%s: "%s (%s)"' % (self.identifier, self.name, self.team)
+
+
+def ListIdentities():
+ return subprocess.check_output([
+ 'xcrun',
+ 'security',
+ 'find-identity',
+ '-v',
+ '-p',
+ 'codesigning',
+ ]).decode('utf8')
+
+
+def FindValidIdentity(pattern):
+ """Find all identities matching the pattern."""
+ lines = list(l.strip() for l in ListIdentities().splitlines())
+ # Look for something like "2) XYZ "iPhone Developer: Name (ABC)""
+ regex = re.compile('[0-9]+\) ([A-F0-9]+) "([^"(]*) \(([^)"]*)\)"')
+
+ result = []
+ for line in lines:
+ res = regex.match(line)
+ if res is None:
+ continue
+ if pattern is None or pattern in res.group(2):
+ result.append(Identity(*res.groups()))
+ return result
+
+
+def Main(args):
+ parser = argparse.ArgumentParser('codesign iOS bundles')
+ parser.add_argument('--matching-pattern',
+ dest='pattern',
+ help='Pattern used to select the code signing identity.')
+ parsed = parser.parse_args(args)
+
+ identities = FindValidIdentity(parsed.pattern)
+ if len(identities) == 1:
+ print(identities[0].identifier, end='')
+ return 0
+
+ all_identities = FindValidIdentity(None)
+
+ print('Automatic code signing identity selection was enabled but could not')
+ print('find exactly one codesigning identity matching "%s".' % parsed.pattern)
+ print('')
+ print('Check that the keychain is accessible and that there is exactly one')
+ print('valid codesigning identity matching the pattern. Here is the parsed')
+ print('output of `xcrun security find-identity -v -p codesigning`:')
+ print()
+ for i, identity in enumerate(all_identities):
+ print(' %d) %s' % (i + 1, identity.redacted().format()))
+ print(' %d valid identities found' % (len(all_identities)))
+ return 1
+
+
+if __name__ == '__main__':
+ sys.exit(Main(sys.argv[1:]))
diff --git a/third_party/libwebrtc/build/config/ios/generate_umbrella_header.py b/third_party/libwebrtc/build/config/ios/generate_umbrella_header.py
new file mode 100644
index 0000000000..8547e18aa7
--- /dev/null
+++ b/third_party/libwebrtc/build/config/ios/generate_umbrella_header.py
@@ -0,0 +1,75 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Generates an umbrella header for an iOS framework."""
+
+import argparse
+import datetime
+import os
+import re
+import string
+
+
+HEADER_TEMPLATE = string.Template('''\
+// Copyright $year The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// This file is auto-generated by //build/ios/config/generate_umbrella_header.py
+
+#ifndef $header_guard
+#define $header_guard
+
+$imports
+
+#endif // $header_guard
+''')
+
+
+def ComputeHeaderGuard(file_path):
+ """Computes the header guard for a file path.
+
+ Args:
+ file_path: The path to convert into an header guard.
+ Returns:
+ The header guard string for the file_path.
+ """
+ return re.sub(r'[.+/\\]', r'_', file_path.upper()) + '_'
+
+
+def WriteUmbrellaHeader(output_path, imported_headers):
+ """Writes the umbrella header.
+
+ Args:
+ output_path: The path to the umbrella header.
+ imported_headers: A list of headers to #import in the umbrella header.
+ """
+ year = datetime.date.today().year
+ header_guard = ComputeHeaderGuard(output_path)
+ imports = '\n'.join([
+ '#import "%s"' % os.path.basename(header)
+ for header in sorted(imported_headers)
+ ])
+ with open(output_path, 'w') as output_file:
+ output_file.write(
+ HEADER_TEMPLATE.safe_substitute({
+ 'year': year,
+ 'header_guard': header_guard,
+ 'imports': imports,
+ }))
+
+
+def Main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--output-path', required=True, type=str,
+ help='Path to the generated umbrella header.')
+ parser.add_argument('imported_headers', type=str, nargs='+',
+ help='Headers to #import in the umbrella header.')
+ options = parser.parse_args()
+
+ return WriteUmbrellaHeader(options.output_path, options.imported_headers)
+
+
+if __name__ == '__main__':
+ Main()
diff --git a/third_party/libwebrtc/build/config/ios/hardlink.py b/third_party/libwebrtc/build/config/ios/hardlink.py
new file mode 100644
index 0000000000..38f60d4013
--- /dev/null
+++ b/third_party/libwebrtc/build/config/ios/hardlink.py
@@ -0,0 +1,71 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Recursively create hardlink to target named output."""
+
+
+import argparse
+import os
+import shutil
+
+
+def CreateHardlinkHelper(target, output):
+ """Recursively create a hardlink named output pointing to target.
+
+ Args:
+ target: path to an existing file or directory
+ output: path to the newly created hardlink
+
+ This function assumes that output does not exists but that the parent
+ directory containing output does. If those conditions are false, then
+ the function will fails with an exception corresponding to an OS error.
+ """
+ if os.path.islink(target):
+ os.symlink(os.readlink(target), output)
+ elif not os.path.isdir(target):
+ try:
+ os.link(target, output)
+ except:
+ shutil.copy(target, output)
+ else:
+ os.mkdir(output)
+ for name in os.listdir(target):
+ CreateHardlinkHelper(
+ os.path.join(target, name),
+ os.path.join(output, name))
+
+
+def CreateHardlink(target, output):
+ """Recursively create a hardlink named output pointing to target.
+
+ Args:
+ target: path to an existing file or directory
+ output: path to the newly created hardlink
+
+ If output already exists, it is first removed. In all cases, the
+ parent directory containing output is created.
+ """
+ if os.path.isdir(output):
+ shutil.rmtree(output)
+ elif os.path.exists(output):
+ os.unlink(output)
+
+ parent_dir = os.path.dirname(os.path.abspath(output))
+ if not os.path.isdir(parent_dir):
+ os.makedirs(parent_dir)
+
+ CreateHardlinkHelper(target, output)
+
+
+def Main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('target', help='path to the file or directory to link to')
+ parser.add_argument('output', help='name of the hardlink to create')
+ args = parser.parse_args()
+
+ CreateHardlink(args.target, args.output)
+
+
+if __name__ == '__main__':
+ Main()
diff --git a/third_party/libwebrtc/build/config/ios/ios_sdk.gni b/third_party/libwebrtc/build/config/ios/ios_sdk.gni
new file mode 100644
index 0000000000..ffff5921d8
--- /dev/null
+++ b/third_party/libwebrtc/build/config/ios/ios_sdk.gni
@@ -0,0 +1,185 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/ios/config.gni")
+import("//build/config/ios/ios_sdk_overrides.gni")
+import("//build/toolchain/goma.gni")
+import("//build/toolchain/goma.gni")
+import("//build/toolchain/toolchain.gni")
+import("//build_overrides/build.gni")
+
+assert(current_os == "ios")
+assert(use_system_xcode, "Hermetic xcode doesn't work for ios.")
+
+declare_args() {
+ # SDK path to use. When empty this will use the default SDK based on the
+ # value of target_environment.
+ ios_bin_path = ""
+ ios_sdk_path = ""
+ ios_sdk_name = ""
+ ios_sdk_version = ""
+ ios_sdk_platform = ""
+ ios_sdk_platform_path = ""
+ ios_toolchains_path = ""
+ xcode_version = ""
+ xcode_version_int = 0
+ xcode_build = ""
+ machine_os_build = ""
+
+ # Set DEVELOPER_DIR while running sdk_info.py.
+ ios_sdk_developer_dir = ""
+
+ # Control whether codesiging is enabled (ignored for simulator builds).
+ ios_enable_code_signing = true
+
+ # Explicitly select the identity to use for codesigning. If defined, must
+ # be set to a non-empty string that will be passed to codesigning. Can be
+ # left unspecified if ios_code_signing_identity_description is used instead.
+ ios_code_signing_identity = ""
+
+ # Pattern used to select the identity to use for codesigning. If defined,
+ # must be a substring of the description of exactly one of the identities by
+ # `security find-identity -v -p codesigning`.
+ ios_code_signing_identity_description = "Apple Development"
+
+ # Prefix for CFBundleIdentifier property of iOS bundles (correspond to the
+ # "Organization Identifier" in Xcode). Code signing will fail if no mobile
+ # provisioning for the selected code signing identify support that prefix.
+ ios_app_bundle_id_prefix = "org.chromium"
+
+ # If non-empty, this list must contain valid cpu architecture, and the final
+ # build will be a multi-architecture build (aka fat build) supporting the
+ # main $target_cpu architecture and all of $additional_target_cpus.
+ #
+ # For example to build an application that will run on both arm64 and armv7
+ # devices, you would use the following in args.gn file when running "gn args":
+ #
+ # target_os = "ios"
+ # target_cpu = "arm64"
+ # additional_target_cpus = [ "arm" ]
+ #
+ # You can also pass the value via "--args" parameter for "gn gen" command by
+ # using the syntax --args='additional_target_cpus=["arm"] target_cpu="arm64"'.
+ additional_target_cpus = []
+}
+
+declare_args() {
+ # This variable is set by the toolchain. It is set to true if the toolchain
+ # is a secondary toolchain as part of a "fat" build.
+ is_fat_secondary_toolchain = false
+
+ # This variable is set by the toolchain. It is the name of the primary
+ # toolchain for the fat build (could be current_toolchain).
+ primary_fat_toolchain_name = ""
+}
+
+# Official builds may not use goma.
+assert(!(use_goma && is_chrome_branded && is_official_build &&
+ target_cpu == "arm64"),
+ "goma use is forbidden for official iOS builds.")
+
+assert(custom_toolchain == "" || additional_target_cpus == [],
+ "cannot define both custom_toolchain and additional_target_cpus")
+
+# If codesigning is enabled, use must configure either a codesigning identity
+# or a filter to automatically select the codesigning identity.
+if (target_environment == "device" && ios_enable_code_signing) {
+ assert(ios_code_signing_identity == "" ||
+ ios_code_signing_identity_description == "",
+ "You should either specify the precise identity to use with " +
+ "ios_code_signing_identity or let the code select an identity " +
+ "automatically (via find_signing_identity.py which use the " +
+ "variable ios_code_signing_identity_description to set the " +
+ "pattern to match the identity to use).")
+}
+
+# Initialize additional_toolchains from additional_target_cpus. Assert here
+# that the list does not contains $target_cpu nor duplicates as this would
+# cause weird errors during the build.
+additional_toolchains = []
+if (additional_target_cpus != [] && !is_fat_secondary_toolchain) {
+ foreach(_additional_target_cpu, additional_target_cpus) {
+ assert(_additional_target_cpu != target_cpu,
+ "target_cpu must not be listed in additional_target_cpus")
+
+ _toolchain = "${current_toolchain}_fat_${_additional_target_cpu}"
+ foreach(_additional_toolchain, additional_toolchains) {
+ assert(_toolchain != _additional_toolchain,
+ "additional_target_cpus must not contains duplicate values")
+ }
+
+ additional_toolchains += [ _toolchain ]
+ }
+}
+
+if (ios_sdk_path == "") {
+ # Compute default target.
+ if (target_environment == "simulator") {
+ ios_sdk_name = "iphonesimulator"
+ ios_sdk_platform = "iPhoneSimulator"
+ } else if (target_environment == "device") {
+ ios_sdk_name = "iphoneos"
+ ios_sdk_platform = "iPhoneOS"
+ } else if (target_environment == "catalyst") {
+ ios_sdk_name = "macosx"
+ ios_sdk_platform = "MacOSX"
+ } else {
+ assert(false, "unsupported environment: $target_environment")
+ }
+
+ ios_sdk_info_args = [
+ "--get_sdk_info",
+ "--get_machine_info",
+ ]
+ ios_sdk_info_args += [ ios_sdk_name ]
+ if (ios_sdk_developer_dir != "") {
+ ios_sdk_info_args += [
+ "--developer_dir",
+ ios_sdk_developer_dir,
+ ]
+ }
+ if (use_system_xcode && use_goma) {
+ ios_sdk_info_args += [
+ "--create_symlink_at",
+ "sdk/xcode_links",
+ ]
+ }
+ script_name = "//build/config/apple/sdk_info.py"
+ _ios_sdk_result = exec_script(script_name, ios_sdk_info_args, "scope")
+ ios_bin_path =
+ rebase_path("${_ios_sdk_result.toolchains_path}/usr/bin/", root_build_dir)
+ ios_sdk_path = _ios_sdk_result.sdk_path
+ ios_sdk_platform_path = _ios_sdk_result.sdk_platform_path
+ ios_sdk_version = _ios_sdk_result.sdk_version
+ ios_sdk_build = _ios_sdk_result.sdk_build
+ ios_toolchains_path = _ios_sdk_result.toolchains_path
+ xcode_version = _ios_sdk_result.xcode_version
+ xcode_version_int = _ios_sdk_result.xcode_version_int
+ xcode_build = _ios_sdk_result.xcode_build
+ machine_os_build = _ios_sdk_result.machine_os_build
+ if (target_environment == "simulator") {
+ # This is weird, but Xcode sets DTPlatformBuild to an empty field for
+ # simulator builds.
+ ios_platform_build = ""
+ } else {
+ ios_platform_build = ios_sdk_build
+ }
+}
+
+if (target_environment == "device" && ios_enable_code_signing) {
+ # Automatically select a codesigning identity if no identity is configured.
+ # This only applies to device build as simulator builds are not signed.
+ if (ios_code_signing_identity == "") {
+ find_signing_identity_args = []
+ if (ios_code_signing_identity_description != "") {
+ find_signing_identity_args = [
+ "--matching-pattern",
+ ios_code_signing_identity_description,
+ ]
+ }
+ ios_code_signing_identity = exec_script("find_signing_identity.py",
+ find_signing_identity_args,
+ "trim string")
+ }
+}
diff --git a/third_party/libwebrtc/build/config/ios/ios_sdk_overrides.gni b/third_party/libwebrtc/build/config/ios/ios_sdk_overrides.gni
new file mode 100644
index 0000000000..12d52521da
--- /dev/null
+++ b/third_party/libwebrtc/build/config/ios/ios_sdk_overrides.gni
@@ -0,0 +1,17 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This file contains arguments that subprojects may choose to override. It
+# asserts that those overrides are used, to prevent unused args warnings.
+
+declare_args() {
+ # Version of iOS that we're targeting.
+ ios_deployment_target = "14.0"
+}
+
+# Always assert that ios_deployment_target is used on non-iOS platforms to
+# prevent unused args warnings.
+if (!is_ios) {
+ assert(ios_deployment_target == "14.0" || true)
+}
diff --git a/third_party/libwebrtc/build/config/ios/ios_test_runner_wrapper.gni b/third_party/libwebrtc/build/config/ios/ios_test_runner_wrapper.gni
new file mode 100644
index 0000000000..115db7ffdb
--- /dev/null
+++ b/third_party/libwebrtc/build/config/ios/ios_test_runner_wrapper.gni
@@ -0,0 +1,143 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/coverage/coverage.gni")
+import("//build/config/ios/ios_sdk.gni")
+import("//build/util/generate_wrapper.gni")
+
+# Invokes generate_wrapper to create an executable script wrapping iOS'
+# run.py with baked in arguments. Only takes effect when test entry in
+# gn_isolate_map.pyl is updated to type="generated_script" with script
+# set to the wrapper output path.
+#
+# Arguments:
+#
+# data
+# (optional, default [ "//ios/build/bots/scripts/" ]) list of files or
+# directories required to run target
+#
+# data_deps
+# (optional) list of target non-linked labels
+#
+# deps
+# (optional) list of files or directories required to run target
+#
+# executable_args
+# (optional) a list of string arguments to pass to run.py
+#
+# retries
+# (optional, default 3) number of retry attempts
+#
+# shards
+# (optional, default 1) number of shards to execute tests in parallel. not
+# the same as swarming shards.
+#
+# wrapper_output_name
+# (optional, default "run_${target_name}") name of the wrapper script
+#
+template("ios_test_runner_wrapper") {
+ generate_wrapper(target_name) {
+ forward_variables_from(invoker,
+ [
+ "deps",
+ "retries",
+ "shards",
+ "wrapper_output_name",
+ ])
+ testonly = true
+ executable = "//testing/test_env.py"
+
+ # iOS main test runner
+ _runner_path =
+ rebase_path("//ios/build/bots/scripts/run.py", root_build_dir)
+
+ executable_args = [ "@WrappedPath(${_runner_path})" ]
+
+ # arguments passed to run.py
+ if (defined(invoker.executable_args)) {
+ executable_args += invoker.executable_args
+ }
+
+ _rebased_mac_toolchain = rebase_path("//mac_toolchain", root_build_dir)
+ _rebased_xcode_path = rebase_path("//Xcode.app", root_build_dir)
+ _rebased_ios_runtime_cache_prefix =
+ rebase_path("//Runtime-ios-", root_build_dir)
+
+ # --out-dir argument is specified in gn_isolate_map.pyl because
+ # ${ISOLATED_OUTDIR} doesn't get resolved through this wrapper.
+ executable_args += [
+ "--xcode-path",
+ "@WrappedPath(${_rebased_xcode_path})",
+ "--mac-toolchain-cmd",
+ "@WrappedPath(${_rebased_mac_toolchain})",
+ "--runtime-cache-prefix",
+ "@WrappedPath(${_rebased_ios_runtime_cache_prefix})",
+ ]
+
+ # Default retries to 3
+ if (!defined(retries)) {
+ retries = 3
+ }
+ executable_args += [
+ "--retries",
+ "${retries}",
+ ]
+
+ # Default shards to 1
+ if (!defined(shards)) {
+ shards = 1
+ }
+ executable_args += [
+ "--shards",
+ "${shards}",
+ ]
+
+ data_deps = [ "//testing:test_scripts_shared" ]
+ if (defined(invoker.data_deps)) {
+ data_deps += invoker.data_deps
+ }
+
+ # test runner relies on iossim for simulator builds.
+ if (target_environment == "simulator") {
+ _rebased_root_build_dir = rebase_path("${root_build_dir}", root_build_dir)
+ data_deps += [ "//testing/iossim" ]
+
+ executable_args += [
+ "--iossim",
+ "@WrappedPath(${_rebased_root_build_dir}/iossim)",
+ ]
+ }
+
+ if (use_clang_coverage) {
+ executable_args += [ "--use-clang-coverage" ]
+ }
+
+ if (!is_debug) {
+ executable_args += [ "--release" ]
+ }
+
+ # wrapper script output name and path
+ if (!defined(wrapper_output_name)) {
+ _wrapper_output_name = "run_${target_name}"
+ } else {
+ _wrapper_output_name = wrapper_output_name
+ }
+
+ # Test targets may attempt to generate multiple wrappers for a suite with
+ # multiple different toolchains when running with additional_target_cpus.
+ # Generate the wrapper script into root_out_dir rather than root_build_dir
+ # to ensure those wrappers are distinct.
+ wrapper_script = "${root_out_dir}/bin/${_wrapper_output_name}"
+
+ data = []
+ if (defined(invoker.data)) {
+ data += invoker.data
+ }
+ data += [
+ "//.vpython",
+ "//ios/build/bots/scripts/",
+ "//testing/test_env.py",
+ ]
+ }
+}
diff --git a/third_party/libwebrtc/build/config/ios/resources/XCTRunnerAddition+Info.plist b/third_party/libwebrtc/build/config/ios/resources/XCTRunnerAddition+Info.plist
new file mode 100644
index 0000000000..cf9463f694
--- /dev/null
+++ b/third_party/libwebrtc/build/config/ios/resources/XCTRunnerAddition+Info.plist
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleIdentifier</key>
+ <string>com.apple.test.${EXECUTABLE_NAME}</string>
+ <key>CFBundleName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+</dict>
+</plist>
diff --git a/third_party/libwebrtc/build/config/ios/rules.gni b/third_party/libwebrtc/build/config/ios/rules.gni
new file mode 100644
index 0000000000..04d605dd97
--- /dev/null
+++ b/third_party/libwebrtc/build/config/ios/rules.gni
@@ -0,0 +1,2173 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/apple/apple_info_plist.gni")
+import("//build/config/apple/symbols.gni")
+import("//build/config/ios/ios_sdk.gni")
+import("//build/toolchain/goma.gni")
+import("//build/toolchain/toolchain.gni")
+import("//build_overrides/build.gni")
+
+declare_args() {
+ # Set to true if an Xcode project is generated for this build. Set this to
+ # false if you do not plan to run `gn gen --ide=xcode` in this directory.
+ # This will speed up the generation at the cost of generating an invalid
+ # Xcode project if `gn gen --ide=xcode` is used. Defaults to true (favor
+ # correctness over speed).
+ ios_set_attributes_for_xcode_project_generation = true
+}
+
+# Constants corresponding to the bundle type identifiers use application,
+# application extension, XCTest and XCUITest targets respectively.
+_ios_xcode_app_bundle_id = "com.apple.product-type.application"
+_ios_xcode_appex_bundle_id = "com.apple.product-type.app-extension"
+_ios_xcode_xctest_bundle_id = "com.apple.product-type.bundle.unit-test"
+_ios_xcode_xcuitest_bundle_id = "com.apple.product-type.bundle.ui-testing"
+
+# Invokes lipo on multiple arch-specific binaries to create a fat binary.
+#
+# Arguments
+#
+# arch_binary_target
+# name of the target generating the arch-specific binaries, they must
+# be named $target_out_dir/$toolchain_cpu/$arch_binary_output.
+#
+# arch_binary_output
+# (optional, defaults to the name of $arch_binary_target) base name of
+# the arch-specific binary generated by arch_binary_target.
+#
+# output_name
+# (optional, defaults to $target_name) base name of the target output,
+# the full path will be $target_out_dir/$output_name.
+#
+# configs
+# (optional) a list of configurations, this is used to check whether
+# the binary should be stripped, when "enable_stripping" is true.
+#
+template("lipo_binary") {
+ assert(defined(invoker.arch_binary_target),
+ "arch_binary_target must be defined for $target_name")
+
+ assert(!is_fat_secondary_toolchain,
+ "lipo_binary can only be used in the primary toolchain of a fat build")
+
+ _target_name = target_name
+ _output_name = target_name
+ if (defined(invoker.output_name)) {
+ _output_name = invoker.output_name
+ }
+
+ _all_target_cpu = [ target_cpu ] + additional_target_cpus
+ _all_toolchains = [ current_toolchain ] + additional_toolchains
+
+ _arch_binary_target = invoker.arch_binary_target
+ _arch_binary_output = get_label_info(_arch_binary_target, "name")
+ if (defined(invoker.arch_binary_output)) {
+ _arch_binary_output = invoker.arch_binary_output
+ }
+
+ action(_target_name) {
+ forward_variables_from(invoker,
+ "*",
+ [
+ "arch_binary_output",
+ "arch_binary_target",
+ "configs",
+ "output_name",
+ ])
+
+ script = "//build/toolchain/apple/linker_driver.py"
+
+ # http://crbug.com/762840. Fix for bots running out of memory.
+ pool = "//build/toolchain:link_pool($default_toolchain)"
+
+ outputs = [ "$target_out_dir/$_output_name" ]
+
+ deps = []
+ _index = 0
+ inputs = []
+ foreach(_cpu, _all_target_cpu) {
+ _toolchain = _all_toolchains[_index]
+ _index = _index + 1
+
+ inputs +=
+ [ get_label_info("$_arch_binary_target($_toolchain)",
+ "target_out_dir") + "/$_cpu/$_arch_binary_output" ]
+
+ deps += [ "$_arch_binary_target($_toolchain)" ]
+ }
+
+ args = [
+ "xcrun",
+ "lipo",
+ "-create",
+ "-output",
+ rebase_path("$target_out_dir/$_output_name", root_build_dir),
+ ] + rebase_path(inputs, root_build_dir)
+
+ if (enable_dsyms) {
+ _dsyms_output_dir = "$root_out_dir/$_output_name.dSYM"
+ outputs += [
+ "$_dsyms_output_dir/",
+ "$_dsyms_output_dir/Contents/Info.plist",
+ "$_dsyms_output_dir/Contents/Resources/DWARF/$_output_name",
+ ]
+ args += [ "-Wcrl,dsym," + rebase_path("$root_out_dir/.", root_build_dir) ]
+ if (!use_xcode_clang) {
+ args += [ "-Wcrl,dsymutilpath," +
+ rebase_path("//tools/clang/dsymutil/bin/dsymutil",
+ root_build_dir) ]
+ }
+ }
+
+ if (enable_stripping) {
+ args += [ "-Wcrl,strip,-x,-S" ]
+ if (save_unstripped_output) {
+ outputs += [ "$root_out_dir/$_output_name.unstripped" ]
+ args += [ "-Wcrl,unstripped," +
+ rebase_path("$root_out_dir/.", root_build_dir) ]
+ }
+ }
+ }
+}
+
+# Wrapper around create_bundle taking care of code signature settings.
+#
+# Arguments
+#
+# product_type
+# string, product type for the generated Xcode project.
+#
+# bundle_gen_dir
+# (optional) directory where the bundle is generated; must be below
+# root_out_dir and defaults to root_out_dir if omitted.
+#
+# bundle_deps
+# (optional) list of additional dependencies.
+#
+# bundle_deps_filter
+# (optional) list of dependencies to filter (for more information
+# see "gn help bundle_deps_filter").
+#
+# bundle_extension
+# string, extension of the bundle, used to generate bundle name.
+#
+# bundle_binary_target
+# (optional) string, label of the target generating the bundle main
+# binary. This target and bundle_binary_path are mutually exclusive.
+#
+# bundle_binary_output
+# (optional) string, base name of the binary generated by the
+# bundle_binary_target target, defaults to the target name.
+#
+# bundle_binary_path
+# (optional) string, path to the bundle main binary. This target and
+# bundle_binary_target are mutually exclusive.
+#
+# output_name:
+# (optional) string, name of the generated application, if omitted,
+# defaults to the target_name.
+#
+# extra_system_frameworks
+# (optional) list of system framework to copy to the bundle.
+#
+# enable_code_signing
+# (optional) boolean, control whether code signing is enabled or not,
+# default to ios_enable_code_signing if not defined.
+#
+# entitlements_path:
+# (optional) path to the template to use to generate the application
+# entitlements by performing variable substitutions, defaults to
+# //build/config/ios/entitlements.plist.
+#
+# entitlements_target:
+# (optional) label of the target generating the application
+# entitlements (must generate a single file as output); cannot be
+# defined if entitlements_path is set.
+#
+# has_public_headers:
+# (optional) boolean, defaults to false; only meaningful if the bundle
+# is a framework bundle; if true, then the frameworks includes public
+# headers
+#
+# disable_entitlements
+# (optional, defaults to false) boolean, control whether entitlements willi
+# be embedded in the application during signature. If false and no
+# entitlements are provided, default empty entitlements will be used.
+#
+# disable_embedded_mobileprovision
+# (optional, default to false) boolean, control whether mobile provisions
+# will be embedded in the bundle. If true, the existing
+# embedded.mobileprovision will be deleted.
+#
+# xcode_extra_attributes
+# (optional) scope, extra attributes for Xcode projects.
+#
+# xcode_test_application_name:
+# (optional) string, name of the test application for Xcode unit or ui
+# test target.
+#
+# xcode_product_bundle_id:
+# (optional) string, the bundle ID that will be added in the XCode
+# attributes to enable some features when debugging (e.g. MetricKit).
+#
+# primary_info_plist:
+# (optional) path to Info.plist to merge with the $partial_info_plist
+# generated by the compilation of the asset catalog.
+#
+# partial_info_plist:
+# (optional) path to the partial Info.plist generated by the asset
+# catalog compiler; if defined $primary_info_plist must also be defined.
+#
+template("create_signed_bundle") {
+ assert(defined(invoker.product_type),
+ "product_type must be defined for $target_name")
+ assert(defined(invoker.bundle_extension),
+ "bundle_extension must be defined for $target_name")
+ assert(defined(invoker.bundle_binary_target) !=
+ defined(invoker.bundle_binary_path),
+ "Only one of bundle_binary_target or bundle_binary_path may be " +
+ "specified for $target_name")
+ assert(!defined(invoker.partial_info_plist) ||
+ defined(invoker.primary_info_plist),
+ "primary_info_plist must be defined when partial_info_plist is " +
+ "defined for $target_name")
+
+ if (defined(invoker.xcode_test_application_name)) {
+ assert(
+ invoker.product_type == _ios_xcode_xctest_bundle_id ||
+ invoker.product_type == _ios_xcode_xcuitest_bundle_id,
+ "xcode_test_application_name can be only defined for Xcode unit or ui test target.")
+ }
+
+ _target_name = target_name
+ _output_name = target_name
+ if (defined(invoker.output_name)) {
+ _output_name = invoker.output_name
+ }
+
+ if (defined(invoker.bundle_binary_path)) {
+ _bundle_binary_path = invoker.bundle_binary_path
+ } else {
+ _bundle_binary_target = invoker.bundle_binary_target
+ _bundle_binary_output = get_label_info(_bundle_binary_target, "name")
+ if (defined(invoker.bundle_binary_output)) {
+ _bundle_binary_output = invoker.bundle_binary_output
+ }
+ _bundle_binary_path =
+ get_label_info(_bundle_binary_target, "target_out_dir") +
+ "/$_bundle_binary_output"
+ }
+
+ _bundle_gen_dir = root_out_dir
+ if (defined(invoker.bundle_gen_dir)) {
+ _bundle_gen_dir = invoker.bundle_gen_dir
+ }
+
+ _bundle_extension = invoker.bundle_extension
+
+ _enable_embedded_mobileprovision = true
+ if (defined(invoker.disable_embedded_mobileprovision)) {
+ _enable_embedded_mobileprovision = !invoker.disable_embedded_mobileprovision
+ }
+
+ if (target_environment == "catalyst") {
+ _enable_embedded_mobileprovision = false
+ }
+
+ _enable_entitlements = true
+ if (defined(invoker.disable_entitlements)) {
+ _enable_entitlements = !invoker.disable_entitlements
+ }
+
+ if (_enable_entitlements) {
+ if (!defined(invoker.entitlements_target)) {
+ _entitlements_path = "//build/config/ios/entitlements.plist"
+ if (defined(invoker.entitlements_path)) {
+ _entitlements_path = invoker.entitlements_path
+ }
+ } else {
+ assert(!defined(invoker.entitlements_path),
+ "Cannot define both entitlements_path and entitlements_target " +
+ "for $target_name")
+
+ _entitlements_target_outputs =
+ get_target_outputs(invoker.entitlements_target)
+ _entitlements_path = _entitlements_target_outputs[0]
+ }
+ }
+
+ _enable_code_signing = ios_enable_code_signing
+ if (defined(invoker.enable_code_signing)) {
+ _enable_code_signing = invoker.enable_code_signing
+ }
+
+ if (!ios_set_attributes_for_xcode_project_generation) {
+ not_needed(invoker,
+ [
+ "xcode_product_bundle_id",
+ "xcode_extra_attributes",
+ ])
+ }
+
+ create_bundle(_target_name) {
+ forward_variables_from(invoker,
+ [
+ "bundle_deps_filter",
+ "data_deps",
+ "deps",
+ "partial_info_plist",
+ "product_type",
+ "public_configs",
+ "public_deps",
+ "testonly",
+ "visibility",
+ "xcode_test_application_name",
+ ])
+
+ bundle_root_dir = "$_bundle_gen_dir/$_output_name$_bundle_extension"
+ if (target_environment == "simulator" || target_environment == "device") {
+ bundle_contents_dir = bundle_root_dir
+ bundle_resources_dir = bundle_contents_dir
+ bundle_executable_dir = bundle_contents_dir
+ } else if (target_environment == "catalyst") {
+ if (_bundle_extension != ".framework") {
+ bundle_contents_dir = "$bundle_root_dir/Contents"
+ bundle_resources_dir = "$bundle_contents_dir/Resources"
+ bundle_executable_dir = "$bundle_contents_dir/MacOS"
+ } else {
+ bundle_contents_dir = "$bundle_root_dir/Versions/A"
+ bundle_resources_dir = "$bundle_contents_dir/Resources"
+ bundle_executable_dir = bundle_contents_dir
+ }
+ }
+
+ if (!defined(public_deps)) {
+ public_deps = []
+ }
+
+ if (ios_set_attributes_for_xcode_project_generation) {
+ _xcode_product_bundle_id = ""
+ if (defined(invoker.xcode_product_bundle_id)) {
+ _xcode_product_bundle_id = invoker.xcode_product_bundle_id
+ }
+
+ if (_xcode_product_bundle_id != "") {
+ _ios_provisioning_profile_info =
+ exec_script("//build/config/ios/codesign.py",
+ [
+ "find-provisioning-profile",
+ "-b=" + _xcode_product_bundle_id,
+ ],
+ "json")
+ }
+
+ xcode_extra_attributes = {
+ IPHONEOS_DEPLOYMENT_TARGET = ios_deployment_target
+ if (_xcode_product_bundle_id != "") {
+ CODE_SIGN_IDENTITY = "iPhone Developer"
+ DEVELOPMENT_TEAM = _ios_provisioning_profile_info.team_identifier
+ PRODUCT_BUNDLE_IDENTIFIER = _xcode_product_bundle_id
+ PROVISIONING_PROFILE_SPECIFIER = _ios_provisioning_profile_info.name
+ }
+
+ # If invoker has defined extra attributes, they override the defaults.
+ if (defined(invoker.xcode_extra_attributes)) {
+ forward_variables_from(invoker.xcode_extra_attributes, "*")
+ }
+ }
+ }
+
+ if (defined(invoker.bundle_binary_target)) {
+ public_deps += [ invoker.bundle_binary_target ]
+ }
+
+ if (defined(invoker.bundle_deps)) {
+ if (!defined(deps)) {
+ deps = []
+ }
+ deps += invoker.bundle_deps
+ }
+ if (!defined(deps)) {
+ deps = []
+ }
+
+ code_signing_script = "//build/config/ios/codesign.py"
+ code_signing_sources = [ _bundle_binary_path ]
+ if (_enable_entitlements) {
+ if (defined(invoker.entitlements_target)) {
+ deps += [ invoker.entitlements_target ]
+ }
+ code_signing_sources += [ _entitlements_path ]
+ }
+ code_signing_outputs = [ "$bundle_executable_dir/$_output_name" ]
+ if (_enable_code_signing) {
+ code_signing_outputs +=
+ [ "$bundle_contents_dir/_CodeSignature/CodeResources" ]
+ }
+ if (ios_code_signing_identity != "" && target_environment == "device" &&
+ _enable_embedded_mobileprovision) {
+ code_signing_outputs +=
+ [ "$bundle_contents_dir/embedded.mobileprovision" ]
+ }
+ if (_bundle_extension == ".framework") {
+ if (target_environment == "catalyst") {
+ code_signing_outputs += [
+ "$bundle_root_dir/Versions/Current",
+ "$bundle_root_dir/$_output_name",
+ ]
+
+ if (defined(invoker.has_public_headers) && invoker.has_public_headers) {
+ code_signing_outputs += [
+ "$bundle_root_dir/Headers",
+ "$bundle_root_dir/Modules",
+ ]
+ }
+ } else {
+ not_needed(invoker, [ "has_public_headers" ])
+ }
+ }
+
+ if (defined(invoker.extra_system_frameworks)) {
+ foreach(_framework, invoker.extra_system_frameworks) {
+ code_signing_outputs += [ "$bundle_contents_dir/Frameworks/" +
+ get_path_info(_framework, "file") ]
+ }
+ }
+
+ code_signing_args = [
+ "code-sign-bundle",
+ "-t=" + ios_sdk_name,
+ "-i=" + ios_code_signing_identity,
+ "-b=" + rebase_path(_bundle_binary_path, root_build_dir),
+ ]
+ if (_enable_entitlements) {
+ code_signing_args +=
+ [ "-e=" + rebase_path(_entitlements_path, root_build_dir) ]
+ }
+ if (!_enable_embedded_mobileprovision) {
+ code_signing_args += [ "--disable-embedded-mobileprovision" ]
+ }
+ code_signing_args += [ rebase_path(bundle_root_dir, root_build_dir) ]
+ if (!_enable_code_signing) {
+ code_signing_args += [ "--disable-code-signature" ]
+ }
+ if (defined(invoker.extra_system_frameworks)) {
+ # All framework in extra_system_frameworks are expected to be system
+ # framework and the path to be already system absolute so do not use
+ # rebase_path here unless using Goma RBE and system Xcode (as in that
+ # case the system framework are found via a symlink in root_build_dir).
+ foreach(_framework, invoker.extra_system_frameworks) {
+ if (use_system_xcode && use_goma) {
+ _framework_path = rebase_path(_framework, root_build_dir)
+ } else {
+ _framework_path = _framework
+ }
+ code_signing_args += [ "-F=$_framework_path" ]
+ }
+ }
+ if (defined(invoker.partial_info_plist)) {
+ _partial_info_plists = [
+ invoker.primary_info_plist,
+ invoker.partial_info_plist,
+ ]
+
+ _plist_compiler_path = "//build/apple/plist_util.py"
+
+ code_signing_sources += _partial_info_plists
+ code_signing_sources += [ _plist_compiler_path ]
+ if (target_environment != "catalyst" ||
+ _bundle_extension != ".framework") {
+ code_signing_outputs += [ "$bundle_contents_dir/Info.plist" ]
+ } else {
+ code_signing_outputs += [ "$bundle_resources_dir/Info.plist" ]
+ }
+
+ code_signing_args +=
+ [ "-P=" + rebase_path(_plist_compiler_path, root_build_dir) ]
+ foreach(_partial_info_plist, _partial_info_plists) {
+ code_signing_args +=
+ [ "-p=" + rebase_path(_partial_info_plist, root_build_dir) ]
+ }
+ }
+ }
+}
+
+# Generates Info.plist files for Mac apps and frameworks.
+#
+# Arguments
+#
+# info_plist:
+# (optional) string, path to the Info.plist file that will be used for
+# the bundle.
+#
+# info_plist_target:
+# (optional) string, if the info_plist is generated from an action,
+# rather than a regular source file, specify the target name in lieu
+# of info_plist. The two arguments are mutually exclusive.
+#
+# executable_name:
+# string, name of the generated target used for the product
+# and executable name as specified in the output Info.plist.
+#
+# extra_substitutions:
+# (optional) string array, 'key=value' pairs for extra fields which are
+# specified in a source Info.plist template.
+template("ios_info_plist") {
+ assert(defined(invoker.info_plist) != defined(invoker.info_plist_target),
+ "Only one of info_plist or info_plist_target may be specified in " +
+ target_name)
+
+ if (defined(invoker.info_plist)) {
+ _info_plist = invoker.info_plist
+ } else {
+ _info_plist_target_output = get_target_outputs(invoker.info_plist_target)
+ _info_plist = _info_plist_target_output[0]
+ }
+
+ apple_info_plist(target_name) {
+ format = "binary1"
+ extra_substitutions = []
+ if (defined(invoker.extra_substitutions)) {
+ extra_substitutions = invoker.extra_substitutions
+ }
+ extra_substitutions += [
+ "IOS_BUNDLE_ID_PREFIX=$ios_app_bundle_id_prefix",
+ "IOS_PLATFORM_BUILD=$ios_platform_build",
+ "IOS_PLATFORM_NAME=$ios_sdk_name",
+ "IOS_PLATFORM_VERSION=$ios_sdk_version",
+ "IOS_SDK_BUILD=$ios_sdk_build",
+ "IOS_SDK_NAME=$ios_sdk_name$ios_sdk_version",
+ "IOS_SUPPORTED_PLATFORM=$ios_sdk_platform",
+ "BUILD_MACHINE_OS_BUILD=$machine_os_build",
+ "IOS_DEPLOYMENT_TARGET=$ios_deployment_target",
+ "XCODE_BUILD=$xcode_build",
+ "XCODE_VERSION=$xcode_version",
+ ]
+ plist_templates = [
+ "//build/config/ios/BuildInfo.plist",
+ _info_plist,
+ ]
+ if (defined(invoker.info_plist_target)) {
+ deps = [ invoker.info_plist_target ]
+ }
+ forward_variables_from(invoker,
+ [
+ "executable_name",
+ "output_name",
+ "visibility",
+ "testonly",
+ ])
+ }
+}
+
+# Template to build an application bundle for iOS.
+#
+# This should be used instead of "executable" built-in target type on iOS.
+# As the template forward the generation of the application executable to
+# an "executable" target, all arguments supported by "executable" targets
+# are also supported by this template.
+#
+# Arguments
+#
+# output_name:
+# (optional) string, name of the generated application, if omitted,
+# defaults to the target_name.
+#
+# extra_substitutions:
+# (optional) list of string in "key=value" format, each value will
+# be used as an additional variable substitution rule when generating
+# the application Info.plist
+#
+# info_plist:
+# (optional) string, path to the Info.plist file that will be used for
+# the bundle.
+#
+# info_plist_target:
+# (optional) string, if the info_plist is generated from an action,
+# rather than a regular source file, specify the target name in lieu
+# of info_plist. The two arguments are mutually exclusive.
+#
+# entitlements_path:
+# (optional) path to the template to use to generate the application
+# entitlements by performing variable substitutions, defaults to
+# //build/config/ios/entitlements.plist.
+#
+# entitlements_target:
+# (optional) label of the target generating the application
+# entitlements (must generate a single file as output); cannot be
+# defined if entitlements_path is set.
+#
+# product_type
+# (optional) string, product type for the generated Xcode project,
+# default to "com.apple.product-type.application". Should only be
+# overriden when building application extension.
+#
+# enable_code_signing
+# (optional) boolean, control whether code signing is enabled or not,
+# default to ios_enable_code_signing if not defined.
+#
+# variants
+# (optional) list of scopes, each scope needs to define the attributes
+# "name" and "bundle_deps"; if defined and non-empty, then one bundle
+# named $target_out_dir/$variant/$output_name will be created for each
+# variant with the same binary but the correct bundle_deps, the bundle
+# at $target_out_dir/$output_name will be a copy of the first variant.
+#
+# xcode_product_bundle_id:
+# (optional) string, the bundle ID that will be added in the XCode
+# attributes to enable some features when debugging (e.g. MetricKit).
+# defaults to "$ios_app_bundle_id_prefix.$output_name".
+#
+# For more information, see "gn help executable".
+template("ios_app_bundle") {
+ _output_name = target_name
+ _target_name = target_name
+ if (defined(invoker.output_name)) {
+ _output_name = invoker.output_name
+ }
+
+ _primary_toolchain = current_toolchain
+ if (is_fat_secondary_toolchain) {
+ _primary_toolchain = primary_fat_toolchain_name
+ }
+
+ assert(
+ !defined(invoker.bundle_extension),
+ "bundle_extension must not be set for ios_app_bundle template for $target_name")
+
+ _xcode_product_bundle_id = "$ios_app_bundle_id_prefix.$_output_name"
+ if (defined(invoker.xcode_product_bundle_id)) {
+ _xcode_product_bundle_id = invoker.xcode_product_bundle_id
+ _xcode_product_bundle_id =
+ "$ios_app_bundle_id_prefix.$_xcode_product_bundle_id"
+ } else if (defined(invoker.bundle_id)) {
+ _xcode_product_bundle_id = invoker.bundle_id
+ }
+
+ # Bundle ID should respect rfc1034 and replace _ with -.
+ _xcode_product_bundle_id =
+ string_replace("$_xcode_product_bundle_id", "_", "-")
+
+ _arch_executable_source = _target_name + "_arch_executable_sources"
+ _arch_executable_target = _target_name + "_arch_executable"
+ _lipo_executable_target = _target_name + "_executable"
+
+ if (defined(invoker.variants) && invoker.variants != []) {
+ _variants = []
+
+ foreach(_variant, invoker.variants) {
+ assert(defined(_variant.name) && _variant.name != "",
+ "name must be defined for all $target_name variants")
+
+ assert(defined(_variant.bundle_deps),
+ "bundle_deps must be defined for all $target_name variants")
+
+ _variants += [
+ {
+ name = _variant.name
+ bundle_deps = _variant.bundle_deps
+ target_name = "${_target_name}_variants_${_variant.name}"
+ bundle_gen_dir = "$root_out_dir/variants/${_variant.name}"
+ },
+ ]
+ }
+ } else {
+ # If no variants are passed to the template, use a fake variant with
+ # no name to avoid duplicating code. As no variant can have an empty
+ # name except this fake variant, it is possible to know if a variant
+ # is fake or not.
+ _variants = [
+ {
+ name = ""
+ bundle_deps = []
+ target_name = _target_name
+ bundle_gen_dir = root_out_dir
+ },
+ ]
+ }
+
+ _default_variant = _variants[0]
+
+ source_set(_arch_executable_source) {
+ forward_variables_from(invoker,
+ "*",
+ [
+ "bundle_deps",
+ "bundle_deps_filter",
+ "bundle_extension",
+ "enable_code_signing",
+ "entitlements_path",
+ "entitlements_target",
+ "extra_substitutions",
+ "extra_system_frameworks",
+ "info_plist",
+ "info_plist_target",
+ "output_name",
+ "product_type",
+ "visibility",
+ "xcode_extra_attributes",
+ ])
+
+ visibility = [ ":$_arch_executable_target" ]
+ }
+
+ if (!is_fat_secondary_toolchain || target_environment == "simulator") {
+ _generate_entitlements_target = _target_name + "_gen_entitlements"
+ _generate_entitlements_output =
+ get_label_info(":$_generate_entitlements_target($_primary_toolchain)",
+ "target_out_dir") + "/$_output_name.xcent"
+ }
+
+ _product_type = _ios_xcode_app_bundle_id
+ if (defined(invoker.product_type)) {
+ _product_type = invoker.product_type
+ }
+
+ if (_product_type == _ios_xcode_app_bundle_id) {
+ _bundle_extension = ".app"
+ } else if (_product_type == _ios_xcode_appex_bundle_id) {
+ _bundle_extension = ".appex"
+ } else {
+ assert(false, "unknown product_type \"$product_type\" for $_target_name")
+ }
+
+ _is_app_bundle = _product_type == _ios_xcode_app_bundle_id
+
+ executable(_arch_executable_target) {
+ forward_variables_from(invoker,
+ "*",
+ [
+ "bundle_deps",
+ "bundle_deps_filter",
+ "bundle_extension",
+ "enable_code_signing",
+ "entitlements_path",
+ "entitlements_target",
+ "extra_substitutions",
+ "extra_system_frameworks",
+ "info_plist",
+ "info_plist_target",
+ "output_name",
+ "product_type",
+ "sources",
+ "visibility",
+ "xcode_extra_attributes",
+ ])
+
+ visibility = [ ":$_lipo_executable_target($_primary_toolchain)" ]
+ if (is_fat_secondary_toolchain) {
+ visibility += [ ":$_target_name" ]
+ }
+
+ if (!defined(deps)) {
+ deps = []
+ }
+ deps += [ ":$_arch_executable_source" ]
+
+ if (!defined(frameworks)) {
+ frameworks = []
+ }
+ frameworks += [ "UIKit.framework" ]
+
+ if (target_environment == "simulator") {
+ deps += [ ":$_generate_entitlements_target($_primary_toolchain)" ]
+
+ if (!defined(inputs)) {
+ inputs = []
+ }
+ inputs += [ _generate_entitlements_output ]
+
+ if (!defined(ldflags)) {
+ ldflags = []
+ }
+ ldflags += [ "-Wl,-sectcreate,__TEXT,__entitlements," +
+ rebase_path(_generate_entitlements_output, root_build_dir) ]
+ }
+
+ output_name = _output_name
+ output_prefix_override = true
+ output_dir = "$target_out_dir/$target_cpu"
+ }
+
+ if (is_fat_secondary_toolchain) {
+ # For fat builds, only the default toolchain will generate an application
+ # bundle. For the other toolchains, the template is only used for building
+ # the arch-specific binary, thus the default target is just a group().
+
+ group(_target_name) {
+ forward_variables_from(invoker,
+ [
+ "visibility",
+ "testonly",
+ ])
+ public_deps = [ ":$_arch_executable_target" ]
+ }
+ } else {
+ lipo_binary(_lipo_executable_target) {
+ forward_variables_from(invoker,
+ [
+ "configs",
+ "testonly",
+ ])
+
+ visibility = []
+ foreach(_variant, _variants) {
+ visibility += [ ":${_variant.target_name}" ]
+ }
+
+ output_name = _output_name
+ arch_binary_target = ":$_arch_executable_target"
+ arch_binary_output = _output_name
+ }
+
+ _generate_info_plist = target_name + "_generate_info_plist"
+ ios_info_plist(_generate_info_plist) {
+ forward_variables_from(invoker,
+ [
+ "extra_substitutions",
+ "info_plist",
+ "info_plist_target",
+ ])
+
+ executable_name = _output_name
+ }
+
+ if (!is_fat_secondary_toolchain) {
+ if (!defined(invoker.entitlements_target)) {
+ _entitlements_path = "//build/config/ios/entitlements.plist"
+ if (defined(invoker.entitlements_path)) {
+ _entitlements_path = invoker.entitlements_path
+ }
+ } else {
+ assert(!defined(invoker.entitlements_path),
+ "Cannot define both entitlements_path and entitlements_target" +
+ "for $_target_name")
+
+ _entitlements_target_outputs =
+ get_target_outputs(invoker.entitlements_target)
+ _entitlements_path = _entitlements_target_outputs[0]
+ }
+
+ action(_generate_entitlements_target) {
+ _gen_info_plist_outputs = get_target_outputs(":$_generate_info_plist")
+ _info_plist_path = _gen_info_plist_outputs[0]
+
+ script = "//build/config/ios/codesign.py"
+ deps = [ ":$_generate_info_plist" ]
+ if (defined(invoker.entitlements_target)) {
+ deps += [ invoker.entitlements_target ]
+ }
+ sources = [
+ _entitlements_path,
+ _info_plist_path,
+ ]
+ outputs = [ _generate_entitlements_output ]
+
+ args = [
+ "generate-entitlements",
+ "-e=" + rebase_path(_entitlements_path, root_build_dir),
+ "-p=" + rebase_path(_info_plist_path, root_build_dir),
+ ] + rebase_path(outputs, root_build_dir)
+ }
+ }
+
+ # Only write PkgInfo for real application, not application extension.
+ if (_is_app_bundle) {
+ _create_pkg_info = target_name + "_pkg_info"
+ action(_create_pkg_info) {
+ forward_variables_from(invoker, [ "testonly" ])
+ script = "//build/apple/write_pkg_info.py"
+ inputs = [ "//build/apple/plist_util.py" ]
+ sources = get_target_outputs(":$_generate_info_plist")
+ outputs = [
+ # Cannot name the output PkgInfo as the name will not be unique if
+ # multiple ios_app_bundle are defined in the same BUILD.gn file. The
+ # file is renamed in the bundle_data outputs to the correct name.
+ "$target_gen_dir/$target_name",
+ ]
+ args = [ "--plist" ] + rebase_path(sources, root_build_dir) +
+ [ "--output" ] + rebase_path(outputs, root_build_dir)
+ deps = [ ":$_generate_info_plist" ]
+ }
+
+ _bundle_data_pkg_info = target_name + "_bundle_data_pkg_info"
+ bundle_data(_bundle_data_pkg_info) {
+ forward_variables_from(invoker, [ "testonly" ])
+ sources = get_target_outputs(":$_create_pkg_info")
+ outputs = [ "{{bundle_resources_dir}}/PkgInfo" ]
+ public_deps = [ ":$_create_pkg_info" ]
+ }
+ }
+
+ foreach(_variant, _variants) {
+ create_signed_bundle(_variant.target_name) {
+ forward_variables_from(invoker,
+ [
+ "bundle_deps",
+ "bundle_deps_filter",
+ "data_deps",
+ "deps",
+ "enable_code_signing",
+ "entitlements_path",
+ "entitlements_target",
+ "extra_system_frameworks",
+ "public_configs",
+ "public_deps",
+ "testonly",
+ "visibility",
+ "xcode_extra_attributes",
+ ])
+
+ output_name = _output_name
+ bundle_gen_dir = _variant.bundle_gen_dir
+ bundle_binary_target = ":$_lipo_executable_target"
+ bundle_binary_output = _output_name
+ bundle_extension = _bundle_extension
+ product_type = _product_type
+ xcode_product_bundle_id = _xcode_product_bundle_id
+
+ _generate_info_plist_outputs =
+ get_target_outputs(":$_generate_info_plist")
+ primary_info_plist = _generate_info_plist_outputs[0]
+ partial_info_plist =
+ "$target_gen_dir/${_variant.target_name}_partial_info.plist"
+
+ if (!defined(deps)) {
+ deps = []
+ }
+ deps += [ ":$_generate_info_plist" ]
+
+ if (!defined(bundle_deps)) {
+ bundle_deps = []
+ }
+ if (_is_app_bundle) {
+ bundle_deps += [ ":$_bundle_data_pkg_info" ]
+ }
+ bundle_deps += _variant.bundle_deps
+
+ if (target_environment == "simulator") {
+ if (!defined(data_deps)) {
+ data_deps = []
+ }
+ data_deps += [ "//testing/iossim" ]
+ }
+ }
+ }
+
+ if (_default_variant.name != "") {
+ _bundle_short_name = "$_output_name$_bundle_extension"
+ action(_target_name) {
+ forward_variables_from(invoker, [ "testonly" ])
+
+ script = "//build/config/ios/hardlink.py"
+ public_deps = []
+ foreach(_variant, _variants) {
+ public_deps += [ ":${_variant.target_name}" ]
+ }
+
+ sources = [ "${_default_variant.bundle_gen_dir}/$_bundle_short_name" ]
+ outputs = [ "$root_out_dir/$_bundle_short_name" ]
+
+ args = rebase_path(sources, root_build_dir) +
+ rebase_path(outputs, root_build_dir)
+ }
+ }
+ }
+
+ if (is_fat_secondary_toolchain) {
+ not_needed("*")
+ }
+}
+
+set_defaults("ios_app_bundle") {
+ configs = default_executable_configs
+}
+
+# Template to build an application extension bundle for iOS.
+#
+# This should be used instead of "executable" built-in target type on iOS.
+# As the template forward the generation of the application executable to
+# an "executable" target, all arguments supported by "executable" targets
+# are also supported by this template.
+#
+# Arguments
+#
+# output_name:
+# (optional) string, name of the generated application, if omitted,
+# defaults to the target_name.
+#
+# extra_substitutions:
+# (optional) list of string in "key=value" format, each value will
+# be used as an additional variable substitution rule when generating
+# the application Info.plist
+#
+# info_plist:
+# (optional) string, path to the Info.plist file that will be used for
+# the bundle.
+#
+# info_plist_target:
+# (optional) string, if the info_plist is generated from an action,
+# rather than a regular source file, specify the target name in lieu
+# of info_plist. The two arguments are mutually exclusive.
+#
+# For more information, see "gn help executable".
+template("ios_appex_bundle") {
+ ios_app_bundle(target_name) {
+ forward_variables_from(invoker,
+ "*",
+ [
+ "bundle_extension",
+ "product_type",
+ ])
+ product_type = _ios_xcode_appex_bundle_id
+ }
+}
+
+set_defaults("ios_appex_bundle") {
+ configs = [ "//build/config/ios:ios_extension_executable_flags" ]
+}
+
+# Template to compile .xib and .storyboard files.
+#
+# Arguments
+#
+# sources:
+# list of string, sources to compile
+#
+# ibtool_flags:
+# (optional) list of string, additional flags to pass to the ibtool
+template("compile_ib_files") {
+ action_foreach(target_name) {
+ forward_variables_from(invoker,
+ [
+ "testonly",
+ "visibility",
+ ])
+ assert(defined(invoker.sources),
+ "sources must be specified for $target_name")
+ assert(defined(invoker.output_extension),
+ "output_extension must be specified for $target_name")
+
+ ibtool_flags = []
+ if (defined(invoker.ibtool_flags)) {
+ ibtool_flags = invoker.ibtool_flags
+ }
+
+ _output_extension = invoker.output_extension
+
+ script = "//build/config/ios/compile_ib_files.py"
+ sources = invoker.sources
+ outputs = [
+ "$target_gen_dir/$target_name/{{source_name_part}}.$_output_extension",
+ ]
+ args = [
+ "--input",
+ "{{source}}",
+ "--output",
+ rebase_path(
+ "$target_gen_dir/$target_name/{{source_name_part}}.$_output_extension",
+ root_build_dir),
+ ]
+ args += ibtool_flags
+ }
+}
+
+# Compile a xib or storyboard file and add it to a bundle_data so that it is
+# available at runtime in the bundle.
+#
+# Arguments
+#
+# source:
+# string, path of the xib or storyboard to compile.
+#
+# Forwards all variables to the bundle_data target.
+template("bundle_data_ib_file") {
+ assert(defined(invoker.source), "source needs to be defined for $target_name")
+
+ _source_extension = get_path_info(invoker.source, "extension")
+ assert(_source_extension == "xib" || _source_extension == "storyboard",
+ "source must be a .xib or .storyboard for $target_name")
+
+ _target_name = target_name
+ if (_source_extension == "xib") {
+ _compile_ib_file = target_name + "_compile_xib"
+ _output_extension = "nib"
+ } else {
+ _compile_ib_file = target_name + "_compile_storyboard"
+ _output_extension = "storyboardc"
+ }
+
+ compile_ib_files(_compile_ib_file) {
+ sources = [ invoker.source ]
+ output_extension = _output_extension
+ visibility = [ ":$_target_name" ]
+ ibtool_flags = [
+ "--minimum-deployment-target",
+ ios_deployment_target,
+ "--auto-activate-custom-fonts",
+ "--target-device",
+ "iphone",
+ "--target-device",
+ "ipad",
+ ]
+ }
+
+ bundle_data(_target_name) {
+ forward_variables_from(invoker, "*", [ "source" ])
+
+ if (!defined(public_deps)) {
+ public_deps = []
+ }
+ public_deps += [ ":$_compile_ib_file" ]
+
+ sources = get_target_outputs(":$_compile_ib_file")
+
+ outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ]
+ }
+}
+
+# Compile a strings file and add it to a bundle_data so that it is available
+# at runtime in the bundle.
+#
+# Arguments
+#
+# source:
+# string, path of the strings file to compile.
+#
+# output:
+# string, path of the compiled file in the final bundle.
+#
+# Forwards all variables to the bundle_data target.
+template("bundle_data_strings") {
+ assert(defined(invoker.source), "source needs to be defined for $target_name")
+ assert(defined(invoker.output), "output needs to be defined for $target_name")
+
+ _source_extension = get_path_info(invoker.source, "extension")
+ assert(_source_extension == "strings",
+ "source must be a .strings for $target_name")
+
+ _target_name = target_name
+ _convert_target = target_name + "_compile_strings"
+
+ convert_plist(_convert_target) {
+ visibility = [ ":$_target_name" ]
+ source = invoker.source
+ output =
+ "$target_gen_dir/$_target_name/" + get_path_info(invoker.source, "file")
+ format = "binary1"
+ }
+
+ bundle_data(_target_name) {
+ forward_variables_from(invoker,
+ "*",
+ [
+ "source",
+ "output",
+ ])
+
+ if (!defined(public_deps)) {
+ public_deps = []
+ }
+ public_deps += [ ":$_convert_target" ]
+
+ sources = get_target_outputs(":$_convert_target")
+
+ outputs = [ invoker.output ]
+ }
+}
+
+# Template to package a shared library into an iOS framework bundle.
+#
+# 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
+#
+# output_name:
+# (optional) string, name of the generated framework without the
+# .framework suffix. If omitted, defaults to target_name.
+#
+# public_headers:
+# (optional) list of paths to header file that needs to be copied
+# into the framework bundle Headers subdirectory. If omitted or
+# empty then the Headers subdirectory is not created.
+#
+# sources
+# (optional) list of files. Needs to be defined and non-empty if
+# public_headers is defined and non-empty.
+#
+# enable_code_signing
+# (optional) boolean, control whether code signing is enabled or not,
+# default to ios_enable_code_signing if not defined.
+#
+# 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_contents_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_contents_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") {
+ _target_name = target_name
+ _output_name = target_name
+ if (defined(invoker.output_name)) {
+ _output_name = invoker.output_name
+ }
+
+ _has_public_headers =
+ defined(invoker.public_headers) && invoker.public_headers != []
+
+ _primary_toolchain = current_toolchain
+ if (is_fat_secondary_toolchain) {
+ _primary_toolchain = primary_fat_toolchain_name
+ }
+
+ # Public configs are not propagated across toolchain (see crbug.com/675224)
+ # so some configs have to be defined for both default_toolchain and all others
+ # toolchains when performing a fat build. Use "get_label_info" to construct
+ # the path since they need to be relative to the default_toolchain.
+
+ _default_toolchain_root_out_dir =
+ get_label_info("$_target_name($_primary_toolchain)", "root_out_dir")
+
+ _arch_shared_library_source = _target_name + "_arch_shared_library_sources"
+ _arch_shared_library_target = _target_name + "_arch_shared_library"
+ _lipo_shared_library_target = _target_name + "_shared_library"
+ _link_target_name = _target_name + "+link"
+
+ if (_has_public_headers) {
+ _default_toolchain_target_gen_dir =
+ get_label_info("$_target_name($_primary_toolchain)", "target_gen_dir")
+
+ _framework_headers_target = _target_name + "_framework_headers"
+
+ _headers_map_config = _target_name + "_headers_map"
+ _header_map_filename =
+ "$_default_toolchain_target_gen_dir/$_output_name.headers.hmap"
+ config(_headers_map_config) {
+ visibility = [
+ ":${_arch_shared_library_source}",
+ ":${_target_name}_signed_bundle",
+ ]
+ include_dirs = [ _header_map_filename ]
+ }
+ }
+
+ _framework_headers_config = _target_name + "_framework_headers_config"
+ config(_framework_headers_config) {
+ framework_dirs = [ _default_toolchain_root_out_dir ]
+ }
+
+ _framework_public_config = _target_name + "_public_config"
+ config(_framework_public_config) {
+ configs = [ ":$_framework_headers_config" ]
+ frameworks = [ "$_output_name.framework" ]
+ }
+
+ source_set(_arch_shared_library_source) {
+ forward_variables_from(invoker,
+ "*",
+ [
+ "bundle_deps",
+ "bundle_deps_filter",
+ "data_deps",
+ "enable_code_signing",
+ "extra_substitutions",
+ "info_plist",
+ "info_plist_target",
+ "output_name",
+ "public_configs",
+ "visibility",
+ ])
+
+ visibility = [ ":$_arch_shared_library_target" ]
+
+ if (_has_public_headers) {
+ configs += [ ":$_headers_map_config" ]
+
+ if (!defined(deps)) {
+ deps = []
+ }
+ deps += [ ":$_framework_headers_target($_primary_toolchain)" ]
+ }
+ }
+
+ shared_library(_arch_shared_library_target) {
+ forward_variables_from(invoker,
+ "*",
+ [
+ "bundle_deps",
+ "bundle_deps_filter",
+ "data_deps",
+ "enable_code_signing",
+ "extra_substitutions",
+ "info_plist",
+ "info_plist_target",
+ "output_name",
+ "sources",
+ "public_configs",
+ "visibility",
+ ])
+
+ visibility = [ ":$_lipo_shared_library_target($_primary_toolchain)" ]
+ if (is_fat_secondary_toolchain) {
+ visibility += [
+ ":${_target_name}",
+ ":${_target_name}_signed_bundle",
+ ]
+ }
+
+ if (!defined(deps)) {
+ deps = []
+ }
+ deps += [ ":$_arch_shared_library_source" ]
+ if (_has_public_headers) {
+ deps += [ ":$_framework_headers_target($_primary_toolchain)" ]
+ }
+ if (!defined(ldflags)) {
+ ldflags = []
+ }
+ ldflags +=
+ [ "-Wl,-install_name,@rpath/$_output_name.framework/$_output_name" ]
+
+ output_extension = ""
+ output_name = _output_name
+ output_prefix_override = true
+ output_dir = "$target_out_dir/$target_cpu"
+ }
+
+ if (is_fat_secondary_toolchain) {
+ # For fat builds, only the default toolchain will generate a framework
+ # bundle. For the other toolchains, the template is only used for building
+ # the arch-specific binary, thus the default target is just a group().
+
+ group(_target_name) {
+ forward_variables_from(invoker,
+ [
+ "visibility",
+ "testonly",
+ ])
+ public_deps = [ ":$_arch_shared_library_target" ]
+ }
+
+ group(_link_target_name) {
+ forward_variables_from(invoker,
+ [
+ "public_configs",
+ "visibility",
+ "testonly",
+ ])
+ public_deps = [ ":$_link_target_name($_primary_toolchain)" ]
+
+ if (_has_public_headers) {
+ if (!defined(public_configs)) {
+ public_configs = []
+ }
+ public_configs += [ ":$_framework_headers_config" ]
+ }
+ if (!defined(all_dependent_configs)) {
+ all_dependent_configs = []
+ }
+ all_dependent_configs += [ ":$_framework_public_config" ]
+ }
+
+ group("$_target_name+bundle") {
+ forward_variables_from(invoker, [ "testonly" ])
+ public_deps = [ ":$_target_name+bundle($_primary_toolchain)" ]
+ }
+
+ not_needed(invoker, "*")
+ } else {
+ if (_has_public_headers) {
+ _public_headers = invoker.public_headers
+
+ _framework_root_dir = "$root_out_dir/$_output_name.framework"
+ if (target_environment == "simulator" || target_environment == "device") {
+ _framework_contents_dir = _framework_root_dir
+ } else if (target_environment == "catalyst") {
+ _framework_contents_dir = "$_framework_root_dir/Versions/A"
+ }
+
+ _compile_headers_map_target = _target_name + "_compile_headers_map"
+ action(_compile_headers_map_target) {
+ visibility = [ ":$_framework_headers_target" ]
+ forward_variables_from(invoker,
+ [
+ "deps",
+ "public_deps",
+ "testonly",
+ ])
+ script = "//build/config/ios/write_framework_hmap.py"
+ outputs = [ _header_map_filename ]
+
+ # The header map generation only wants the list of headers, not all of
+ # sources, so filter any non-header source files from "sources". It is
+ # less error prone that having the developer duplicate the list of all
+ # headers in addition to "sources".
+ sources = []
+ foreach(_source, invoker.sources) {
+ if (get_path_info(_source, "extension") == "h") {
+ sources += [ _source ]
+ }
+ }
+
+ args = [
+ rebase_path(_header_map_filename),
+ rebase_path(_framework_root_dir, root_build_dir),
+ ] + rebase_path(sources, root_build_dir)
+ }
+
+ _create_module_map_target = _target_name + "_module_map"
+ action(_create_module_map_target) {
+ visibility = [ ":$_framework_headers_target" ]
+ script = "//build/config/ios/write_framework_modulemap.py"
+ outputs = [ "$_framework_contents_dir/Modules/module.modulemap" ]
+ args = [
+ _output_name,
+ rebase_path("$_framework_contents_dir/Modules", root_build_dir),
+ ]
+ }
+
+ _copy_public_headers_target = _target_name + "_copy_public_headers"
+ copy(_copy_public_headers_target) {
+ forward_variables_from(invoker,
+ [
+ "testonly",
+ "deps",
+ ])
+ visibility = [ ":$_framework_headers_target" ]
+ sources = _public_headers
+ outputs = [ "$_framework_contents_dir/Headers/{{source_file_part}}" ]
+
+ # Do not use forward_variables_from for "public_deps" as
+ # we do not want to forward those dependencies.
+ if (defined(invoker.public_deps)) {
+ if (!defined(deps)) {
+ deps = []
+ }
+ deps += invoker.public_deps
+ }
+ }
+
+ group(_framework_headers_target) {
+ forward_variables_from(invoker, [ "testonly" ])
+ deps = [
+ ":$_compile_headers_map_target",
+ ":$_create_module_map_target",
+ ]
+ public_deps = [ ":$_copy_public_headers_target" ]
+ }
+ }
+
+ lipo_binary(_lipo_shared_library_target) {
+ forward_variables_from(invoker,
+ [
+ "configs",
+ "testonly",
+ ])
+
+ visibility = [ ":${_target_name}_signed_bundle" ]
+ output_name = _output_name
+ arch_binary_target = ":$_arch_shared_library_target"
+ arch_binary_output = _output_name
+ }
+
+ _info_plist_target = _target_name + "_info_plist"
+ _info_plist_bundle = _target_name + "_info_plist_bundle"
+ ios_info_plist(_info_plist_target) {
+ visibility = [ ":$_info_plist_bundle" ]
+ executable_name = _output_name
+ forward_variables_from(invoker,
+ [
+ "extra_substitutions",
+ "info_plist",
+ "info_plist_target",
+ ])
+ }
+
+ bundle_data(_info_plist_bundle) {
+ visibility = [ ":${_target_name}_signed_bundle" ]
+ forward_variables_from(invoker, [ "testonly" ])
+ sources = get_target_outputs(":$_info_plist_target")
+ public_deps = [ ":$_info_plist_target" ]
+
+ if (target_environment != "catalyst") {
+ outputs = [ "{{bundle_contents_dir}}/Info.plist" ]
+ } else {
+ outputs = [ "{{bundle_resources_dir}}/Info.plist" ]
+ }
+ }
+
+ create_signed_bundle(_target_name + "_signed_bundle") {
+ forward_variables_from(invoker,
+ [
+ "bundle_deps",
+ "bundle_deps_filter",
+ "data_deps",
+ "deps",
+ "enable_code_signing",
+ "public_configs",
+ "public_deps",
+ "testonly",
+ "visibility",
+ ])
+
+ product_type = "com.apple.product-type.framework"
+ bundle_extension = ".framework"
+
+ output_name = _output_name
+ bundle_binary_target = ":$_lipo_shared_library_target"
+ bundle_binary_output = _output_name
+
+ has_public_headers = _has_public_headers
+
+ # Framework do not have entitlements nor mobileprovision because they use
+ # the one from the bundle using them (.app or .appex) as they are just
+ # dynamic library with shared code.
+ disable_entitlements = true
+ disable_embedded_mobileprovision = true
+
+ if (!defined(deps)) {
+ deps = []
+ }
+ deps += [ ":$_info_plist_bundle" ]
+ }
+
+ group(_target_name) {
+ forward_variables_from(invoker,
+ [
+ "public_configs",
+ "public_deps",
+ "testonly",
+ "visibility",
+ ])
+ if (!defined(public_deps)) {
+ public_deps = []
+ }
+ public_deps += [ ":${_target_name}_signed_bundle" ]
+
+ if (_has_public_headers) {
+ if (!defined(public_configs)) {
+ public_configs = []
+ }
+ public_configs += [ ":$_framework_headers_config" ]
+ }
+ }
+
+ group(_link_target_name) {
+ forward_variables_from(invoker,
+ [
+ "public_configs",
+ "public_deps",
+ "testonly",
+ "visibility",
+ ])
+ if (!defined(public_deps)) {
+ public_deps = []
+ }
+ public_deps += [ ":$_target_name" ]
+
+ if (!defined(all_dependent_configs)) {
+ all_dependent_configs = []
+ }
+ all_dependent_configs += [ ":$_framework_public_config" ]
+ }
+
+ bundle_data(_target_name + "+bundle") {
+ forward_variables_from(invoker,
+ [
+ "testonly",
+ "visibility",
+ ])
+ public_deps = [ ":$_target_name" ]
+ sources = [ "$root_out_dir/$_output_name.framework" ]
+ outputs = [ "{{bundle_contents_dir}}/Frameworks/$_output_name.framework" ]
+ }
+ }
+}
+
+set_defaults("ios_framework_bundle") {
+ configs = default_shared_library_configs
+}
+
+# Template to build a xctest bundle that contains a loadable module for iOS.
+#
+# Arguments
+#
+# deps:
+# list of labels to depends on, these values are used to create the
+# loadable module.
+#
+# product_type
+# string, product type for the generated Xcode project, use
+# "com.apple.product-type.bundle.unit-test" for unit test and
+# "com.apple.product-type.bundle.ui-testing" for UI testing.
+#
+# host_target:
+# string, name of the target that depends on the generated bundle, this
+# value is used to restrict visibilities.
+#
+# xcode_test_application_name:
+# string, name of the test application for Xcode unit or ui test target.
+#
+# output_name
+# (optional) string, name of the generated application, if omitted,
+# defaults to the target_name.
+#
+# This template defines two targets, one named "${target_name}" is the xctest
+# bundle, and the other named "${target_name}_bundle" is a bundle_data that
+# wraps the xctest bundle and that only the "${host_target}" can depend on.
+#
+template("ios_xctest_bundle") {
+ assert(defined(invoker.deps), "deps must be defined for $target_name")
+ assert(defined(invoker.product_type),
+ "product_type must be defined for $target_name")
+ assert(invoker.product_type == _ios_xcode_xctest_bundle_id ||
+ invoker.product_type == _ios_xcode_xcuitest_bundle_id,
+ "product_type defined for $target_name is invalid.")
+ assert(defined(invoker.host_target),
+ "host_target must be defined for $target_name")
+ assert(defined(invoker.xcode_test_application_name),
+ "xcode_test_application_name must be defined for $target_name")
+
+ # Silence "assignment had no effect" error for non-default toolchains as
+ # following variables are only used in the expansion of the template for the
+ # default toolchain.
+ if (is_fat_secondary_toolchain) {
+ not_needed(invoker, "*")
+ }
+
+ _target_name = target_name
+ _output_name = target_name
+
+ if (defined(invoker.output_name)) {
+ _output_name = invoker.output_name
+ }
+
+ _arch_loadable_module_source = _target_name + "_arch_loadable_module_source"
+ _arch_loadable_module_target = _target_name + "_arch_loadable_module"
+ _lipo_loadable_module_target = _target_name + "_loadable_module"
+
+ _primary_toolchain = current_toolchain
+ if (is_fat_secondary_toolchain) {
+ _primary_toolchain = primary_fat_toolchain_name
+ }
+
+ source_set(_arch_loadable_module_source) {
+ forward_variables_from(invoker, [ "deps" ])
+
+ testonly = true
+ visibility = [ ":$_arch_loadable_module_target" ]
+ }
+
+ loadable_module(_arch_loadable_module_target) {
+ testonly = true
+ visibility = [ ":$_lipo_loadable_module_target($_primary_toolchain)" ]
+ if (is_fat_secondary_toolchain) {
+ visibility += [ ":$_target_name" ]
+ }
+
+ deps = [ ":$_arch_loadable_module_source" ]
+ configs += [ "//build/config/ios:xctest_config" ]
+
+ output_dir = "$target_out_dir/$target_cpu"
+ output_name = _output_name
+ output_prefix_override = true
+ output_extension = ""
+ }
+
+ if (is_fat_secondary_toolchain) {
+ # For fat builds, only the default toolchain will generate a test bundle.
+ # For the other toolchains, the template is only used for building the
+ # arch-specific binary, thus the default target is just a group().
+ group(_target_name) {
+ forward_variables_from(invoker, [ "visibility" ])
+ testonly = true
+
+ public_deps = [ ":$_arch_loadable_module_target" ]
+ }
+
+ not_needed(invoker, "*")
+ } else {
+ _info_plist_target = _target_name + "_info_plist"
+ _info_plist_bundle = _target_name + "_info_plist_bundle"
+
+ ios_info_plist(_info_plist_target) {
+ testonly = true
+ visibility = [ ":$_info_plist_bundle" ]
+
+ info_plist = "//build/config/ios/Module-Info.plist"
+ executable_name = _output_name
+
+ if (defined(invoker.xctest_bundle_principal_class)) {
+ _principal_class = invoker.xctest_bundle_principal_class
+ } else {
+ # Fall back to a reasonable default value.
+ _principal_class = "NSObject"
+ }
+ extra_substitutions = [
+ "XCTEST_BUNDLE_PRINCIPAL_CLASS=${_principal_class}",
+ "MODULE_BUNDLE_ID=gtest.$_output_name",
+ ]
+ }
+
+ bundle_data(_info_plist_bundle) {
+ testonly = true
+ visibility = [ ":$_target_name" ]
+
+ public_deps = [ ":$_info_plist_target" ]
+
+ sources = get_target_outputs(":$_info_plist_target")
+ outputs = [ "{{bundle_contents_dir}}/Info.plist" ]
+ }
+
+ lipo_binary(_lipo_loadable_module_target) {
+ forward_variables_from(invoker, [ "configs" ])
+
+ testonly = true
+ visibility = [ ":$_target_name" ]
+
+ output_name = _output_name
+ arch_binary_target = ":$_arch_loadable_module_target"
+ arch_binary_output = _output_name
+ }
+
+ _xctest_bundle = _target_name + "_bundle"
+ create_signed_bundle(_target_name) {
+ forward_variables_from(invoker,
+ [
+ "bundle_id",
+ "data_deps",
+ "enable_code_signing",
+ "product_type",
+ "xcode_test_application_name",
+ ])
+
+ testonly = true
+ visibility = [ ":$_xctest_bundle" ]
+
+ bundle_extension = ".xctest"
+
+ output_name = _output_name
+ bundle_binary_target = ":$_lipo_loadable_module_target"
+ bundle_binary_output = _output_name
+
+ if (ios_set_attributes_for_xcode_project_generation) {
+ _xcode_product_bundle_id =
+ "$ios_app_bundle_id_prefix.gtest.$_output_name"
+
+ _ios_provisioning_profile_info =
+ exec_script("//build/config/ios/codesign.py",
+ [
+ "find-provisioning-profile",
+ "-b=" + _xcode_product_bundle_id,
+ ],
+ "json")
+
+ xcode_extra_attributes = {
+ IPHONEOS_DEPLOYMENT_TARGET = ios_deployment_target
+ CODE_SIGN_IDENTITY = "iPhone Developer"
+ DEVELOPMENT_TEAM = _ios_provisioning_profile_info.team_identifier
+ PRODUCT_BUNDLE_IDENTIFIER = _xcode_product_bundle_id
+ PROVISIONING_PROFILE_SPECIFIER = _ios_provisioning_profile_info.name
+
+ # For XCUITest, Xcode requires specifying the host application name
+ # via the TEST_TARGET_NAME attribute.
+ if (invoker.product_type == _ios_xcode_xcuitest_bundle_id) {
+ TEST_TARGET_NAME = invoker.xcode_test_application_name
+ }
+
+ # For XCTest, Xcode requires specifying the host application path via
+ # both BUNDLE_LOADER and TEST_HOST attributes.
+ if (invoker.product_type == _ios_xcode_xctest_bundle_id) {
+ _xcode_app_name = invoker.xcode_test_application_name
+ if (defined(invoker.xcode_test_application_output_name)) {
+ _xcode_app_name = invoker.xcode_test_application_output_name
+ }
+
+ BUNDLE_LOADER = "\$(TEST_HOST)"
+ TEST_HOST = "\$(BUILT_PRODUCTS_DIR)/" +
+ "${_xcode_app_name}.app/${_xcode_app_name}"
+ }
+ }
+ } else {
+ not_needed(invoker,
+ [
+ "xcode_test_application_name",
+ "xcode_test_application_output_name",
+ ])
+ }
+
+ deps = [ ":$_info_plist_bundle" ]
+ }
+
+ bundle_data(_xctest_bundle) {
+ forward_variables_from(invoker, [ "host_target" ])
+
+ testonly = true
+ visibility = [ ":$host_target" ]
+
+ public_deps = [ ":$_target_name" ]
+ sources = [ "$root_out_dir/$_output_name.xctest" ]
+ outputs = [ "{{bundle_contents_dir}}/PlugIns/$_output_name.xctest" ]
+ }
+ }
+}
+
+set_defaults("ios_xctest_bundle") {
+ configs = default_shared_library_configs
+}
+
+# For Chrome on iOS we want to run XCTests for all our build configurations
+# (Debug, Release, ...). In addition, the symbols visibility is configured to
+# private by default. To simplify testing with those constraints, our tests are
+# compiled in the TEST_HOST target instead of the .xctest bundle.
+template("ios_xctest_test") {
+ _target_name = target_name
+ _output_name = target_name
+ if (defined(invoker.output_name)) {
+ _output_name = invoker.output_name
+ }
+
+ _xctest_target = _target_name + "_module"
+ _xctest_output = _output_name + "_module"
+
+ _host_target = _target_name
+ _host_output = _output_name
+
+ # Allow invokers to specify their own target for the xctest module, but
+ # fall back to a default (empty) module otherwise.
+ if (defined(invoker.xctest_module_target)) {
+ _xctest_module_target = invoker.xctest_module_target
+ } else {
+ _xctest_module_target_name = _xctest_target + "shell_source"
+ _xctest_module_target = ":$_xctest_module_target_name"
+ source_set(_xctest_module_target_name) {
+ sources = [ "//build/config/ios/xctest_shell.mm" ]
+
+ configs += [ "//build/config/ios:xctest_config" ]
+ }
+ }
+
+ ios_xctest_bundle(_xctest_target) {
+ forward_variables_from(invoker, [ "data_deps" ])
+ output_name = _xctest_output
+ product_type = _ios_xcode_xctest_bundle_id
+ host_target = _host_target
+
+ # TODO(crbug.com/1056328) The change in output name results in a mismatch
+ # between this value and the ios_app_bundle target name. To mitigate, this
+ # has been modified to _host_target. output_name is set to _host_output
+ # to mitigate the naming.
+ xcode_test_application_name = _host_target
+ xcode_test_application_output_name = _host_output
+
+ deps = [ _xctest_module_target ]
+ }
+
+ ios_app_bundle(_host_target) {
+ forward_variables_from(invoker, "*", [ "testonly" ])
+
+ testonly = true
+ output_name = _host_output
+ configs += [ "//build/config/ios:xctest_config" ]
+
+ if (!defined(invoker.info_plist) && !defined(invoker.info_plist_target)) {
+ info_plist = "//build/config/ios/Host-Info.plist"
+ }
+
+ # Xcode needs the following frameworks installed in the application (and
+ # signed) for the XCTest to run, so install them using
+ # extra_system_frameworks.
+ extra_system_frameworks = [
+ "$ios_sdk_platform_path/Developer/Library/Frameworks/XCTest.framework",
+ "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCTAutomationSupport.framework",
+ "$ios_sdk_platform_path/Developer/usr/lib/libXCTestBundleInject.dylib",
+ ]
+
+ # Xcode 13 now depends on XCTestCore. To keep things future proof, copy over
+ # everything that Xcode copies.
+ if (xcode_version_int >= 1300) {
+ extra_system_frameworks += [
+ "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCTestCore.framework",
+ "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCUIAutomation.framework",
+ "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCUnit.framework",
+ "$ios_sdk_platform_path/Developer/usr/lib/libXCTestSwiftSupport.dylib",
+ ]
+ }
+
+ _xctest_bundle = _xctest_target + "_bundle"
+ if (!is_fat_secondary_toolchain) {
+ if (!defined(bundle_deps)) {
+ bundle_deps = []
+ }
+ bundle_deps += [ ":$_xctest_bundle" ]
+ }
+ }
+}
+
+set_defaults("ios_xctest_test") {
+ configs = default_executable_configs
+}
+
+# Template to build a xcuitest test runner bundle.
+#
+# Xcode requires a test runner application with a copy of the XCTest dynamic
+# library bundle in it for the XCUITest to run. The test runner bundle is created
+# by copying the system bundle XCTRunner.app from Xcode SDK with the plist file
+# being properly tweaked, and a xctest and it needs to be code signed in order
+# to run on devices.
+#
+# Arguments
+#
+# xctest_bundle
+# string, name of the dependent xctest bundle target.
+#
+# output_name
+# (optional) string, name of the generated application, if omitted,
+# defaults to the target_name.
+#
+template("ios_xcuitest_test_runner_bundle") {
+ assert(defined(invoker.xctest_bundle),
+ "xctest_bundle must be defined for $target_name")
+
+ _target_name = target_name
+ _output_name = target_name
+ if (defined(invoker.output_name)) {
+ _output_name = invoker.output_name
+ }
+
+ _xctrunner_path =
+ "$ios_sdk_platform_path/Developer/Library/Xcode/Agents/XCTRunner.app"
+
+ _info_plist_merge_plist = _target_name + "_info_plist_merge_plist"
+ _info_plist_target = _target_name + "_info_plist"
+ _info_plist_bundle = _target_name + "_info_plist_bundle"
+
+ action(_info_plist_merge_plist) {
+ testonly = true
+ script = "//build/apple/plist_util.py"
+
+ sources = [
+ "$_xctrunner_path/Info.plist",
+
+ # NOTE: The XCTRunnerAddition+Info.plist must come after the Info.plist
+ # because it overrides the values under "CFBundleIdentifier" and
+ # "CFBundleName".
+ "//build/config/ios/resources/XCTRunnerAddition+Info.plist",
+ ]
+
+ _output_name = "$target_gen_dir/${_target_name}_merged.plist"
+ outputs = [ _output_name ]
+ args = [
+ "merge",
+ "-f=xml1",
+ "-x=$xcode_version",
+ "-o=" + rebase_path(_output_name, root_build_dir),
+ ] + rebase_path(sources, root_build_dir)
+
+ if (use_system_xcode && use_goma) {
+ deps = [ "//build/config/ios:copy_xctrunner_app" ]
+ }
+ }
+
+ ios_info_plist(_info_plist_target) {
+ testonly = true
+ visibility = [ ":$_info_plist_bundle" ]
+
+ executable_name = _output_name
+ info_plist_target = ":$_info_plist_merge_plist"
+ }
+
+ bundle_data(_info_plist_bundle) {
+ testonly = true
+ visibility = [ ":$_target_name" ]
+
+ public_deps = [ ":$_info_plist_target" ]
+
+ sources = get_target_outputs(":$_info_plist_target")
+ outputs = [ "{{bundle_contents_dir}}/Info.plist" ]
+ }
+
+ _pkginfo_bundle = _target_name + "_pkginfo_bundle"
+ bundle_data(_pkginfo_bundle) {
+ testonly = true
+ visibility = [ ":$_target_name" ]
+
+ sources = [ "$_xctrunner_path/PkgInfo" ]
+
+ outputs = [ "{{bundle_contents_dir}}/PkgInfo" ]
+
+ if (use_system_xcode && use_goma) {
+ public_deps = [ "//build/config/ios:copy_xctrunner_app" ]
+ }
+ }
+
+ _xctest_bundle = invoker.xctest_bundle
+ create_signed_bundle(_target_name) {
+ testonly = true
+
+ bundle_binary_target = "//build/config/ios:xctest_runner_without_arm64e"
+ bundle_binary_output = "XCTRunner"
+ bundle_extension = ".app"
+ product_type = _ios_xcode_app_bundle_id
+
+ output_name = _output_name
+
+ # Xcode needs the following frameworks installed in the application
+ # (and signed) for the XCUITest to run, so install them using
+ # extra_system_frameworks.
+ extra_system_frameworks = [
+ "$ios_sdk_platform_path/Developer/Library/Frameworks/XCTest.framework",
+ "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCTAutomationSupport.framework",
+ ]
+
+ # Xcode 13 now depends on XCTestCore. To keep things future proof, copy over
+ # everything that Xcode copies.
+ if (xcode_version_int >= 1300) {
+ extra_system_frameworks += [
+ "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCTestCore.framework",
+ "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCUIAutomation.framework",
+ "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCUnit.framework",
+ "$ios_sdk_platform_path/Developer/usr/lib/libXCTestSwiftSupport.dylib",
+ ]
+ }
+
+ bundle_deps = []
+ if (defined(invoker.bundle_deps)) {
+ bundle_deps += invoker.bundle_deps
+ }
+ bundle_deps += [
+ ":$_info_plist_bundle",
+ ":$_pkginfo_bundle",
+ ":$_xctest_bundle",
+ ]
+ }
+}
+
+# Template to build a XCUITest that consists of two parts: the test runner
+# application bundle and the xctest dynamic library.
+#
+# Arguments
+#
+# deps:
+# list of labels to depends on, these values are used to create the
+# xctest dynamic library.
+#
+# xcode_test_application_name:
+# string, name of the test application for the ui test target.
+#
+# This template defines two targets, one named "${target_name}_module" is the
+# xctest dynamic library, and the other named "${target_name}_runner" is the
+# test runner application bundle.
+#
+template("ios_xcuitest_test") {
+ assert(defined(invoker.deps), "deps must be defined for $target_name")
+ assert(defined(invoker.xcode_test_application_name),
+ "xcode_test_application_name must be defined for $target_name")
+
+ _xcuitest_target = target_name
+ if (defined(invoker.output_name)) {
+ _xcuitest_target = invoker.output_name
+ }
+
+ _xcuitest_runner_target = _xcuitest_target + "_runner"
+ _xcuitest_module_target = _xcuitest_target + "_module"
+
+ group(target_name) {
+ testonly = true
+
+ deps = [ ":$_xcuitest_runner_target" ]
+ }
+
+ _xcuitest_module_output = _xcuitest_target
+ ios_xctest_bundle(_xcuitest_module_target) {
+ forward_variables_from(invoker,
+ [
+ "xcode_test_application_name",
+ "xctest_bundle_principal_class",
+ "data_deps",
+ ])
+
+ product_type = _ios_xcode_xcuitest_bundle_id
+ host_target = _xcuitest_runner_target
+ output_name = _xcuitest_module_output
+
+ deps = invoker.deps
+ }
+
+ _xcuitest_runner_output = _xcuitest_target + "-Runner"
+ ios_xcuitest_test_runner_bundle(_xcuitest_runner_target) {
+ output_name = _xcuitest_runner_output
+ xctest_bundle = _xcuitest_module_target + "_bundle"
+ forward_variables_from(invoker, [ "bundle_deps" ])
+ }
+}
+
+set_defaults("ios_xcuitest_test") {
+ configs = default_executable_configs
+}
diff --git a/third_party/libwebrtc/build/config/ios/strip_arm64e.py b/third_party/libwebrtc/build/config/ios/strip_arm64e.py
new file mode 100644
index 0000000000..f21baf423d
--- /dev/null
+++ b/third_party/libwebrtc/build/config/ios/strip_arm64e.py
@@ -0,0 +1,70 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Strip arm64e architecture from a binary if present."""
+
+import argparse
+import os
+import shutil
+import subprocess
+import sys
+
+
+def check_output(command):
+ """Returns the output from |command| or propagates error, quitting script."""
+ process = subprocess.Popen(
+ command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ outs, errs = process.communicate()
+ if process.returncode:
+ sys.stderr.write('error: command failed with retcode %d: %s\n\n' %
+ (process.returncode, ' '.join(map(repr, command))))
+ sys.stderr.write(errs.decode('UTF-8', errors='ignore'))
+ sys.exit(process.returncode)
+ return outs.decode('UTF-8')
+
+
+def check_call(command):
+ """Invokes |command| or propagates error."""
+ check_output(command)
+
+
+def parse_args(args):
+ """Parses the command-line."""
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--input', required=True, help='Path to input binary')
+ parser.add_argument('--output', required=True, help='Path to output binary')
+ parser.add_argument('--xcode-version', required=True, help='Version of Xcode')
+ return parser.parse_args(args)
+
+
+def get_archs(path):
+ """Extracts the architectures present in binary at |path|."""
+ outputs = check_output(["xcrun", "lipo", "-info", os.path.abspath(path)])
+ return outputs.split(': ')[-1].split()
+
+
+def main(args):
+ parsed = parse_args(args)
+
+ outdir = os.path.dirname(parsed.output)
+ if not os.path.isdir(outdir):
+ os.makedirs(outdir)
+
+ if os.path.exists(parsed.output):
+ os.unlink(parsed.output)
+
+ # As "lipo" fails with an error if asked to remove an architecture that is
+ # not included, only use it if "arm64e" is present in the binary. Otherwise
+ # simply copy the file.
+ if 'arm64e' in get_archs(parsed.input):
+ check_output([
+ "xcrun", "lipo", "-remove", "arm64e", "-output",
+ os.path.abspath(parsed.output),
+ os.path.abspath(parsed.input)
+ ])
+ else:
+ shutil.copy(parsed.input, parsed.output)
+
+
+if __name__ == '__main__':
+ main(sys.argv[1:])
diff --git a/third_party/libwebrtc/build/config/ios/write_framework_hmap.py b/third_party/libwebrtc/build/config/ios/write_framework_hmap.py
new file mode 100644
index 0000000000..ac467ee92a
--- /dev/null
+++ b/third_party/libwebrtc/build/config/ios/write_framework_hmap.py
@@ -0,0 +1,103 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from __future__ import print_function
+
+import os
+import struct
+import sys
+
+def Main(args):
+ if len(args) < 4:
+ print(
+ "Usage: %s output.hmap Foo.framework header1.h..." % args[0],
+ file=sys.stderr)
+ return 1
+
+ (out, framework, all_headers) = args[1], args[2], args[3:]
+
+ framework_name = os.path.basename(framework).split('.')[0]
+ all_headers = map(os.path.abspath, all_headers)
+ filelist = {}
+ for header in all_headers:
+ filename = os.path.basename(header)
+ filelist[filename] = header
+ filelist[os.path.join(framework_name, filename)] = header
+ WriteHmap(out, filelist)
+ return 0
+
+
+def NextGreaterPowerOf2(x):
+ return 2**(x).bit_length()
+
+
+def WriteHmap(output_name, filelist):
+ """Generates a header map based on |filelist|.
+
+ Per Mark Mentovai:
+ A header map is structured essentially as a hash table, keyed by names used
+ in #includes, and providing pathnames to the actual files.
+
+ The implementation below and the comment above comes from inspecting:
+ http://www.opensource.apple.com/source/distcc/distcc-2503/distcc_dist/include_server/headermap.py?txt
+ while also looking at the implementation in clang in:
+ https://llvm.org/svn/llvm-project/cfe/trunk/lib/Lex/HeaderMap.cpp
+ """
+ magic = 1751998832
+ version = 1
+ _reserved = 0
+ count = len(filelist)
+ capacity = NextGreaterPowerOf2(count)
+ strings_offset = 24 + (12 * capacity)
+ max_value_length = len(max(filelist.values(), key=lambda v: len(v)))
+
+ out = open(output_name, 'wb')
+ out.write(struct.pack('<LHHLLLL', magic, version, _reserved, strings_offset,
+ count, capacity, max_value_length))
+
+ # Create empty hashmap buckets.
+ buckets = [None] * capacity
+ for file, path in filelist.items():
+ key = 0
+ for c in file:
+ key += ord(c.lower()) * 13
+
+ # Fill next empty bucket.
+ while buckets[key & capacity - 1] is not None:
+ key = key + 1
+ buckets[key & capacity - 1] = (file, path)
+
+ next_offset = 1
+ for bucket in buckets:
+ if bucket is None:
+ out.write(struct.pack('<LLL', 0, 0, 0))
+ else:
+ (file, path) = bucket
+ key_offset = next_offset
+ prefix_offset = key_offset + len(file) + 1
+ suffix_offset = prefix_offset + len(os.path.dirname(path) + os.sep) + 1
+ next_offset = suffix_offset + len(os.path.basename(path)) + 1
+ out.write(struct.pack('<LLL', key_offset, prefix_offset, suffix_offset))
+
+ # Pad byte since next offset starts at 1.
+ out.write(struct.pack('<x'))
+
+ for bucket in buckets:
+ if bucket is not None:
+ (file, path) = bucket
+ base = os.path.dirname(path) + os.sep
+ path = os.path.basename(path)
+ file = file.encode('UTF-8')
+ base = base.encode('UTF-8')
+ path = path.encode('UTF-8')
+ out.write(struct.pack('<%ds' % len(file), file))
+ out.write(struct.pack('<s', b'\0'))
+ out.write(struct.pack('<%ds' % len(base), base))
+ out.write(struct.pack('<s', b'\0'))
+ out.write(struct.pack('<%ds' % len(path), path))
+ out.write(struct.pack('<s', b'\0'))
+
+
+if __name__ == '__main__':
+ sys.exit(Main(sys.argv))
diff --git a/third_party/libwebrtc/build/config/ios/write_framework_modulemap.py b/third_party/libwebrtc/build/config/ios/write_framework_modulemap.py
new file mode 100644
index 0000000000..dcc88a8ea6
--- /dev/null
+++ b/third_party/libwebrtc/build/config/ios/write_framework_modulemap.py
@@ -0,0 +1,28 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import sys
+
+MODULE_MAP_TEMPLATE = '''\
+framework module %(framework_name)s {
+ umbrella header "%(framework_name)s.h"
+
+ export *
+ module * { export * }
+}
+'''
+
+
+def Main(framework_name, modules_dir):
+ # Find the name of the binary based on the part before the ".framework".
+ if not os.path.isdir(modules_dir):
+ os.makedirs(modules_dir)
+
+ with open(os.path.join(modules_dir, 'module.modulemap'), 'w') as module_file:
+ module_file.write(MODULE_MAP_TEMPLATE % {'framework_name': framework_name})
+
+
+if __name__ == '__main__':
+ Main(*sys.argv[1:])
diff --git a/third_party/libwebrtc/build/config/ios/xctest_shell.mm b/third_party/libwebrtc/build/config/ios/xctest_shell.mm
new file mode 100644
index 0000000000..dcf5bad5e7
--- /dev/null
+++ b/third_party/libwebrtc/build/config/ios/xctest_shell.mm
@@ -0,0 +1,19 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <UIKit/UIKit.h>
+#import <XCTest/XCTest.h>
+
+// For Chrome on iOS we want to run EarlGrey tests (that are XCTests) for all
+// our build configurations (Debug, Release, ...). In addition, the symbols
+// visibility is configured to private by default. To simplify testing with
+// those constraints, our tests are compiled in the TEST_HOST target instead
+// of the .xctest bundle that all link against this single test (just there to
+// ensure that the bundle is not empty).
+
+@interface XCTestShellEmptyClass : NSObject
+@end
+
+@implementation XCTestShellEmptyClass
+@end