Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

App Extension Info.plist Validation #1946

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apple/internal/apple_product_type.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ apple_product_type = struct(
app_extension = "com.apple.product-type.app-extension",
bundle = "com.apple.product-type.bundle",
dylib = "com.apple.product-type.library.dynamic",
extensionkit_extension = "com.apple.product-type.extensionkit-extension",
framework = "com.apple.product-type.framework",
kernel_extension = "com.apple.product-type.kernel-extension",
messages_application = "com.apple.product-type.application.messages",
Expand Down
31 changes: 26 additions & 5 deletions apple/internal/ios_rules.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -950,13 +950,24 @@ def _ios_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
extensionkit_keys_required = True
nsextension_keys_required = False
else:
bundle_location = processor.location.plugin
extensionkit_keys_required = False
nsextension_keys_required = True

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 Down Expand Up @@ -990,11 +1001,18 @@ def _ios_extension_impl(ctx):
predeclared_outputs = predeclared_outputs,
)

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

processor_partials = [
partials.app_assets_validation_partial(
app_icons = ctx.files.app_icons,
platform_prerequisites = platform_prerequisites,
product_type = rule_descriptor.product_type,
product_type = product_type,
),
partials.apple_bundle_info_partial(
actions = actions,
Expand All @@ -1007,7 +1025,7 @@ def _ios_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 All @@ -1028,7 +1046,7 @@ def _ios_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 Down Expand Up @@ -1061,7 +1079,8 @@ def _ios_extension_impl(ctx):
partials.embedded_bundles_partial(
embeddable_targets = ctx.attr.frameworks,
platform_prerequisites = platform_prerequisites,
plugins = [archive_for_embedding],
plugins = plugins,
extensions = extensions,
),
partials.extension_safe_validation_partial(
is_extension_safe = True,
Expand All @@ -1076,7 +1095,9 @@ def _ios_extension_impl(ctx):
bundle_name = bundle_name,
environment_plist = ctx.file._environment_plist,
executable_name = executable_name,
extensionkit_keys_required = extensionkit_keys_required,
launch_storyboard = None,
nsextension_keys_required = nsextension_keys_required,
platform_prerequisites = platform_prerequisites,
resource_deps = resource_deps,
rule_descriptor = rule_descriptor,
Expand Down
31 changes: 26 additions & 5 deletions apple/internal/macos_rules.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -562,13 +562,24 @@ def _macos_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
extensionkit_keys_required = True
nsextension_keys_required = False
else:
bundle_location = processor.location.plugin
extensionkit_keys_required = False
nsextension_keys_required = True

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 @@ -583,14 +594,21 @@ def _macos_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_name = bundle_name,
bundle_extension = bundle_extension,
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 @@ -603,7 +621,7 @@ def _macos_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 All @@ -625,7 +643,7 @@ def _macos_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,
entitlements = entitlements.codesigning,
Expand All @@ -647,7 +665,8 @@ def _macos_extension_impl(ctx):
),
partials.embedded_bundles_partial(
platform_prerequisites = platform_prerequisites,
plugins = [archive],
plugins = plugins,
extensions = extensions,
),
partials.macos_additional_contents_partial(
additional_contents = ctx.attr.additional_contents,
Expand All @@ -660,7 +679,9 @@ def _macos_extension_impl(ctx):
bundle_name = bundle_name,
environment_plist = ctx.file._environment_plist,
executable_name = executable_name,
extensionkit_keys_required = extensionkit_keys_required,
launch_storyboard = None,
nsextension_keys_required = nsextension_keys_required,
platform_prerequisites = platform_prerequisites,
resource_deps = resource_deps,
rule_descriptor = rule_descriptor,
Expand Down
2 changes: 2 additions & 0 deletions apple/internal/partials/codesigning_dossier.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ Depset of structs with codesigning dossier information to be embedded in another

_VALID_LOCATIONS = sets.make([
processor.location.app_clip,
processor.location.extension,
processor.location.framework,
processor.location.plugin,
processor.location.watch,
Expand Down Expand Up @@ -77,6 +78,7 @@ def _location_map(rule_descriptor):
resolved = rule_descriptor.bundle_locations
return {
processor.location.app_clip: resolved.contents_relative_app_clips,
processor.location.extension: resolved.contents_relative_extensions,
processor.location.framework: resolved.contents_relative_frameworks,
processor.location.plugin: resolved.contents_relative_plugins,
processor.location.watch: resolved.contents_relative_watch,
Expand Down
5 changes: 5 additions & 0 deletions apple/internal/partials/embedded_bundles.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ def _embedded_bundles_partial_impl(
# Map of embedded bundle type to their final location in the top-level bundle.
bundle_type_to_location = {
"app_clips": processor.location.app_clip,
"extensions": processor.location.extension,
"frameworks": processor.location.framework,
"plugins": processor.location.plugin,
"watch_bundles": processor.location.watch,
Expand Down Expand Up @@ -145,6 +146,7 @@ def embedded_bundles_partial(
app_clips = [],
bundle_embedded_bundles = False,
embeddable_targets = [],
extensions = [],
frameworks = [],
platform_prerequisites,
plugins = [],
Expand All @@ -166,6 +168,8 @@ def embedded_bundles_partial(
embeddable bundles will be propagated downstream for a top level target to bundle them.
embeddable_targets: The list of targets that propagate embeddable bundles to bundle or
propagate.
extensions: List of extension bundles that should be propagated downstream for a top level
target to bundle inside `Extensions`.
frameworks: List of framework bundles that should be propagated downstream for a top level
target to bundle inside `Frameworks`.
platform_prerequisites: Struct containing information on the platform being targeted.
Expand All @@ -186,6 +190,7 @@ def embedded_bundles_partial(
app_clips = app_clips,
bundle_embedded_bundles = bundle_embedded_bundles,
embeddable_targets = embeddable_targets,
extensions = extensions,
frameworks = frameworks,
platform_prerequisites = platform_prerequisites,
plugins = plugins,
Expand Down
16 changes: 14 additions & 2 deletions apple/internal/partials/resources.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

"""Partial implementations for resource processing.

Resources are procesed according to type, by a series of methods that deal with the specifics for
Resources are processed according to type, by a series of methods that deal with the specifics for
each resource type. Each of this methods returns a struct, which always have a `files` field
containing resource tuples as described in processor.bzl. Optionally, the structs can also have an
`infoplists` field containing a list of plists that should be merged into the root Info.plist.
Expand Down Expand Up @@ -152,7 +152,9 @@ def _resources_partial_impl(
executable_name,
bundle_verification_targets,
environment_plist,
extensionkit_keys_required,
launch_storyboard,
nsextension_keys_required,
output_discriminator,
platform_prerequisites,
resource_deps,
Expand Down Expand Up @@ -317,8 +319,10 @@ def _resources_partial_impl(
child_plists = bundle_verification_infoplists,
child_required_values = bundle_verification_required_values,
environment_plist = environment_plist,
extensionkit_keys_required = extensionkit_keys_required,
input_plists = infoplists,
launch_storyboard = launch_storyboard,
nsextension_keys_required = nsextension_keys_required,
out_infoplist = out_infoplist,
output_discriminator = output_discriminator,
platform_prerequisites = platform_prerequisites,
Expand Down Expand Up @@ -346,7 +350,9 @@ def resources_partial(
executable_name,
bundle_verification_targets = [],
environment_plist,
extensionkit_keys_required = False,
launch_storyboard,
nsextension_keys_required = False,
output_discriminator = None,
platform_prerequisites,
resource_deps,
Expand All @@ -371,14 +377,18 @@ def resources_partial(
occur.
bundle_name: The name of the output bundle.
executable_name: The name of the output executable.
bundle_verification_targets: List of structs that reference embedable targets that need to
bundle_verification_targets: List of structs that reference embeddable targets that need to
be validated. The structs must have a `target` field with the target containing an
Info.plist file that will be validated. The structs may also have a
`parent_bundle_id_reference` field that contains the plist path, in list form, to the
plist entry that must contain this target's bundle ID.
environment_plist: File referencing a plist with the required variables about the versions
the target is being built for and with.
extensionkit_keys_required: Whether to validate that the Info.plist ExtensionKit keys are correctly
configured.
launch_storyboard: A file to be used as a launch screen for the application.
nsextension_keys_required: Whether to validate that the Info.plist ExtensionKit keys are correctly
configured.
output_discriminator: A string to differentiate between different target intermediate files
or `None`.
platform_prerequisites: Struct containing information on the platform being targeted.
Expand Down Expand Up @@ -406,9 +416,11 @@ def resources_partial(
bundle_id = bundle_id,
bundle_name = bundle_name,
executable_name = executable_name,
extensionkit_keys_required = extensionkit_keys_required,
bundle_verification_targets = bundle_verification_targets,
environment_plist = environment_plist,
launch_storyboard = launch_storyboard,
nsextension_keys_required = nsextension_keys_required,
output_discriminator = output_discriminator,
platform_prerequisites = platform_prerequisites,
resource_deps = resource_deps,
Expand Down
6 changes: 6 additions & 0 deletions apple/internal/processor.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Location types can be:
- binary: Files are to be placed in the binary section of the bundle.
- bundle: Files are to be placed at the root of the bundle.
- content: Files are to be placed in the contents section of the bundle.
- extension: Files are to be placed in the Extensions section of the bundle.
- framework: Files are to be placed in the Frameworks section of the bundle.
- plugin: Files are to be placed in the PlugIns section of the bundle.
- resources: Files are to be placed in the resources section of the bundle.
Expand Down Expand Up @@ -107,6 +108,7 @@ _LOCATION_ENUM = struct(
binary = "binary",
bundle = "bundle",
content = "content",
extension = "extension",
framework = "framework",
plugin = "plugin",
resource = "resource",
Expand Down Expand Up @@ -195,6 +197,10 @@ def _archive_paths(
),
_LOCATION_ENUM.bundle: bundle_path,
_LOCATION_ENUM.content: contents_path,
_LOCATION_ENUM.extension: paths.join(
contents_path,
rule_descriptor.bundle_locations.contents_relative_extensions,
),
_LOCATION_ENUM.framework: paths.join(
contents_path,
rule_descriptor.bundle_locations.contents_relative_frameworks,
Expand Down
3 changes: 3 additions & 0 deletions apple/internal/providers/embeddable_info.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ _APPLE_EMBEDDABLE_INFO_FIELDS = {
"app_clips": """
A depset with the zipped archives of bundles that need to be expanded into the
AppClips section of the packaging bundle.""",
"extensions": """
A depset with the zipped archives of bundles that need to be expanded into the
Extensions section of the packaging bundle.""",
"frameworks": """
A depset with the zipped archives of bundles that need to be expanded into the
Frameworks section of the packaging bundle.""",
Expand Down
14 changes: 14 additions & 0 deletions apple/internal/resource_actions/plist.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,11 @@ def merge_root_infoplists(
child_plists = [],
child_required_values = [],
environment_plist,
extensionkit_keys_required = False,
include_executable_name = True,
input_plists,
launch_storyboard,
nsextension_keys_required = False,
output_discriminator,
output_plist,
output_pkginfo,
Expand Down Expand Up @@ -223,11 +225,17 @@ def merge_root_infoplists(
pair, see plisttool's `child_plist_required_values`, as this is passed
straight through to it.
environment_plist: An executable file referencing the environment_plist tool.
extensionkit_keys_required: If True, the merged Info.plist file must include
an EXAppExtensionAttributes dictionary containing EXExtensionPointIdentifier.
The presence of an NSExtension entry will raise an error.
include_executable_name: If True, the executable name will be added to
the plist in the `CFBundleExecutable` key. This is mainly intended for
plists embedded in a command line tool which don't need this value.
input_plists: The root plist files to merge.
launch_storyboard: A file to be used as a launch screen for the application.
nsextension_keys_required: If True, the merged Info.plist file must include
an NSExtension dictionary containing NSExtensionPointIdentifier.
The presence of an EXAppExtensionAttributes entry will raise an error.
output_discriminator: A string to differentiate between different target intermediate files
or `None`.
output_pkginfo: The file reference for the PkgInfo file. Can be None if not
Expand Down Expand Up @@ -298,6 +306,12 @@ def merge_root_infoplists(
**{str(p.owner): v for (p, v) in child_required_values}
)

if extensionkit_keys_required:
info_plist_options["extensionkit_keys_required"] = True

if nsextension_keys_required:
info_plist_options["nsextension_keys_required"] = True

if (version != None and AppleBundleVersionInfo in version):
version_info = version[AppleBundleVersionInfo]
input_files.append(version_info.version_file)
Expand Down
1 change: 1 addition & 0 deletions apple/internal/resources.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ def _get_attr_as_list(*, attr, nested_attr, split_attr_keys):
attr = attr,
nested_attr = nested_attr,
))

else:
# Search the attribute within each split key if any split keys were defined.
for split_attr_key in split_attr_keys:
Expand Down
Loading