Files
2025-05-24 02:02:35 +05:30

6.2 KiB

Control your app's structure

Add resources, modify your Info.plist, and more.

Overview

When building your app, xtool provides many knobs to add resources and modify files in its .app bundle. This article explains how to perform some common tasks along these lines.

Many of the tasks here involve modifying the xtool.yml file. The default xtool new template should generate this file for you. If you don't have it, make sure you create one first.

cat > xtool.yml << EOF
version: 1
bundleID: com.example.Hello
EOF

Change your bundle ID

You can update your app's bundle ID by editing the bundleID field in xtool.yml.

Note:

xtool adds a prefix to your bundle ID when signing and installing the app on a real device. For example, it may update the above bundle id to XTL-1234.com.example.Hello. This is because, at least with free accounts (those not enrolled in the Apple Developer Program), two accounts cannot use the same bundle ID. Prefixing ensures that if you share your app with someone else, they won't run into a bundle ID conflict when installing it.

With additional engineering effort, this limitation could be lifted for paid Developer Program users by leveraging wildcard provisioning profiles. If you have a concrete use case for this and/or wish to contribute, please file an issue.

Customize Info.plist

xtool automatically generates a bare-bones Info.plist file for you. However, you may need to add new Info.plist keys or edit existing ones.

To do this, create an Info.plist file in your project containing just the keys you want to add/update, and tell xtool about it by adding the infoPath key:

infoPath: path/to/Info.plist

Tip:

After running xtool dev [build], you can inspect the built app bundle at ./xtool/YourApp.app to view its Info.plist and other resources.

For example, you might create an Info.plist file that looks something like

<?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>UISupportedInterfaceOrientations</key>
    <array>
        <string>UIInterfaceOrientationLandscapeLeft</string>
        <string>UIInterfaceOrientationLandscapeRight</string>
    </array>
    <key>CFBundleDisplayName</key>
    <string>My App</string>
</dict>
</plist>
  • The default Info.plist has a UISupportedInterfaceOrientations value of portrait. This will replace it with landscape-only.
  • We don't include a CFBundleDisplayName by default, so this will add the key and specify a display name of "My App".

Copy resources (SwiftPM)

If you need to include non-code resource files, like images, the easiest way to do so is to use SwiftPM Resources. These "just work" with xtool.

For example, if you have Sources/Hello/Blob.png, you can include it in your app by updating the targets in your Package.swift to

targets: [
    .target(
        name: "Hello",
        resources: [.copy("Blob.png")]
    ),
]

Then, to draw it on screen, you can use

Image("Blob", bundle: Bundle.module)

Copy resources (top level)

SwiftPM resources are copied into .bundle directories nested inside your .app. Sometimes, you need to place a file in a specific location in the app directory instead.

To achieve this, you can include a resources array in your xtool.yml containing a list of files that should be directly included at the root level of the app bundle.

For example, if you use Firebase, you usually need to include a GoogleServices-Info.plist file in your root bundle. If you saved this file in your project directory at ./Resources/GoogleServices-Info.plist, you can update your xtool.yml with

resources:
- Resources/GoogleServices-Info.plist

The file will be copied to Hello.app/GoogleServices-Info.plist.

Add an app icon

Say your app icon is saved at Resources/AppIcon.png. You can make this your app icon by setting the iconPath key in xtool.yml:

iconPath: Resources/AppIcon.png

Tip:

Your app icon must be a png, and it should ideally have a resolution of 1024x1024px.

Add entitlements

You may need to add special entitlements to your app, for example you need the com.apple.developer.homekit entitlement in order to connect to HomeKit devices.

First create an App.entitlements file with the necessary entitlements:

<?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>com.apple.developer.homekit</key>
    <true/>
</dict>
</plist>

Then, tell xtool about it via xtool.yml:

entitlementsPath: App.entitlements

Troubleshooting:

There are a number of situations in which xtool may not be able to successfully apply an entitlement to your app.

  • Some entitlements, such as Network Extension, don't work with free developer accounts. You might need to enrol in one of the Apple Developer Programs to use these.
  • Other entitlements, like User Notifications Filtering, require special permission from Apple. If you do have the appropriate permission, these may or may not work with xtool.
  • Many entitlements require specific "Capabilities" to be enabled on your app in the Developer Services portal. xtool handles this for you, but we need to add code to xtool for each Entitlement-Capability mapping. If you run into a Capability that we don't handle yet, please let us know.

Entitlements are a large surface area. If you find any bugs or missing functionality, please create a GitHub Issue.