> ## Documentation Index
> Fetch the complete documentation index at: https://ngquct-feat-ai-sql-walkthroughs.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Building

> Development builds, release builds, static libraries, DMG packaging, and CI/CD

# Building TablePro

## Development Builds

### Xcode

* `Cmd+R` to build and run
* `Cmd+B` to build only
* Scheme: **TablePro**, Destination: **My Mac**

### Command Line

```bash theme={null}
xcodebuild -project TablePro.xcodeproj -scheme TablePro -configuration Debug build -skipPackagePluginValidation
```

Build and run:

```bash theme={null}
xcodebuild -project TablePro.xcodeproj -scheme TablePro -configuration Debug build -skipPackagePluginValidation && open build/Debug/TablePro.app
```

<Note>
  `-skipPackagePluginValidation` is required. CodeEditSourceEditor bundles a SwiftLint plugin that triggers Xcode's plugin validation on CLI builds.
</Note>

Debug builds use automatic signing with an Apple Development identity. Switch the **Team** in Signing & Capabilities to your own Apple Developer account (a free account works), see [Development Setup](/development/setup). Signing matters even locally: plugin signature verification derives the required team from the running app's signature.

## Release Builds

```bash theme={null}
scripts/build-release.sh arm64      # Apple Silicon
scripts/build-release.sh x86_64     # Intel
scripts/build-release.sh both       # Both architectures
```

Output: `build/Release/TablePro-arm64.app` and `build/Release/TablePro-x86_64.app`.

The script extracts the right slice from the universal static libraries, strips the main binary, helpers, PluginKit framework, and plugin binaries, then signs each binary individually and the app bundle last with hardened runtime and entitlements. Environment variables control signing:

| Variable        | Default                   | Purpose                                          |
| --------------- | ------------------------- | ------------------------------------------------ |
| `SIGN_IDENTITY` | Maintainer's Developer ID | Codesign identity for every binary               |
| `NOTARIZE`      | `false`                   | Set `true` to notarize and staple after building |
| `APPLE_ID`      | Maintainer's Apple ID     | Account for notarization                         |

Notarization uses a `notarytool` keychain profile named `TablePro`. Create it once with `xcrun notarytool store-credentials "TablePro" --apple-id ... --team-id ... --password ...`. Do not sign or notarize by hand; the script already does it per binary, which is what Apple's guidance requires.

## Static Libraries

Static `.a` files (libmariadb, libpq, libsybdb, and others) are hosted on the `libs-v1` GitHub Release, not in git.

```bash theme={null}
scripts/download-libs.sh          # Download (skips if already present)
scripts/download-libs.sh --force  # Re-download and overwrite
```

### Publishing Libraries (Maintainers)

After rebuilding a library, publish it with `scripts/publish-libs.sh`, naming every lib you rebuilt:

```bash theme={null}
scripts/publish-libs.sh libmongoc_arm64.a libmongoc_x86_64.a libmongoc_universal.a libmongoc.a
git add Libs/checksums.sha256 && git commit -m "build: update static library checksums"
```

The script verifies all libraries you did not name against the checksums committed at HEAD, regenerates `Libs/checksums.sha256`, and uploads the archive with `--clobber`.

<Warning>
  Never run `shasum -a 256 Libs/*.a > Libs/checksums.sha256` by hand. Regenerating from a stale `Libs/` directory silently reverts other libraries; this shipped a broken libmongoc and rolled back DuckDB once.
</Warning>

iOS xcframeworks (`Libs/ios/*.xcframework`) upload to the same release:

```bash theme={null}
tar czf /tmp/tablepro-libs-ios-v1.tar.gz -C Libs/ios .
gh release upload libs-v1 /tmp/tablepro-libs-ios-v1.tar.gz --clobber --repo TableProApp/TablePro
```

## Creating a DMG

`scripts/create-dmg.sh` takes the version, the architecture (default `universal`), and the source app (default `build/Release/TablePro.app`):

```bash theme={null}
scripts/build-release.sh arm64
scripts/create-dmg.sh 0.57.0 arm64 build/Release/TablePro-arm64.app
```

Output: `build/Release/TablePro-0.57.0-arm64.dmg`.

## Clean Build

| Method  | Command                                                         |
| ------- | --------------------------------------------------------------- |
| Xcode   | `Cmd+Shift+K`                                                   |
| CLI     | `xcodebuild -project TablePro.xcodeproj -scheme TablePro clean` |
| Nuclear | `rm -rf ~/Library/Developer/Xcode/DerivedData`                  |

## CI/CD

### App Releases

`.github/workflows/build.yml`, triggered by `v*` tags (e.g. `v0.57.0`).

Jobs: SwiftLint, macOS Tests, Build ARM64, Build x86\_64, Registry Readiness. The release job needs all five, so failing tests block the release. It produces DMGs, ZIPs, and Sparkle signatures, with release notes extracted from `CHANGELOG.md`.

### Plugin Releases

`.github/workflows/build-plugin.yml`, triggered by `plugin-*-v*` tags (e.g. `plugin-oracle-v1.0.0`) or by `workflow_dispatch`. The dispatch input takes comma-separated `tag:pluginKitVersion` pairs, e.g. `plugin-mongodb-v1.0.25:13`. Omit `:pluginKitVersion` and the workflow reads `currentPluginKitVersion` from `PluginManager.swift`.

After a PluginKit ABI bump, re-release every registry plugin in one parallel matrix run:

```bash theme={null}
scripts/release-all-plugins.sh <pluginKitVersion>
```

See [Plugin Registry](/development/plugin-registry) for how published binaries reach users.

<Warning>
  Pushing more than 3 tags in one push creates no push events at all, so zero workflows fire. Push plugin tags one at a time, or use `workflow_dispatch`.
</Warning>
