> ## Documentation Index
> Fetch the complete documentation index at: https://ngquct-docs-fix-500-query-results.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Building

> Debug builds, the plugin compile check, clean builds, and what CI runs on a pull request

Xcode and `xcodebuild` write the built app to different directories. `Cmd+R` leaves it in
DerivedData; the command line leaves it in `build/Debug/` inside the repo. Both need the
**TablePro** scheme and the **My Mac** destination.

<Note>
  `TablePro.xcodeproj` is generated from `project.yml` by `scripts/generate-project.sh` and is not in
  git. Run it after cloning, after editing `project.yml` or anything in `Configs/`, and after adding,
  moving, or deleting a source file. See [Development Setup](/development/setup).
</Note>

## Debug builds

In Xcode, `Cmd+B` builds and `Cmd+R` builds and runs. From the command line:

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

Build and launch in one line:

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

`-skipPackagePluginValidation` belongs on every `xcodebuild` invocation.
`scripts/build-release.sh`, `scripts/build-plugin.sh`, `scripts/check-pluginkit-abi.sh` and every
CI job that shells out to `xcodebuild` pass it.

Debug builds sign with an Apple Development identity resolved from `TABLEPRO_DEVELOPMENT_TEAM`, so
signing matters even locally: a plugin in the user plugins directory has to carry the same team as
the running app, and the app derives the required team from its own signature. Set the variable in
`Configs/Secrets.xcconfig` as [Development Setup](/development/setup) describes.

## Compiling every plugin

An app build compiles only the plugin bundles the app embeds, which leaves every registry-only
driver uncompiled. The `AllPlugins` aggregate target covers all of them in one pass:

```bash theme={null}
xcodebuild build -project TablePro.xcodeproj -scheme AllPlugins -destination 'platform=macOS' -skipPackagePluginValidation CODE_SIGNING_ALLOWED=NO
```

Run it after changing anything under `Plugins/TableProPluginKit/`, which every plugin links. To
build one signed, packaged bundle instead, use `scripts/build-plugin.sh <PluginTarget>`; the target
names are the keys under `targets:` in `project.yml`, such as `OracleDriver` or
`SurrealDBDriverPlugin`.

## Clean builds

| Reach for                                                       | When                                                            |
| --------------------------------------------------------------- | --------------------------------------------------------------- |
| `Cmd+Shift+K` in Xcode                                          | The usual case                                                  |
| `xcodebuild -project TablePro.xcodeproj -scheme TablePro clean` | Same, from a terminal                                           |
| `rm -rf ~/Library/Developer/Xcode/DerivedData`                  | Package resolution is stuck or a stale module keeps reappearing |

The last one deletes the caches for every project on the machine, and the next build starts from
nothing.

## What a pull request has to pass

`.github/workflows/macos-tests.yml` starts on every pull request, on Xcode 26.4.1. Its first job
decides whether the macOS suites run at all and skips them when nothing relevant changed, so the
workflow still reports a result on a docs-only change.

| Job                     | What it does                                                                                |
| ----------------------- | ------------------------------------------------------------------------------------------- |
| Detect relevant changes | Decides whether the macOS suites run                                                        |
| Package Tests           | `swift test` for TableProCore and CodeEditTextView                                          |
| Build for testing       | Builds `AllPlugins`, `dlopen`s each built bundle, then builds the app and both test bundles |
| Unit tests              | `TableProTests` against the prebuilt products                                               |
| UI tests                | `TableProUITests`, split across three shards                                                |
| macOS Tests Gate        | Fails unless every other job reported success or skipped                                    |

A plugin that builds and signs can still fail to load, which is why the load step is separate:
"Bundle failed to load executable" has shipped twice.

`.github/workflows/repo-hygiene.yml` runs beside it on Ubuntu in under a minute. It runs
`actionlint` over every workflow, which shells out to `shellcheck` for each inline `run:` block;
`shellcheck` at warning severity over every script; the plugin manifest check; and the
shared-contract drift gates in `scripts/audit-refactor-health.sh`.

Lint runs in the release workflow rather than this one. Run `swiftlint lint --strict` yourself
before pushing; see [Code Style](/development/code-style).

## Related

Release builds, notarization, DMG packaging and the tag that publishes them are on
[Releasing](/development/releasing). Publishing a driver plugin is on
[Plugin Registry](/development/plugin-registry).
