Skip to content

Commit

Permalink
Add tvOS ExtensionKit Extension
Browse files Browse the repository at this point in the history
  • Loading branch information
maustinstar committed Apr 18, 2023
1 parent ccc2f24 commit 2eef4f4
Show file tree
Hide file tree
Showing 6 changed files with 240 additions and 8 deletions.
10 changes: 10 additions & 0 deletions apple/internal/rule_factory.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -887,6 +887,16 @@ def _get_tvos_attrs(rule_descriptor):
default = Label("@build_bazel_rules_apple//apple/internal/templates:ios_sim_template"),
),
})
elif rule_descriptor.product_type == apple_product_type.app_extension:
attrs.append({
"extensionkit_extension": attr.bool(
default = False,
doc = """
If `True`, this extension is an ExtensionKit Extension instead of an App Extension.
The bundle is installed into the Extensions directory instead of PlugIns.
""",
),
})
elif rule_descriptor.product_type == apple_product_type.framework:
attrs.append({
# TODO(kaipi): This attribute is not publicly documented, but it is tested in
Expand Down
25 changes: 20 additions & 5 deletions apple/internal/tvos_rules.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -900,13 +900,20 @@ def _tvos_extension_impl(ctx):
],
)

product_type = rule_descriptor.product_type
if ctx.attr.extensionkit_extension:
bundle_location = processor.location.extension
product_type = apple_product_type.extensionkit_extension
else:
bundle_location = processor.location.plugin

