# macOS Application Bundle

import CommandTabs from '@components/CommandTabs.astro';

An application bundle is the package format that is executed on macOS. It is a simple directory that includes everything your application requires for successful operation,
including your app executable, resources, the Info.plist file and other files such as macOS frameworks.

To package your app as a macOS application bundle you can use the Tauri CLI and run the `tauri build` command in a Mac computer:

<CommandTabs
  npm="npm run tauri build -- --bundles app"
  yarn="yarn tauri build --bundles app"
  pnpm="pnpm tauri build --bundles app"
  deno="deno task tauri build --bundles app"
  bun="bun tauri build --bundles app"
  cargo="cargo tauri build --bundles app"
/>

:::note

GUI apps on macOS and Linux do not inherit the `$PATH` from your shell dotfiles (`.bashrc`, `.bash_profile`, `.zshrc`, etc). Check out Tauri's [fix-path-env-rs](https://github.com/tauri-apps/fix-path-env-rs) crate to fix this issue.

:::

## File structure

The macOS app bundle is a directory with the following structure:

```
├── <productName>.app
│   ├── Contents
│   │   ├── Info.plist
│   │   ├── ...additional files from [`tauri.conf.json > bundle > macOS > files`]
│   ├── MacOS
│   │   ├── <app-name> (app executable)
│   ├── Resources
│   │   ├── icon.icns (app icon)
│   │   ├── ...resources from [`tauri.conf.json > bundle > resources`]
│   ├── _CodeSignature (codesign information generated by Apple)
│   ├── Frameworks
│   ├── PlugIns
│   ├── SharedSupport
```

See the [official documentation](https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFBundles/BundleTypes/BundleTypes.html) for more information.

## Native configuration

The app bundle is configured by the `Info.plist` file, which includes key-value pairs with your app identity and configuration values read by macOS.

Tauri automatically configures the most important properties such as your app binary name, version. bundle identifier, minimum system version and more.

To extend the configuration file, create an `Info.plist` file in the `src-tauri` folder and include the key-pairs you desire:

```xml title="src-tauri/Info.plist"
<?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>NSCameraUsageDescription</key>
	<string>Request camera access for WebRTC</string>
	<key>NSMicrophoneUsageDescription</key>
	<string>Request microphone access for WebRTC</string>
</dict>
</plist>
```

This `Info.plist` file is merged with the values generated by the Tauri CLI. Be careful when overwriting default values such as application version as they might conflict with other configuration values
and introduce unexpected behavior.

See the [official Info.plist documentation] for more information.

### Info.plist localization

The `Info.plist` file by itself only supports a single language, typically English. If you want to support multiple languages, you can create `InfoPlist.strings` files for each additional language. Each file belongs in its own language specific `lproj` directory in the `Resources` directory in the application bundle.

To bundle these files automatically you can leverage Tauri's [resources] feature. To do that, create a file structure in your project following this pattern:

```
├── src-tauri
│   ├── tauri.conf.json
│   ├── infoplist
│   │   ├── de.lproj
│   │   │   ├── InfoPlist.strings
│   │   ├── fr.lproj
│   │   │   ├── InfoPlist.strings
```

While the `infoplist` directory name can be chosen freely, as long as you update it in the resources config below, the `lproj` directories must follow the `<lang-code>.lproj` naming and the string catalogue files must be named `InfoPlist.strings` (capital i and p). For most cases the language code should be a two letter code following [BCP 47].

For the `Info.plist` example shown above, the `de.lproj > InfoPlist.strings` file could look like this:

```ini title="de.lproj/InfoPlist.strings"
NSCameraUsageDescription = "Kamera Zugriff wird benötigt für WebRTC Funktionalität";
NSMicrophoneUsageDescription = "Mikrofon Zugriff wird benötigt für WebRTC Funktionalität";
```

Lastly, make Tauri pick up these files by using the resources feature mentioned above:

```json title="src-tauri/tauri.conf.json"
{
  "bundle": {
    "resources": {
      "infoplist/**": "./"
    }
  }
}
```

## Entitlements

An entitlement is a special Apple configuration key-value pair that acts as a right or privilege that grants your app particular capabilities,
such as act as the user's default email client and using the App Sandbox feature.

Entitlements are applied when your application is signed. See the [code signing documentation] for more information.

To define the entitlements required by your application, you must create the entitlements file and configure Tauri to use it.

1. Create a `Entitlements.plist` file in the `src-tauri` folder and configure the key-value pairs you app requires:

```xml title="src-tauri/Entitlements.plist"
<?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.security.app-sandbox</key>
    <true/>
</dict>
</plist>
```

2. Configure Tauri to use the Entitlements.plist file:

```json title="tauri.conf.json" ins={4}
{
  "bundle": {
    "macOS": {
      "entitlements": "./Entitlements.plist"
    }
  }
}
```

See the [official documentation](https://developer.apple.com/documentation/bundleresources/entitlements) for more information.

## Minimum system version

By default your Tauri application supports macOS 10.13 and above. If you are using an API that requires a newer macOS system and want to enforce that requirement in your app bundle,
you can configure the [`tauri.conf.json > bundle > macOS > minimumSystemVersion`] value:

```json title="tauri.conf.json" ins={4}
{
  "bundle": {
    "macOS": {
      "minimumSystemVersion": "12.0"
    }
  }
}
```

## Including macOS frameworks

If your application requires additional macOS frameworks to run, you can list them in the [`tauri.conf.json > bundle > macOS > frameworks`] configuration.
The frameworks list can include either system or custom frameworks and dylib files.

```json title="tauri.conf.json" ins={4-8}
{
  "bundle": {
    "macOS": {
      "frameworks": [
        "CoreAudio",
        "./libs/libmsodbcsql.18.dylib",
        "./frameworks/MyApp.framework"
      ]
    }
  }
}
```

:::note

- To reference a system framework you can just use its name (without the .framework extension) instead of absolute path
- System frameworks must exist in either the `$HOME/Library/Frameworks`, `/Library/Frameworks/`, or `/Network/Library/Frameworks/`
- To reference local frameworks and dylib files you must use the complete path to the framework, relative to the `src-tauri` directory

:::

## Adding custom files

You can use the [`tauri.conf.json > bundle > macOS > files`] configuration to add custom files to your application bundle,
which maps the destination path to its source relative to the `tauri.conf.json` file.
The files are added to the `<product-name>.app/Contents` folder.

```json title="tauri.conf.json" ins={4-7}
{
  "bundle": {
    "macOS": {
      "files": {
        "embedded.provisionprofile": "./profile-name.provisionprofile",
        "SharedSupport/docs.md": "./docs/index.md"
      }
    }
  }
}
```

In the above example, the `profile-name.provisionprofile` file is copied to `<product-name>.app/Contents/embedded.provisionprofile`
and the `docs/index.md` file is copied to `<product-name>.app/Contents/SharedSupport/docs.md`.

[`tauri.conf.json > bundle > macOS > frameworks`]: /reference/config/#frameworks-1
[`tauri.conf.json > bundle > macOS > files`]: /reference/config/#files-2
[`tauri.conf.json > bundle > resources`]: /reference/config/#resources
[official Info.plist documentation]: https://developer.apple.com/documentation/bundleresources/information_property_list
[code signing documentation]: /distribute/sign/macos/
[`tauri.conf.json > bundle > macOS > minimumSystemVersion`]: /reference/config/#minimumsystemversion
[resources]: /develop/resources/
[BCP 47]: https://www.rfc-editor.org/rfc/bcp/bcp47.txt