rules_apple
rules_apple copied to clipboard
ExtensionKit App Extensions not supported
App extensions like Background Assets are of type EXAppExtension
, instead of NSExtension
, and have some different build settings. An EXAppExtension
is of product type com.apple.product-type.extensionkit-extension
and installed into the Extensions
directory instead of PlugIns
.
Trying to configure a Background Asset downloader extension with current Bazel rules will run into validation errors, since PlugIns
expect an NSExtension
dictionary in Info.plist, but the extension point com.apple.background-asset-downloader-extension
disallows that property.
For now, we can work around this simply by moving the .appex
bundle from PlugIns
to Extensions
.
The new ExtensionKit Extension is very similar to the current App Extension, just with a few differences.
App Extension | ExtensionKit Extension | |
---|---|---|
xcode project type | com.apple.product-type.app-extension | com.apple.product-type.extensionkit-extension |
Info.plist | NSEXtensions |
EXAppExtensionAttributes |
bundle folder | *.app/PlugIns | *.app/Extensions |
There are two potential approaches to implement this:
- Add a parameter (maybe called "extension_type"?) to the existing
ios_extension
rule, but it looks we have "one product type per rule" convention inrules_apple
. - Add a new rule called
ios_extensionkit_extension
. This will be extremely similar toios_extension
. We probably also need to renameios_extension
toios_app_extension
for claritrty.
We're happy to implement this, but want to start the discussion beforehand. cc: @keith
I noticed the watchos_extension
has an attribute to change the product type and linking flags. It's used by setting application_extension = True
on watchos_extension
. We could follow a similar pattern with setting extensionkit_extension = True
Thanks for the extensive and detailed proposal! I think going with an attribute like you did in the linked PR probably makes sense. From what I understand, all extensions support both types except the new "Background Assets" which only supports EXAppExtension
? We should make sure that we disallow making the mistake of creating a Background Assets extension but not setting extensionkit_extension = True
(either if some Apple validation tool would fail during compilation, or in our rules).
I'm not sure which extension types are valid for ExtensionKit vs older app extensions, but I agree that an error would be helpful to surface this to consumers. I agree a disallow-list will be more helpful than an allow-list, since Apple will release new extension types, and consumers shouldn't need to wait for updates.
We've noticed that creating a Background Asset extension as an older extension type (NSExtension and app-extension) will compile, but fails App Store validation and won't install to a device/simulator.
To your recommendation of confirming the extension points are valid with ExtensionKit - can we check Info.plist values while building with Bazel? I wasn't sure if Starlark had the ability to read input files. The extension point string defining the extension point is either in the NSExtension
Info.plist dictionary or EXAppExtensionAttributes
dictionary.
Oh, I see. We can follow a similar pattern as plisttool
to run a script and validate fields.
I think some validation warnings/errors can be useful, but we should be cautious not to block future legitimate use cases. Should we create any rule attributes to silence these warnings?
Furthermore, should we use the plist to set the product type instead of expecting extensionkit_extension = True/False
from the rule? (i.e. switch the product type from the presence of NSExtension
or EXAppExtensionAttributes
in the plist)
I just tried quickly to create an Intents extension for iOS (which isn't iOS 16 only), and I could't find a way to have Xcode add it into Extensions
instead of PlugIns
. I tried setting the deployment target to iOS 16.2, so it sounds like only the new extensions which are released and available from iOS 16 onwards support this way of bundling. Have you seen differently? If so, it might be difficult for someone to know to what value they need to set extensionkit_extension
to. It might be better to infer the value from the type of extension, but I'm not sure if there's a way to do that today. I agree with the fact that it might make it more painful in the long-term to support multiple extension types, but it's a tradeoff. I don't have a strong opinion here.
I remembered that we also have something called entitlements_validation_mode
but that's more for provisioning profiles, we could have something similar. Whether an attribute or a flag makes more sense, I'm not sure yet. If we can prevent users from submitting builds which aren't accepted by Apple, I'm all for it (we ran into a few over the last few months and they quite annoying to figure out).
From Info.plist docs, it looks like these are supported NSExtension extension points, and EXExtensionPointIdentifiers aren't documented online, but I scanned Xcode's templates (/Applications/Xcode.app/Contents/Developer/Platforms/*.platform/Developer/Library/Xcode/Templates/Project\ Templates/*/Application\ Extension/
) and found this short list of extension types, and macOS supports third part extension points through ExtensionKit.
I started this commit to plisttool
with the following logic:
- If the extension point string matches a known extension point string for a different App Extension product identifier (e.g. building with ExtensionKit, but recognized the extension as an NSExtension), log a warning, but do not raise an error
- If the extension has a mismatched plist key (e.g. building with ExtensionKit, but found
NSExtension
in Info.plist), raise an error, and provide tips to fix. - If the extension is missing the expected plist key (e.g. building with ExtensionKit, but missing
EXAppExtensionAttributes
in Info.plist), raise an error, and provide tips to fix.
I think this should provide discoverability to the correct build settings without blocking valid use cases, such as:
- Apple creates a new extension point
- Apple changes an extension point to support both NSExtension and ExtensionKit
- Third party ExtensionKit extension point identifiers