|
| 1 | +--- |
| 2 | +name: macios-binding-creator |
| 3 | +description: > |
| 4 | + Create C# bindings for Apple frameworks in dotnet/macios. USE FOR: binding new |
| 5 | + APIs, implementing .todo file entries, creating Xcode SDK bindings, binding |
| 6 | + AVFoundation/UIKit/AppKit or any Apple framework, "bind this framework", |
| 7 | + "implement these APIs". DO NOT USE FOR: Xcode beta version bumps (use |
| 8 | + macios-xcode-beta-update skill), CI failure investigation (use |
| 9 | + macios-ci-failure-inspector skill). |
| 10 | +--- |
| 11 | + |
| 12 | +# macios Binding Creator |
| 13 | + |
| 14 | +Create C# bindings for Apple platform APIs in the dotnet/macios repository. This skill encodes the end-to-end workflow: from reading `.todo` files through implementation, building, and validating with xtro, cecil, and introspection tests on all platforms. |
| 15 | + |
| 16 | +## When to Use This Skill |
| 17 | + |
| 18 | +Use this skill when: |
| 19 | +- Asked to bind a new Apple framework or add missing API bindings |
| 20 | +- Implementing entries from `.todo` files in `tests/xtro-sharpie/api-annotations-dotnet/` |
| 21 | +- Creating bindings for a new Xcode SDK release |
| 22 | +- Adding new types, properties, methods, or enum values to existing framework bindings |
| 23 | +- Asked to "bind", "implement", or "add bindings for" any Apple framework |
| 24 | + |
| 25 | +## Prerequisites |
| 26 | + |
| 27 | +- Repository checked out and configured (`./configure` already run) |
| 28 | +- Xcode installed at the expected `XCODE_DEVELOPER_ROOT` path |
| 29 | +- A successful `make world` or `make all && make install` already completed |
| 30 | + |
| 31 | +## Process |
| 32 | + |
| 33 | +### Step 1: Understand What to Bind |
| 34 | + |
| 35 | +Check the `.todo` files to see what APIs are missing: |
| 36 | + |
| 37 | +```bash |
| 38 | +ls tests/xtro-sharpie/api-annotations-dotnet/*-{FrameworkName}.todo |
| 39 | +cat tests/xtro-sharpie/api-annotations-dotnet/iOS-{FrameworkName}.todo |
| 40 | +``` |
| 41 | + |
| 42 | +Each `.todo` file lists missing APIs per platform (iOS, tvOS, macOS, MacCatalyst). The format is: |
| 43 | +``` |
| 44 | +!missing-selector! ClassName::methodName: not bound |
| 45 | +!missing-type! ClassName not bound |
| 46 | +!missing-field! ClassName FieldName not bound |
| 47 | +!missing-enum-value! EnumName::ValueName not bound |
| 48 | +``` |
| 49 | + |
| 50 | +> ❌ **NEVER** bind APIs that aren't in the `.todo` files unless explicitly asked. The `.todo` files are the source of truth for what's missing. |
| 51 | +
|
| 52 | +### Step 2: Generate Reference Bindings |
| 53 | + |
| 54 | +Run the xtro generator to produce reference C# bindings from the SDK headers: |
| 55 | + |
| 56 | +```bash |
| 57 | +make -C tests/xtro-sharpie gen-all |
| 58 | +``` |
| 59 | + |
| 60 | +This creates generated `.cs` files you can search to find the correct C# signatures, attributes, and patterns for the APIs you need to bind. Use these as reference — don't copy them verbatim. |
| 61 | + |
| 62 | +### Step 3: Research the Native API |
| 63 | + |
| 64 | +Before implementing, understand the native API: |
| 65 | +- Search the generated reference bindings for the correct Objective-C selectors |
| 66 | +- Read Apple header files when available (under `$XCODE_DEVELOPER_ROOT`) |
| 67 | +- Check existing bindings in `src/frameworkname.cs` for patterns used in the same framework |
| 68 | + |
| 69 | +### Step 4: Implement Bindings |
| 70 | + |
| 71 | +Bindings go in these locations: |
| 72 | +- **`src/frameworkname.cs`** — API definitions (interfaces with `[Export]` attributes) |
| 73 | +- **`src/FrameworkName/`** — Manual code (partial classes, enums, P/Invokes, extensions) |
| 74 | +- **`src/frameworks.sources`** — Maps frameworks to source files (update if adding new files) |
| 75 | + |
| 76 | +Key binding patterns: |
| 77 | + |
| 78 | +```csharp |
| 79 | +// New property on existing class |
| 80 | +[Export ("allowsCaptureOfClearKeyVideo")] |
| 81 | +bool AllowsCaptureOfClearKeyVideo { get; set; } |
| 82 | + |
| 83 | +// New method on existing class |
| 84 | +[Export ("setCaptionPreviewProfileId:")] |
| 85 | +void SetCaptionPreviewProfileId ([NullAllowed] string profileId); |
| 86 | + |
| 87 | +// New notification field |
| 88 | +[Field ("AVPlayerInterstitialEventMonitorScheduleRequestedNotification")] |
| 89 | +[Notification] |
| 90 | +NSString ScheduleRequestedNotification { get; } |
| 91 | +``` |
| 92 | + |
| 93 | +> ❌ **NEVER** forget platform availability attributes. Every new API must have `[iOS]`, `[Mac]`, `[TV]`, `[MacCatalyst]`, and/or `[No*]` attributes matching the `.todo` file platforms where the API appears. |
| 94 | +
|
| 95 | +> ❌ **NEVER** use `string.Empty` — use `""`. Never use `Array.Empty<T>()` — use `[]`. |
| 96 | +
|
| 97 | +> ⚠️ Place a space before parentheses and brackets: `Foo ()`, `Bar (1, 2)`, `myarray [0]`. |
| 98 | +
|
| 99 | +> ⚠️ For in depth binding patterns and conventions See [references/binding-patterns.md](references/binding-patterns.md) |
| 100 | +
|
| 101 | +### Step 5: Build |
| 102 | + |
| 103 | +```bash |
| 104 | +make -C src build |
| 105 | +``` |
| 106 | + |
| 107 | +Fix any compilation errors before proceeding. Builds can take up to 60 minutes — do not timeout early. |
| 108 | + |
| 109 | +### Step 6: Validate with Tests |
| 110 | + |
| 111 | +Run all three test suites. **Run them sequentially, not in parallel.** |
| 112 | + |
| 113 | +#### 6a. Xtro Tests |
| 114 | + |
| 115 | +```bash |
| 116 | +make -C tests/xtro-sharpie run-ios |
| 117 | +make -C tests/xtro-sharpie run-tvos |
| 118 | +make -C tests/xtro-sharpie run-macos |
| 119 | +make -C tests/xtro-sharpie run-maccatalyst |
| 120 | +``` |
| 121 | + |
| 122 | +Verify all `.todo` entries for the bound framework are resolved. If any remain, they need binding or explicit `.ignore` entries with justification. |
| 123 | + |
| 124 | +#### 6b. Cecil Tests |
| 125 | + |
| 126 | +```bash |
| 127 | +make -C tests/cecil-tests run-tests |
| 128 | +``` |
| 129 | + |
| 130 | +#### 6c. Introspection Tests (All Platforms) |
| 131 | + |
| 132 | +**IMPORTANT:** Clean shared obj directories before each platform to avoid NETSDK1005 errors: |
| 133 | + |
| 134 | +```bash |
| 135 | +# iOS |
| 136 | +rm -rf tests/common/Touch.Unit/Touch.Client/dotnet/obj tests/common/MonoTouch.Dialog/obj |
| 137 | +make -C tests/introspection/dotnet clean-ios build-ios run-ios |
| 138 | + |
| 139 | +# tvOS |
| 140 | +rm -rf tests/common/Touch.Unit/Touch.Client/dotnet/obj tests/common/MonoTouch.Dialog/obj |
| 141 | +make -C tests/introspection/dotnet clean-tvos build-tvos run-tvos |
| 142 | + |
| 143 | +# macOS (use run-bare for direct execution with captured output) |
| 144 | +rm -rf tests/common/Touch.Unit/Touch.Client/dotnet/obj tests/common/MonoTouch.Dialog/obj |
| 145 | +make -C tests/introspection/dotnet clean-macOS build-macOS run-bare-macOS |
| 146 | + |
| 147 | +# MacCatalyst (use run-bare for direct execution with captured output) |
| 148 | +rm -rf tests/common/Touch.Unit/Touch.Client/dotnet/obj tests/common/MonoTouch.Dialog/obj |
| 149 | +make -C tests/introspection/dotnet clean-MacCatalyst build-MacCatalyst run-bare-MacCatalyst |
| 150 | +``` |
| 151 | + |
| 152 | +> ⚠️ **macOS/MacCatalyst:** Use `make run-bare` (not `make run`) — `make run` launches the app without waiting or capturing stdout. `run-bare` runs the executable directly to capture test output. |
| 153 | +
|
| 154 | +> ⚠️ **iOS/tvOS:** Use `make run` (not `make run-bare`) — these require simulator infrastructure that `run-bare` doesn't provide. |
| 155 | +
|
| 156 | +Look for this pattern in test output to confirm results: |
| 157 | +``` |
| 158 | +Tests run: X Passed: X Inconclusive: X Failed: X Ignored: X |
| 159 | +``` |
| 160 | + |
| 161 | +### Step 7: Handle Test Failures |
| 162 | + |
| 163 | +If introspection tests fail for newly bound types: |
| 164 | +- Check if the type crashes on simulator (common for hardware-dependent APIs) |
| 165 | +- Add exclusions in the platform-specific `ApiCtorInitTest.cs` files if needed |
| 166 | +- Types that crash on init, dispose, or toString need specific exclusion entries |
| 167 | + |
| 168 | +If xtro still shows unresolved entries: |
| 169 | +- Some APIs may be platform-specific (only available on device, not simulator) |
| 170 | +- Create `.ignore` entries with comments explaining why they can't be bound |
| 171 | +- Or create remaining `.todo` entries for known limitations |
| 172 | + |
| 173 | +## Stop Signals |
| 174 | + |
| 175 | +- Stop investigating test failures after identifying the root cause. Don't trace full call stacks. |
| 176 | +- If a type crashes on simulator, add an exclusion and move on — don't try to fix simulator issues. |
| 177 | +- Don't bind APIs beyond what's listed in the `.todo` files unless explicitly asked. |
| 178 | +- Report results per platform after all tests pass. Don't re-run passing tests. |
| 179 | + |
| 180 | +## Output Format |
| 181 | + |
| 182 | +When reporting results, use this structure: |
| 183 | + |
| 184 | +1. **APIs bound** — table of types/members added with their platforms |
| 185 | +2. **Files changed** — list of modified files |
| 186 | +3. **Test results** — per-platform pass/fail for xtro, cecil, and introspection |
| 187 | +4. **Remaining items** — any `.todo` entries intentionally left unbound, with reasons |
| 188 | + |
| 189 | +## References |
| 190 | + |
| 191 | +- **Binding patterns and conventions**: See [references/binding-patterns.md](references/binding-patterns.md) |
| 192 | +- **Test commands and troubleshooting**: See [references/test-workflow.md](references/test-workflow.md) |
0 commit comments