Skip to content

Commit 0eb08a7

Browse files
dalexsotoCopilot
andauthored
[skills] Update macios-binding-creator skill (#24962)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent e5b2061 commit 0eb08a7

File tree

3 files changed

+361
-2
lines changed

3 files changed

+361
-2
lines changed

.agents/skills/macios-binding-creator/SKILL.md

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,21 @@ Before implementing, understand the native API:
6868

6969
### Step 4: Implement Bindings
7070

71+
#### Determine the Correct Availability Version
72+
73+
Before writing any bindings, determine the SDK version you're targeting:
74+
75+
```bash
76+
# Check the current SDK versions
77+
grep -E 'public const string (iOS|TVOS|OSX|MacCatalyst) ' tools/common/SdkVersions.cs
78+
# Or from Make.versions
79+
grep '_NUGET_OS_VERSION=' Make.versions
80+
```
81+
82+
Use the version from `SdkVersions.cs` (e.g., `26.2`) for all availability attributes. If the user specifies a different version (e.g., binding a beta branch at `26.4`), use that instead. **Ask the user if you're unsure which version to use.**
83+
84+
#### File Locations
85+
7186
Bindings go in these locations:
7287
- **`src/frameworkname.cs`** — API definitions (interfaces with `[Export]` attributes)
7388
- **`src/FrameworkName/`** — Manual code (partial classes, enums, P/Invokes, extensions)
@@ -90,10 +105,15 @@ void SetCaptionPreviewProfileId ([NullAllowed] string profileId);
90105
NSString ScheduleRequestedNotification { get; }
91106
```
92107

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.
108+
> **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. This includes **all** binding types:
109+
> - API definition interfaces and members in `src/frameworkname.cs` — use `[iOS (X, Y)]`, `[Mac (X, Y)]`, etc.
110+
> - P/Invoke wrappers and manual properties in `src/FrameworkName/*.cs` — use `[SupportedOSPlatform ("iosX.Y")]`, `[SupportedOSPlatform ("macos")]`, etc.
111+
> - Fields, constants, and enum values
94112
95113
> **NEVER** use `string.Empty` — use `""`. Never use `Array.Empty<T>()` — use `[]`.
96114
115+
> **NEVER** forget `#nullable enable` at the top of every new C# file you create.
116+
97117
> **NEVER** use non-blittable types (`bool`, `char`) as backing fields in structs. Use `byte` (for `bool`) and `ushort`/`short` (for `char`) with property accessors. See [references/binding-patterns.md](references/binding-patterns.md) for the correct pattern.
98118
99119
> **NEVER** use `XAMCORE_5_0` for new code. `XAMCORE_5_0` is only for fixing breaking API changes on existing types that shipped in prior releases.
@@ -106,6 +126,8 @@ NSString ScheduleRequestedNotification { get; }
106126
107127
> ⚠️ For in depth binding patterns and conventions See [references/binding-patterns.md](references/binding-patterns.md)
108128
129+
> ⚠️ **Struct array parameters**: When an API takes a C struct pointer + count (e.g., `MyStruct*` + `NSUInteger`), bind the raw pointer as `[Internal]` with `IntPtr`, then create a manual public wrapper using the **factory pattern** with `fixed`. See [references/binding-patterns.md](references/binding-patterns.md) § "Struct Array Parameter Binding".
130+
109131
### Step 4b: Platform Exclusion Patterns for Manual Types
110132

111133
When a manually coded type (struct, extension, etc.) is not available on a specific platform (e.g., tvOS), you must handle compilation on that platform:
@@ -130,6 +152,46 @@ make -C src build
130152

131153
Fix any compilation errors before proceeding. Builds can take up to 60 minutes — do not timeout early.
132154

155+
### Step 5b: Write Monotouch Tests for Manual Bindings
156+
157+
For any manually bound APIs (P/Invokes, manual properties on partial classes, struct accessors), add tests in `tests/monotouch-test/{FrameworkName}/`.
158+
159+
> ⚠️ **Only run monotouch-tests (Step 6d) if you added or modified test files in this step.** If no manual bindings were added (i.e., all APIs were bound via `[Export]` in the API definition file), skip both this step and Step 6d.
160+
161+
```csharp
162+
using CoreText; // framework being tested
163+
using NUnit.Framework;
164+
165+
namespace MonoTouchFixtures.CoreText { // MonoTouchFixtures.{FrameworkName}
166+
167+
[TestFixture]
168+
[Preserve (AllMembers = true)]
169+
public class FontTest {
170+
171+
[Test]
172+
public void UIFontType_SystemFont ()
173+
{
174+
TestRuntime.AssertXcodeVersion (26, 4); // match the availability version
175+
176+
using (var font = new CTFont ("Helvetica", 12)) {
177+
var fontType = font.UIFontType;
178+
Assert.AreEqual (CTUIFontType.System, fontType);
179+
}
180+
}
181+
}
182+
}
183+
```
184+
185+
Key patterns:
186+
- **Namespace**: `MonoTouchFixtures.{FrameworkName}` (e.g., `MonoTouchFixtures.CoreText`)
187+
- **Version guards**: Use `TestRuntime.AssertXcodeVersion (major, minor)` matching the API's availability version. This skips the test on older runtimes instead of failing.
188+
- **Resource cleanup**: Always use `using` statements for handle-based types
189+
- **Test focus**: Exercise the manual binding — call the P/Invoke wrapper, verify the property returns sensible values, test round-trip behavior for setters
190+
191+
> ⚠️ If adding a new test file, make sure the `.csproj` at `tests/monotouch-test/` picks it up (it typically uses wildcard includes, but verify).
192+
193+
See [references/binding-patterns.md](references/binding-patterns.md) for more monotouch-test patterns.
194+
133195
> ⚠️ **Stale build artifacts**: If you encounter unexpected test failures (false "pre-existing" failures, segfaults in unrelated types), run a full `make all && make install` to clear stale `_build/` artifacts before re-testing.
134196
135197
### Step 6: Validate with Tests
@@ -147,6 +209,8 @@ make -C tests/xtro-sharpie run-maccatalyst
147209

148210
Verify all `.todo` entries for the bound framework are resolved. If any remain, they need binding or explicit `.ignore` entries with justification.
149211

212+
> ⚠️ **Delete empty `.todo` files** after resolving all entries: `git rm tests/xtro-sharpie/api-annotations-dotnet/{platform}-{Framework}.todo`. Do not leave empty `.todo` files in the repository.
213+
150214
#### 6b. Cecil Tests
151215

152216
```bash
@@ -207,6 +271,14 @@ Look for this pattern in test output to confirm results:
207271
Tests run: X Passed: X Inconclusive: X Failed: X Ignored: X
208272
```
209273

274+
#### 6d. Monotouch Tests (only if you added tests in Step 5b)
275+
276+
Skip this step if no monotouch-test files were added or modified.
277+
278+
```bash
279+
make -C tests/monotouch-test run
280+
```
281+
210282
### Step 7: Handle Test Failures
211283

212284
If introspection tests fail for newly bound types:
@@ -234,7 +306,7 @@ When reporting results, use this structure:
234306

235307
1. **APIs bound** — table of types/members added with their platforms
236308
2. **Files changed** — list of modified files
237-
3. **Test results** — per-platform pass/fail for xtro, cecil, and introspection
309+
3. **Test results** — per-platform pass/fail for xtro, cecil, introspection, and monotouch-tests
238310
4. **Remaining items** — any `.todo` entries intentionally left unbound, with reasons
239311

240312
## References

0 commit comments

Comments
 (0)