Some checks failed
Build / Build openSUSE (leap:15.6) (push) Has been cancelled
Build / Build openSUSE (leap:16.0) (push) Has been cancelled
Build / Build openSUSE (tumbleweed) (push) Has been cancelled
Build / Build Fedora (42) (push) Has been cancelled
Build / Build Fedora (43) (push) Has been cancelled
Build / Build Fedora (44) (push) Has been cancelled
Build / Build OpenMandriva (cooker) (push) Has been cancelled
Build / Build Mageia (9) (push) Has been cancelled
Build / Build Debian (bookworm) (push) Has been cancelled
Build / Build Debian (forky) (push) Has been cancelled
Build / Build Debian (trixie) (push) Has been cancelled
Build / Build Ubuntu (noble) (push) Has been cancelled
Build / Build Ubuntu (questing) (push) Has been cancelled
Build / Build Ubuntu (resolute) (push) Has been cancelled
Build / Upload Ubuntu PPA (noble) (push) Has been cancelled
Build / Upload Ubuntu PPA (questing) (push) Has been cancelled
Build / Upload Ubuntu PPA (resolute) (push) Has been cancelled
Build / Build FreeBSD (push) Has been cancelled
Build / Build OpenBSD (push) Has been cancelled
Build / Build macOS Public (release, macos-15) (push) Has been cancelled
Build / Build macOS Public (release, macos-15-intel) (push) Has been cancelled
Build / Build macOS Private (release, macos-arm64) (push) Has been cancelled
Build / Build Windows MinGW (i686, debug) (push) Has been cancelled
Build / Build Windows MinGW (i686, release) (push) Has been cancelled
Build / Build Windows MinGW (x86_64, debug) (push) Has been cancelled
Build / Build Windows MinGW (x86_64, release) (push) Has been cancelled
Build / Build Windows MSVC (arm64, debug, arm64 debug, windows-11-arm) (push) Has been cancelled
Build / Build Windows MSVC (arm64, release, arm64 release, windows-11-arm) (push) Has been cancelled
Build / Build Windows MSVC (x86, debug, x86 debug, windows-2022) (push) Has been cancelled
Build / Build Windows MSVC (x86, release, x86 release, windows-2022) (push) Has been cancelled
Build / Build Windows MSVC (x86_64, debug, x86_64 debug, windows-2022) (push) Has been cancelled
Build / Build Windows MSVC (x86_64, release, x86_64 release, windows-2022) (push) Has been cancelled
Build / Upload (push) Has been cancelled
Build / Attach to release (push) Has been cancelled
This commit enhances the `README_MAS.md` by providing detailed information on the differences between arm64-only, universal, and x86_64-only app architectures for Mac App Store uploads. It includes recommendations for achieving broad compatibility and clarifies the limitations of submitting multiple builds. This update aims to assist developers in making informed decisions regarding app architecture for their submissions.
422 lines
15 KiB
Markdown
422 lines
15 KiB
Markdown
# Mac App Store (MAS) submission guide (manual steps)
|
||
|
||
This repo supports a **Mac App Store build mode** (`BUILD_FOR_MAC_APP_STORE=ON`) and includes scripts to build a signed upload `.pkg`.
|
||
|
||
If you’re blocked because `security find-identity` only shows **Developer ID** and not **Apple Distribution / Installer**, follow the steps below.
|
||
|
||
---
|
||
|
||
## Open Keychain Access (macOS “hidden” Utilities)
|
||
|
||
Any of these work:
|
||
|
||
- **Spotlight**: press `⌘ + Space` → type **Keychain Access** → Enter
|
||
- **Finder**: Applications → Utilities → **Keychain Access**
|
||
- **Terminal**:
|
||
|
||
```bash
|
||
open -a "Keychain Access"
|
||
```
|
||
|
||
---
|
||
|
||
## The core issue: certificate exists but is not a usable identity
|
||
|
||
If you see certificates like:
|
||
|
||
- `Apple Distribution: ...`
|
||
- `3rd Party Mac Developer Installer: ...`
|
||
|
||
but `security find-identity` does **not** list them, then the certificate is present but **the private key is missing** (or not paired / in the wrong keychain).
|
||
|
||
You can confirm with:
|
||
|
||
```bash
|
||
./build_tools/macos/check_signing_identities.sh
|
||
```
|
||
|
||
---
|
||
|
||
## Step 1 — Create the private keys on this Mac (CSR)
|
||
|
||
1. Open **Keychain Access**
|
||
2. Menu: **Keychain Access → Certificate Assistant → Request a Certificate From a Certificate Authority…**
|
||
3. Fill:
|
||
- **User Email Address**: your Apple ID email
|
||
- **Common Name**: e.g. `Dry Ark LLC` (any label is fine)
|
||
- **CA Email Address**: leave blank
|
||
- Select: **Saved to disk**
|
||
4. Save the CSR (`.certSigningRequest`) somewhere safe
|
||
|
||
This CSR step is what creates the **private key** locally in your login keychain.
|
||
|
||
---
|
||
|
||
## Step 2 — Create + download the certificates (Apple Developer portal)
|
||
|
||
In Apple Developer → **Certificates, Identifiers & Profiles** → **Certificates** → **+**:
|
||
|
||
- Create **Apple Distribution** (use the CSR you just made)
|
||
- Create **Mac Installer Distribution** (or “3rd Party Mac Developer Installer”, wording varies) (use a CSR)
|
||
|
||
Download the resulting `.cer` files.
|
||
|
||
---
|
||
|
||
## Step 3 — Install certificates into your login keychain
|
||
|
||
Double-click each downloaded `.cer` to install it.
|
||
|
||
Then in **Keychain Access → login → My Certificates**:
|
||
|
||
- Find **Apple Distribution: ...** and **expand it**
|
||
- You must see a **private key** under it.
|
||
- Find **... Installer ...** and expand it
|
||
- You must see a **private key** under it.
|
||
|
||
If there’s no private key under the certificate, it will not be usable for signing on this Mac.
|
||
|
||
---
|
||
|
||
## Step 4 — Verify identities from the CLI
|
||
|
||
### Common failure: errSecInternalComponent / chain-to-root warnings
|
||
|
||
If you see errors like:
|
||
|
||
- `Warning: unable to build chain to self-signed root for signer "Apple Distribution: ..."`
|
||
- `errSecInternalComponent`
|
||
|
||
This is almost always a **keychain search list / trust chain** issue.
|
||
|
||
#### Important: do NOT “Always Trust” your Apple Distribution / Installer certs
|
||
|
||
Setting your leaf signing certificates (e.g. **Apple Distribution** / **3rd Party Mac Developer Installer**) to **Always Trust** can make things worse by overriding the normal trust chain and causing codesign to fail chain building.
|
||
|
||
If you changed trust settings:
|
||
|
||
- In **Keychain Access → login → My Certificates**
|
||
- open the cert → **Trust**
|
||
- set **“When using this certificate” = “Use System Defaults”**
|
||
|
||
Fix (safe, common): ensure the System keychains are included in the user search list:
|
||
|
||
```bash
|
||
security list-keychains -d user
|
||
security list-keychains -d user -s "$HOME/Library/Keychains/login.keychain-db" "/Library/Keychains/System.keychain" "/System/Library/Keychains/SystemRootCertificates.keychain"
|
||
```
|
||
|
||
Then re-run the build/sign script.
|
||
|
||
#### Install the correct Apple intermediate certificates (WWDR)
|
||
|
||
If the System keychains are already in the search list and you still get chain errors, you’re likely missing an Apple intermediate (commonly **WWDR**).
|
||
|
||
Download the current Apple WWDR intermediate certificate(s) from Apple’s official Certificate Authority page:
|
||
|
||
- `https://www.apple.com/certificateauthority/`
|
||
|
||
Then import into the **System** keychain (recommended):
|
||
|
||
- Keychain Access → **System** keychain → File → **Import Items…** → select the downloaded `.cer`
|
||
|
||
Or via CLI (requires admin):
|
||
|
||
```bash
|
||
sudo security add-certificates -k /Library/Keychains/System.keychain "/path/to/WWDR.cer"
|
||
```
|
||
|
||
Verify it’s visible:
|
||
|
||
```bash
|
||
security find-certificate -a -c "Apple Worldwide Developer Relations" /Library/Keychains/System.keychain | head -n 10
|
||
```
|
||
|
||
If needed, you can also verify the chain for your distribution cert:
|
||
|
||
```bash
|
||
security verify-cert -c "Apple Distribution: Dry Ark LLC (7628766FL2)" 2>&1 | head -n 80
|
||
```
|
||
|
||
```bash
|
||
security find-identity -p codesigning -v
|
||
security find-identity -p basic -v
|
||
./build_tools/macos/check_signing_identities.sh
|
||
```
|
||
|
||
Expected:
|
||
|
||
- `Apple Distribution: ...` shows up under **codesigning**
|
||
- `... Installer ...` shows up as an **installer identity** (used to sign upload `.pkg`)
|
||
|
||
---
|
||
|
||
## Step 5 — Create + install the provisioning profile (Mac App Store)
|
||
|
||
In Apple Developer → **Profiles** → **+**:
|
||
|
||
- Platform: **macOS**
|
||
- Type: **Mac App Store**
|
||
- App ID: `com.dryark.strawberry` (or your own bundle id)
|
||
- Select the **Apple Distribution** certificate
|
||
- Generate + Download
|
||
|
||
### Where the `.provisionprofile` ends up (newer Xcode/macOS)
|
||
|
||
Recent Xcode versions store “downloaded manual profiles” under:
|
||
|
||
- `~/Library/Developer/Xcode/UserData/Provisioning Profiles/`
|
||
|
||
Older tooling sometimes used:
|
||
|
||
- `~/Library/MobileDevice/Provisioning Profiles/`
|
||
|
||
This repo’s MAS build script does **not** require the profile to be in a specific folder — you can pass the path directly.
|
||
|
||
To locate and pick the right profile, use:
|
||
|
||
```bash
|
||
./build_tools/macos/find_mas_provisioning_profile.sh --bundle-id com.dryark.strawberry
|
||
```
|
||
|
||
### (Optional) Copy to the legacy folder
|
||
|
||
If some other tools expect the legacy folder, you can copy it there:
|
||
|
||
```bash
|
||
mkdir -p "$HOME/Library/MobileDevice/Provisioning Profiles"
|
||
cp -f "/path/to/profile.provisionprofile" "$HOME/Library/MobileDevice/Provisioning Profiles/"
|
||
```
|
||
|
||
---
|
||
|
||
## Step 6 — Build the signed upload package (.pkg)
|
||
|
||
This repo provides:
|
||
|
||
- `build_tools/macos/build_mas_pkg.sh` (build → deploy → embed profile → sign → productbuild)
|
||
|
||
Example:
|
||
|
||
```bash
|
||
./build_tools/macos/build_mas_pkg.sh --run --release --clean \
|
||
--codesign-identity "Apple Distribution: Dry Ark LLC (7628766FL2)" \
|
||
--installer-identity "3rd Party Mac Developer Installer: Dry Ark LLC (7628766FL2)" \
|
||
--provisionprofile "$HOME/Library/MobileDevice/Provisioning Profiles/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX.provisionprofile"
|
||
```
|
||
|
||
Outputs:
|
||
|
||
- `cmake-build-macos-release-mas/strawberry.app`
|
||
- `cmake-build-macos-release-mas/strawberry-mas.pkg`
|
||
|
||
---
|
||
|
||
## Architecture note — arm64 vs universal (arm64+x86_64)
|
||
|
||
For Mac App Store uploads, your `.pkg` can contain either:
|
||
|
||
- **arm64-only** app (Apple Silicon only), or
|
||
- **universal** app (arm64 + x86_64), or
|
||
- **x86_64-only** app (runs on Apple Silicon under Rosetta 2, but native Intel only otherwise)
|
||
|
||
Apple does **not** require universal binaries for review. **arm64-only is allowed**, but:
|
||
|
||
- Intel Macs **cannot** run an arm64-only app.
|
||
- If you ship arm64-only, App Store Connect will effectively make the app available only to Apple Silicon Macs (and your listing will reflect that).
|
||
|
||
### Recommendation
|
||
|
||
- If you want the broadest compatibility, aim for a **universal build**.
|
||
- If you’re okay supporting only Apple Silicon Macs, arm64-only is the simplest path.
|
||
|
||
### Can I upload two different `.pkg`s (one arm64, one x86_64)?
|
||
|
||
Not in the way you want.
|
||
|
||
- In App Store Connect you can upload multiple builds over time, but for any given version/submission you ultimately pick **one build** to submit.
|
||
- Apple will not “merge” two separate uploads (arm64-only + x86_64-only) into one app for customers.
|
||
|
||
If you want both Apple Silicon and Intel supported **natively**, you need to produce a **single universal** app bundle and package that into **one** `.pkg`.
|
||
|
||
If you don’t want to deal with universal yet, your practical choices are:
|
||
|
||
- **arm64-only**: Apple Silicon only.
|
||
- **x86_64-only**: runs on Intel natively, and on Apple Silicon under **Rosetta 2** (slower, but widely compatible).
|
||
|
||
### Practical reality for this repo
|
||
|
||
This project depends on large native dependency stacks (Qt, GStreamer, plugins). If you build those via Homebrew, you typically end up with **single-architecture** libraries (arm64 under `/opt/homebrew`, x86_64 under `/usr/local`).
|
||
|
||
A true universal app requires **all bundled native code** (your executable *and* all `.dylib`/plugins/frameworks you ship) to be universal as well.
|
||
|
||
If you decide you want universal:
|
||
|
||
- You’ll need a universal build of **Qt** and **GStreamer** (and all bundled plugins), or
|
||
- Build arm64 and x86_64 bundles separately and combine *matching* binaries where possible (advanced; easy to break signing / plugin loading).
|
||
|
||
---
|
||
|
||
## Troubleshooting — `productbuild` fails with CSSM `-60008` (authorization)
|
||
|
||
If you see something like:
|
||
|
||
- `SignData failed ... CSSM Exception: -60008 Unable to obtain authorization for this operation`
|
||
|
||
That means the **Installer** certificate is present, but macOS is not allowing `productbuild` to use the **private key** without additional authorization.
|
||
|
||
### Fix option A (recommended): set key partition list (CLI)
|
||
|
||
This is the standard “allow Apple tools to sign without GUI prompts” fix:
|
||
|
||
```bash
|
||
security unlock-keychain "$HOME/Library/Keychains/login.keychain-db"
|
||
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "<login-keychain-password>" "$HOME/Library/Keychains/login.keychain-db"
|
||
```
|
||
|
||
Note: if your password contains characters like `!` or `$` and you paste it into a command in `zsh`,
|
||
the shell can modify it (history/variable expansion) and `security ... -k` may claim it’s “incorrect”.
|
||
Use **single quotes** (or the env var path shown below) to avoid this, e.g.:
|
||
|
||
```bash
|
||
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k 'p@ssw0rd!$' "$HOME/Library/Keychains/login.keychain-db"
|
||
```
|
||
|
||
Then rerun:
|
||
|
||
```bash
|
||
./build_tools/macos/build_mas_pkg.sh --run ...
|
||
```
|
||
|
||
This repo’s script also supports:
|
||
|
||
- `--keychain-password <pw>` (or env var `STRAWBERRY_KEYCHAIN_PASSWORD`)
|
||
|
||
### Fix option B: Keychain Access UI (one-time)
|
||
|
||
1. Open **Keychain Access**
|
||
2. Select **login** keychain → **My Certificates**
|
||
3. Find your installer cert (e.g. `3rd Party Mac Developer Installer: ...`) and **expand it**
|
||
4. Select the **private key** under it
|
||
5. **Get Info → Access Control**
|
||
- Add `/usr/bin/productbuild` (and optionally `/usr/bin/pkgbuild`) to the allowed apps
|
||
|
||
---
|
||
|
||
## Step 7 — Upload + submit for review
|
||
|
||
### 7.1 Install Apple “Transporter” (the upload tool)
|
||
|
||
Apple requires Mac App Store submissions to be uploaded using **Transporter** (a macOS app published by Apple).
|
||
|
||
Where to get it:
|
||
|
||
- Install **Transporter** from the **Mac App Store** (search for “Transporter”).
|
||
- App Store listing name is typically **“Transporter”** by Apple.
|
||
|
||
### 7.2 Upload the `.pkg` with Transporter
|
||
|
||
1. Open **Transporter**
|
||
2. Sign in with the Apple ID that has access to **App Store Connect**
|
||
3. Click **Add App** (or **+**) and choose your signed upload package:
|
||
- `cmake-build-macos-release-mas/strawberry-mas.pkg` (or your custom `--pkg-out` path)
|
||
4. Click **Deliver**
|
||
5. Wait for upload + server-side validation to complete
|
||
|
||
Notes:
|
||
|
||
- Uploading can take a while depending on your connection.
|
||
- If Transporter reports an error, the message usually includes the exact App Store Connect requirement you violated (bundle id mismatch, missing entitlements, invalid signature, etc.).
|
||
|
||
### 7.3 Submit the build in App Store Connect
|
||
|
||
1. Open **App Store Connect** in your browser and go to **My Apps**
|
||
2. Select your app, then go to the **macOS App** platform section
|
||
3. Find your uploaded build under **TestFlight** or **Prepare for Submission** (Apple’s UI wording changes over time)
|
||
4. Wait for Apple to finish “Processing” the build
|
||
5. Select the build for your version, complete required metadata, then click **Submit for Review**
|
||
|
||
### (Optional) CLI upload (advanced): `iTMSTransporter`
|
||
|
||
If you prefer uploading from the command line, Apple’s underlying uploader is **iTMSTransporter**.
|
||
On most systems it’s available via Xcode command line tools as:
|
||
|
||
```bash
|
||
xcrun iTMSTransporter -help
|
||
```
|
||
|
||
CLI upload requires additional credentials (App Store Connect API key or Apple ID auth) and is easier to get wrong than the Transporter GUI.
|
||
For most folks, **Transporter.app is the recommended path**.
|
||
|
||
---
|
||
|
||
## Creating a universal Mac App Store upload using two Macs (arm64 + x86_64)
|
||
|
||
If you have both an Apple Silicon Mac and an Intel Mac, the most reliable way to ship a universal app for this repo is:
|
||
|
||
1. Build + deploy the **unsigned** MAS app bundle on each machine (arm64 and x86_64).
|
||
2. Copy both `.app` bundles to the machine that has your signing keys.
|
||
3. Merge them with `lipo` and then **sign + package** once, producing a single universal `.pkg`.
|
||
|
||
### Step A — Build + deploy (arm64 machine)
|
||
|
||
On your Apple Silicon Mac:
|
||
|
||
```bash
|
||
./build_tools/macos/build_app.sh --release --clean --mas --deploy --build-dir ./cmake-build-macos-release-mas-arm64
|
||
```
|
||
|
||
This produces (unsigned):
|
||
|
||
- `cmake-build-macos-release-mas-arm64/strawberry.app`
|
||
|
||
### Step B — Build + deploy (x86_64 machine)
|
||
|
||
On your Intel Mac:
|
||
|
||
```bash
|
||
./build_tools/macos/build_app.sh --release --clean --mas --deploy --build-dir ./cmake-build-macos-release-mas-x86_64
|
||
```
|
||
|
||
This produces (unsigned):
|
||
|
||
- `cmake-build-macos-release-mas-x86_64/strawberry.app`
|
||
|
||
### Step C — Copy both app bundles to one “packaging” machine
|
||
|
||
Pick the Mac that has your **Apple Distribution** and **Installer** identities (private keys) installed.
|
||
Copy both `.app` bundles onto that Mac, for example:
|
||
|
||
- `/path/to/inputs/strawberry-arm64.app`
|
||
- `/path/to/inputs/strawberry-x86_64.app`
|
||
|
||
Tip: `rsync` works well for app bundles:
|
||
|
||
```bash
|
||
rsync -a "/path/to/arm64/strawberry.app" "/path/to/inputs/strawberry-arm64.app"
|
||
rsync -a "/path/to/x86_64/strawberry.app" "/path/to/inputs/strawberry-x86_64.app"
|
||
```
|
||
|
||
### Step D — Merge + sign + build the universal `.pkg`
|
||
|
||
On the packaging machine:
|
||
|
||
```bash
|
||
./build_tools/macos/build_mas_universal_pkg.sh --run \
|
||
--arm-app "/path/to/inputs/strawberry-arm64.app" \
|
||
--x86-app "/path/to/inputs/strawberry-x86_64.app" \
|
||
--codesign-identity "Apple Distribution: Your Name (TEAMID)" \
|
||
--installer-identity "3rd Party Mac Developer Installer: Your Name (TEAMID)" \
|
||
--provisionprofile "/path/to/profile.provisionprofile"
|
||
```
|
||
|
||
Outputs:
|
||
|
||
- `cmake-build-macos-release-mas-universal/strawberry.app` (universal)
|
||
- `cmake-build-macos-release-mas-universal/strawberry-mas-universal.pkg`
|
||
|
||
### Important constraints (don’t skip)
|
||
|
||
- The two input apps must be built from the **same commit** with the **same enabled features** so the app bundle layouts match.
|
||
- Do **not** sign the per-arch apps first; `lipo` invalidates signatures. Sign **only after** merging.
|