entitlements = entitlements_support.process_entitlements(
actions = actions,
apple_mac_toolchain_info = apple_mac_toolchain_info,
bundle_id = bundle_id,
entitlements_file = ctx.file.entitlements,
platform_prerequisites = platform_prerequisites,
product_type = rule_descriptor.product_type,
product_type = product_type,
provisioning_profile = provisioning_profile,
rule_label = label,
validation_mode = ctx.attr.entitlements_validation,
Expand All @@ -922,14 +929,21 @@ def _tvos_extension_impl(ctx):
binary_artifact = link_result.binary
debug_outputs = linking_support.debug_outputs_by_architecture(link_result.outputs)

archive = outputs.archive(
archive_for_embedding = outputs.archive(
actions = actions,
bundle_extension = bundle_extension,
bundle_name = bundle_name,
platform_prerequisites = platform_prerequisites,
predeclared_outputs = predeclared_outputs,
)

if ctx.attr.extensionkit_extension:
plugins = []
extensions = [archive_for_embedding]
else:
plugins = [archive_for_embedding]
extensions = []

processor_partials = [
partials.apple_bundle_info_partial(
actions = actions,
Expand All @@ -942,7 +956,7 @@ def _tvos_extension_impl(ctx):
label_name = label.name,
platform_prerequisites = platform_prerequisites,
predeclared_outputs = predeclared_outputs,
product_type = rule_descriptor.product_type,
product_type = product_type,
),
partials.binary_partial(
actions = actions,
Expand Down Expand Up @@ -972,7 +986,7 @@ def _tvos_extension_impl(ctx):
actions = actions,
apple_mac_toolchain_info = apple_mac_toolchain_info,
bundle_extension = bundle_extension,
bundle_location = processor.location.plugin,
bundle_location = bundle_location,
bundle_name = bundle_name,
embed_target_dossiers = False,
embedded_targets = ctx.attr.frameworks,
Expand All @@ -996,7 +1010,8 @@ def _tvos_extension_impl(ctx):
partials.embedded_bundles_partial(
embeddable_targets = ctx.attr.frameworks,
platform_prerequisites = platform_prerequisites,
plugins = [archive],
plugins = plugins,
extensions = extensions,
),
partials.extension_safe_validation_partial(
is_extension_safe = True,
Expand Down
7 changes: 4 additions & 3 deletions doc/rules-tvos.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,9 @@ Builds and bundles a tvOS dynamic framework that is consumable by Xcode.
<pre>
tvos_extension(<a href="#tvos_extension-name">name</a>, <a href="#tvos_extension-additional_linker_inputs">additional_linker_inputs</a>, <a href="#tvos_extension-bundle_id">bundle_id</a>, <a href="#tvos_extension-bundle_name">bundle_name</a>, <a href="#tvos_extension-codesign_inputs">codesign_inputs</a>,
<a href="#tvos_extension-codesignopts">codesignopts</a>, <a href="#tvos_extension-deps">deps</a>, <a href="#tvos_extension-entitlements">entitlements</a>, <a href="#tvos_extension-entitlements_validation">entitlements_validation</a>, <a href="#tvos_extension-executable_name">executable_name</a>,
<a href="#tvos_extension-exported_symbols_lists">exported_symbols_lists</a>, <a href="#tvos_extension-frameworks">frameworks</a>, <a href="#tvos_extension-infoplists">infoplists</a>, <a href="#tvos_extension-ipa_post_processor">ipa_post_processor</a>, <a href="#tvos_extension-linkopts">linkopts</a>,
<a href="#tvos_extension-minimum_deployment_os_version">minimum_deployment_os_version</a>, <a href="#tvos_extension-minimum_os_version">minimum_os_version</a>, <a href="#tvos_extension-platform_type">platform_type</a>, <a href="#tvos_extension-provisioning_profile">provisioning_profile</a>,
<a href="#tvos_extension-resources">resources</a>, <a href="#tvos_extension-stamp">stamp</a>, <a href="#tvos_extension-strings">strings</a>, <a href="#tvos_extension-version">version</a>)
<a href="#tvos_extension-exported_symbols_lists">exported_symbols_lists</a>, <a href="#tvos_extension-extensionkit_extension">extensionkit_extension</a>, <a href="#tvos_extension-frameworks">frameworks</a>, <a href="#tvos_extension-infoplists">infoplists</a>,
<a href="#tvos_extension-ipa_post_processor">ipa_post_processor</a>, <a href="#tvos_extension-linkopts">linkopts</a>, <a href="#tvos_extension-minimum_deployment_os_version">minimum_deployment_os_version</a>, <a href="#tvos_extension-minimum_os_version">minimum_os_version</a>,
<a href="#tvos_extension-platform_type">platform_type</a>, <a href="#tvos_extension-provisioning_profile">provisioning_profile</a>, <a href="#tvos_extension-resources">resources</a>, <a href="#tvos_extension-stamp">stamp</a>, <a href="#tvos_extension-strings">strings</a>, <a href="#tvos_extension-version">version</a>)
</pre>

Builds and bundles a tvOS Extension.
Expand All @@ -161,6 +161,7 @@ Builds and bundles a tvOS Extension.
| <a id="tvos_extension-entitlements_validation"></a>entitlements_validation | An [<code>entitlements_validation_mode</code>](/doc/types.md#entitlements-validation-mode) to control the validation of the requested entitlements against the provisioning profile to ensure they are supported. | String | optional | <code>"loose"</code> |
| <a id="tvos_extension-executable_name"></a>executable_name | The desired name of the executable, if the bundle has an executable. If this attribute is not set, then the name of the <code>bundle_name</code> attribute will be used if it is set; if not, then the name of the target will be used instead. | String | optional | <code>""</code> |
| <a id="tvos_extension-exported_symbols_lists"></a>exported_symbols_lists | A list of targets containing exported symbols lists files for the linker to control symbol resolution.<br><br>Each file is expected to have a list of global symbol names that will remain as global symbols in the compiled binary owned by this framework. All other global symbols will be treated as if they were marked as <code>__private_extern__</code> (aka <code>visibility=hidden</code>) and will not be global in the output file.<br><br>See the man page documentation for <code>ld(1)</code> on macOS for more details. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | <code>[]</code> |
| <a id="tvos_extension-extensionkit_extension"></a>extensionkit_extension | If <code>True</code>, this extension is an ExtensionKit Extension instead of an App Extension. The bundle is installed into the Extensions directory instead of PlugIns. | Boolean | optional | <code>False</code> |
| <a id="tvos_extension-frameworks"></a>frameworks | A list of framework targets (see [<code>tvos_framework</code>](https://github.com/bazelbuild/rules_apple/blob/master/doc/rules-tvos.md#tvos_framework)) that this target depends on. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | <code>[]</code> |
| <a id="tvos_extension-infoplists"></a>infoplists | A list of .plist files that will be merged to form the Info.plist for this target. At least one file must be specified. Please see [Info.plist Handling](https://github.com/bazelbuild/rules_apple/blob/master/doc/common_info.md#infoplist-handling) for what is supported. | <a href="https://bazel.build/concepts/labels">List of labels</a> | required | |
| <a id="tvos_extension-ipa_post_processor"></a>ipa_post_processor | A tool that edits this target's archive after it is assembled but before it is signed. The tool is invoked with a single command-line argument that denotes the path to a directory containing the unzipped contents of the archive; this target's bundle will be the directory's only contents.<br><br>Any changes made by the tool must be made in this directory, and the tool's execution must be hermetic given these inputs to ensure that the result can be safely cached. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>None</code> |
Expand Down
3 changes: 3 additions & 0 deletions test/starlark_tests/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ load(":tvos_application_swift_tests.bzl", "tvos_application_swift_test_suite")
load(":tvos_application_tests.bzl", "tvos_application_test_suite")
load(":tvos_dynamic_framework_tests.bzl", "tvos_dynamic_framework_test_suite")
load(":tvos_extension_tests.bzl", "tvos_extension_test_suite")
load(":tvos_extensionkit_extension_tests.bzl", "tvos_extensionkit_extension_test_suite")
load(":tvos_framework_tests.bzl", "tvos_framework_test_suite")
load(":tvos_static_framework_tests.bzl", "tvos_static_framework_test_suite")
load(":tvos_ui_test_tests.bzl", "tvos_ui_test_test_suite")
Expand Down Expand Up @@ -124,6 +125,8 @@ tvos_application_test_suite(name = "tvos_application")

tvos_extension_test_suite(name = "tvos_extension")

tvos_extensionkit_extension_test_suite(name = "tvos_extensionkit_extension")

tvos_dynamic_framework_test_suite(name = "tvos_dynamic_framework")

tvos_framework_test_suite(name = "tvos_framework")
Expand Down
58 changes: 58 additions & 0 deletions test/starlark_tests/targets_under_test/tvos/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,64 @@ tvos_extension(

# ---------------------------------------------------------------------------------------

tvos_application(
name = "app_with_exappextension",
bundle_id = "com.google.example",
extensions = [":exappextension"],
infoplists = [
"//test/starlark_tests/resources:Info.plist",
],
minimum_os_version = common.min_os_tvos.baseline,
provisioning_profile = "//test/testdata/provisioning:integration_testing_ios.mobileprovision",
tags = common.fixture_tags,
deps = [
"//test/starlark_tests/resources:objc_main_lib",
],
)

tvos_extension(
name = "exappextension",
bundle_id = "com.google.example.exappextension",
entitlements = "//test/starlark_tests/resources:entitlements.plist",
extensionkit_extension = True,
infoplists = [
"//test/starlark_tests/resources:Info.plist",
],
minimum_os_version = common.min_os_tvos.baseline,
provisioning_profile = "//test/testdata/provisioning:integration_testing_ios.mobileprovision",
tags = common.fixture_tags,
deps = [
"//test/starlark_tests/resources:objc_main_lib",
],
)

tvos_application(
name = "app_with_swift_exappextension",
bundle_id = "com.google.example",
extensions = [":swift_exappextension"],
infoplists = ["//test/starlark_tests/resources:Info.plist"],
minimum_os_version = common.min_os_tvos.baseline,
provisioning_profile = "//test/testdata/provisioning:integration_testing_ios.mobileprovision",
tags = common.fixture_tags,
deps = ["//test/starlark_tests/resources:objc_main_lib"],
)

tvos_extension(
name = "swift_exappextension",
bundle_id = "com.google.example.exappextension",
entitlements = "//test/starlark_tests/resources:entitlements.plist",
extensionkit_extension = True,
infoplists = ["//test/starlark_tests/resources:Info.plist"],
minimum_os_version = common.min_os_tvos.baseline,
provisioning_profile = "//test/testdata/provisioning:integration_testing_ios.mobileprovision",
tags = common.fixture_tags,
deps = [
"//test/starlark_tests/resources:swift_main_lib",
],
)

# ---------------------------------------------------------------------------------------

tvos_application(
name = "app_with_fmwk",
bundle_id = "com.google.example",
Expand Down
145 changes: 145 additions & 0 deletions test/starlark_tests/tvos_extensionkit_extension_tests.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# Copyright 2019 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""tvos_extensionkit_extension Starlark tests."""

load(
":common.bzl",
"common",
)
load(
":rules/apple_verification_test.bzl",
"apple_verification_test",
)
load(
":rules/common_verification_tests.bzl",
"archive_contents_test",
"bitcode_symbol_map_test",
)
load(
":rules/dsyms_test.bzl",
"dsyms_test",
)
load(
":rules/infoplist_contents_test.bzl",
"infoplist_contents_test",
)

def tvos_extensionkit_extension_test_suite(name):
"""Test suite for tvos_extensionkit_extension.
Args:
name: the base name to be used in things created by this macro
"""
apple_verification_test(
name = "{}_codesign_test".format(name),
build_type = "simulator",
target_under_test = "//test/starlark_tests/targets_under_test/tvos:exappextension",
verifier_script = "verifier_scripts/codesign_verifier.sh",
tags = [name],
)

dsyms_test(
name = "{}_dsyms_test".format(name),
target_under_test = "//test/starlark_tests/targets_under_test/tvos:exappextension",
expected_direct_dsyms = ["exappextension.appex"],
expected_transitive_dsyms = ["exappextension.appex"],
tags = [name],
)

infoplist_contents_test(
name = "{}_plist_test".format(name),
target_under_test = "//test/starlark_tests/targets_under_test/tvos:exappextension",
expected_values = {
"BuildMachineOSBuild": "*",
"CFBundleExecutable": "exappextension",
"CFBundleIdentifier": "com.google.example.exappextension",
"CFBundleName": "exappextension",
"CFBundlePackageType": "XPC!",
"CFBundleSupportedPlatforms:0": "AppleTVSimulator*",
"DTCompiler": "com.apple.compilers.llvm.clang.1_0",
"DTPlatformBuild": "*",
"DTPlatformName": "appletvsimulator*",
"DTPlatformVersion": "*",
"DTSDKBuild": "*",
"DTSDKName": "appletvsimulator*",
"DTXcode": "*",
"DTXcodeBuild": "*",
"MinimumOSVersion": common.min_os_tvos.baseline,
"UIDeviceFamily:0": "3",
},
tags = [name],
)

# Tests that the archive contains Bitcode symbol maps when Bitcode is
# enabled.
bitcode_symbol_map_test(
name = "{}_archive_contains_bitcode_symbol_maps_test".format(name),
binary_paths = [
"Payload/app_with_exappextension.app/app_with_exappextension",
"Payload/app_with_exappextension.app/Extensions/exappextension.appex/exappextension",
],
target_under_test = "//test/starlark_tests/targets_under_test/tvos:app_with_exappextension",
tags = [name],
)

# Tests that the provisioning profile is present when built for device.
archive_contents_test(
name = "{}_contains_provisioning_profile_test".format(name),
build_type = "device",
target_under_test = "//test/starlark_tests/targets_under_test/tvos:exappextension",
contains = [
"$BUNDLE_ROOT/embedded.mobileprovision",
],
tags = [name],
)

archive_contents_test(
name = "{}_correct_rpath_header_value_test".format(name),
build_type = "device",
binary_test_file = "$CONTENT_ROOT/exappextension",
macho_load_commands_contain = [
"path @executable_path/Frameworks (offset 12)",
"path @executable_path/../../Frameworks (offset 12)",
],
target_under_test = "//test/starlark_tests/targets_under_test/tvos:exappextension",
tags = [name],
)

# Verify that Swift dylibs are packaged with the application, not with the extension, when only
# an extension uses Swift. And to be safe, verify that they aren't packaged with the extension.
archive_contents_test(
name = "{}_device_swift_dylibs_present".format(name),
build_type = "device",
target_under_test = "//test/starlark_tests/targets_under_test/tvos:app_with_swift_exappextension",
not_contains = ["$BUNDLE_ROOT/Extensions/exappextension.appex/Frameworks/libswiftCore.dylib"],
contains = [
"$BUNDLE_ROOT/Frameworks/libswiftCore.dylib",
"$ARCHIVE_ROOT/SwiftSupport/appletvos/libswiftCore.dylib",
],
tags = [name],
)
archive_contents_test(
name = "{}_simulator_swift_dylibs_present".format(name),
build_type = "simulator",
target_under_test = "//test/starlark_tests/targets_under_test/tvos:app_with_swift_exappextension",
contains = ["$BUNDLE_ROOT/Frameworks/libswiftCore.dylib"],
not_contains = ["$BUNDLE_ROOT/Extensions/exappextension.appex/Frameworks/libswiftCore.dylib"],
tags = [name],
)

native.test_suite(
name = name,
tags = [name],
)

0 comments on commit 2eef4f4

Please sign in to comment.