build-ios-binary
Compile a PAM control's iOS Obj-C/Swift module into the FLAT device-slice `.framework` for a `.ppmplugin` bundle (never an `.xcframework` β the wrap CI won't descend into one). Mac-only (Xcode).
Install / Use
npx skills add microsoft/power-platform-skills --skill build-ios-binaryInstalls into whichever agent you are using.
SKILL.md
Installable skill definition
Quality Score
Category
Development & EngineeringSupported Platforms
Our assessment of build-ios-binary
build-ios-binary scores 85/100 on our quality scale, 2682nd of 4,600 Development & Engineering skills we index.
Its SKILL.md is 15 KB long, well organised into 11 sections with 2 code examples: a thorough specification that gives an agent plenty to work with.
It has 919 GitHub stars, a meaningful sign that others use it.
Maintenance, license and trust
- The repository was last updated 12 days ago, so build-ios-binary is actively maintained.
- It is released under the MIT license, a permissive license that allows use, modification and commercial use with attribution.
- Its trust signals score 100/100, with no cautions. These come from repository metadata, not a code audit β read the skill file before letting an agent act on it.
build-ios-binary compared with similar skills
All 4 of these similar skills score higher than build-ios-binary; compare them before choosing.
| Skill | Score | Stars | Updated | Format |
|---|---|---|---|---|
| build-ios-binary (this skill)by microsoft | 85 | 919 | 12d ago | SKILL.md |
| ai-job-searchby MadsLorentzen | 100 | 45.1k | 1d ago | CLAUDE.md |
| claude-howtoby luongnv89 | 100 | 41.8k | 6d ago | CLAUDE.md |
| algorithmic-artby anthropics | 100 | 177.9k | 14d ago | SKILL.md |
| pptxby anthropics | 100 | 177.9k | 14d ago | SKILL.md |
Frequently asked questions
- How do I install build-ios-binary?
- Run
npx skills add microsoft/power-platform-skills --skill build-ios-binary. The install tabs above show the steps for each supported agent. - Which AI agents does build-ios-binary work with?
- It is written for Universal, as a SKILL.md file. Other agents that read the same format can often use it too.
- Is build-ios-binary safe to use?
- It is MIT-licensed and scores 100/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
- Is build-ios-binary still maintained?
- The repository was last updated 12 days ago, so build-ios-binary is actively maintained.
Skill content
View source on GitHubname: build-ios-binary
description: "Compile a PAM control's iOS Obj-C/Swift module into the FLAT device-slice .framework for a .ppmplugin bundle (never an .xcframework β the wrap CI won't descend into one). Mac-only (Xcode). Builds from a throwaway staged copy so canonical ios/ and the podspec stay untouched, references React-Core headers only (React is weak-linked and provided by the wrap host at runtime, no CocoaPods), generates the required umbrella header, module map and Info.plist, sets the critical build settings, asserts manifest conformance, then runs a device-only xcodebuild archive and copies out the flat framework to ppmplugin/staging/ios/. Known limitation β the React weak-link flags aren't yet validated against a live wrap host and the RN pin must match the host's. Run after /generate-ppmplugin-manifest for an iOS or Both target, before /assemble-ppmplugin."
allowed-tools: Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion, Skill
model: sonnet
/build-ios-binary
Turns the extension's iOS source (ios/RCT<Pascal>Module.{h,m}) into the flat <Pascal>Plugin.framework/ (device slice) that the wrap runtime loads. iOS analogue of /build-android-binary: source in, a prebuilt framework out.
Ship a FLAT
.framework, NOT an.xcframework. The wrap pipeline expectsios/<Name>.frameworkand does not descend into an.xcframeworkβ shipping one fails with "Framework '<Name>.framework' not found in plugin." This skill builds the device archive only and copies out the flat.framework. Seeppmplugin-format Β§5b.
Mac-only. Requires Xcode. On Linux/Windows this skill BLOCKs β Android-only contributors can't produce the iOS slice.
KNOWN LIMITATION β read this. The single hard part is React-Core: the framework compiles against React's headers (
#import <React/RCTBridgeModule.h>) from the control repo's own pinnedreact-nativedevDep, while never embedding React β the wrap host provides it at runtime (weak-link). The coupling that matters is the RN version pin (0.79.7): it must match the RN the wrap host ships. The exact weak-link flags / header-search-path setup aren't yet validated against a live wrap host β that's the main risk area. React symbol/header errors mean the RN pin diverged from the host's RN, not a code bug.
Read shared/ppmplugin-format.md Β§5b (iOS binary requirements) and the naming-conventions.md iOS rows.
What this skill does NOT do
- Does not author
manifest.json(run/generate-ppmplugin-manifestfirst β this skill reads it for cross-checks and the framework/moduleClass names). - Does not zip the
.ppmpluginβ that's/assemble-ppmplugin. - Does not build Android β that's
/build-android-binary. - Does not modify the canonical
ios/or the podspec β all adjustments live in a throwaway copy underppmplugin/staging/ios-build/. - Does not sign the framework β the wrap pipeline signs at packaging time (given
BUILD_LIBRARY_FOR_DISTRIBUTION=YES SKIP_INSTALL=NO). No signing skill needed.
Step 1 β Read shared docs + prereq block
- Read
shared/shared-instructions.mdandshared/ppmplugin-format.md. - Read
ppmplugin/staging/manifest.json. If absent, STOP withNEEDS_CONTEXT: manifest.json missing β run /generate-ppmplugin-manifest first. If it has noentrypoints.ios, STOP withNEEDS_CONTEXT: manifest targets Android-only β re-run /generate-ppmplugin-manifest and choose iOS/Both. - Read the
## ppmplugin (third-party controls)block in.extension-state.md. Replace-existing gate: ifppmplugin/staging/ios/<framework>.frameworkalready exists, surface it (with its build timestamp) and ask viaAskUserQuestionβ Keep existing (skip to Step 6) vs Replace (rebuild). Default Keep if source + manifest unchanged since the recorded build, else Replace (note Keep is stale). Perppmplugin-format Β§1replace-existing rule. - Run prereq checks and print the visible block (shared-instructions Β§9.2). Policy: resolve, don't punt (locate tools by path; offer + run safe installs):
| Check | Verify | Auto-fix |
|---|---|---|
| macOS | uname = Darwin | NOT fixable β STOP with BLOCKED: /build-ios-binary is Mac-only (iOS needs Xcode) on Linux/Windows |
| Xcode 16+ (26.2+ recommended) | xcodebuild -version | NOT auto-fixable β print: install Xcode from the App Store / xcodes; STOP if missing |
| React-Core headers present | node_modules/react-native/React/Base/RCTBridgeModule.h exists (the react-native devDep, in the control repo) | if the devDep isn't installed: pnpm install in the repo |
| CocoaPods (optional β fallback path only) | pod --version | Not required for the recommended header-only build (Step 2). Only needed if you fall back to the Podfile path; brew install cocoapods on confirm. |
Step 2 β React-Core source (self-contained) + confirm the config
The framework needs React's headers at compile time. The source is the control repo's own node_modules/react-native β the pinned react-native devDep (0.79.7 for pen-input), which ships the React headers (React/Base/RCTBridgeModule.h). The build is fully self-contained in the control repo. If the devDep isn't installed, run pnpm install; only if it's genuinely absent, ask the user for a react-native path.
Recommended: header-only React (no CocoaPods). Aggregate the React headers into a flat include dir in the staging copy and point the framework target at it β cleaner and faster than the Pod chain, and it avoids the CocoaPods/React-Codegen failures that bite under recent Xcode (see ppmplugin-format Β§5b):
mkdir -p ppmplugin/staging/ios-build/include/React
# copy the RN headers the module imports (Base + the Libraries it uses):
cp node_modules/react-native/React/Base/*.h ppmplugin/staging/ios-build/include/React/
cp -R node_modules/react-native/React/Base node_modules/react-native/Libraries ppmplugin/staging/ios-build/include/React/ 2>/dev/null || true
Then set on the framework target: HEADER_SEARCH_PATHS = $(inherited) $(SRCROOT)/include and OTHER_LDFLAGS = -undefined dynamic_lookup (weak-links React's symbols β the host provides them at runtime). -undefined dynamic_lookup is deprecated by Apple (works today, may break in a future Xcode β known caveat).
Fallback: CocoaPods β only if the header-only path doesn't suffice. A Podfile referencing the devDep (pod 'React-Core', :path => '<repo>/node_modules/react-native') gives CocoaPods the header map, but on recent Xcode/RN-0.79 you'll need post_install patches (boost URL, Yoga _pt, RCT-Folly clockid_t, boost std::unary_function) and may still hit the React-Codegen sandbox failure β all documented in ppmplugin-format Β§5b.
What matters either way is that the pinned RN version (0.79.7) matches the RN the wrap host ships at runtime (React is weak-linked, host-provided). Print the detected RN version and ask via AskUserQuestion to confirm / override the source + version before building. State plainly: "React is provided by the wrap host at runtime; React symbol/header errors at build or load mean the RN pin has diverged from the host's RN version."
Step 3 β Stage a standalone Xcode framework project (canonical ios/ stays pristine)
Like the Android build, work from a throwaway copy so the source the engineer maintains is never touched.
-
Copy
ios/*.{h,m}βppmplugin/staging/ios-build/Sources/(fresh each run). -
Generate the umbrella header
ppmplugin/staging/ios-build/<Pascal>Plugin.hand mark it a Public header (build hygiene, not runtime-required β the wrap playerdlopens the binary and usesNSClassFromString, it neverimports the module, so the framework loads fine without a module map; the umbrella just silences theDEFINES_MODULEwarning. Generate it anyway for a clean build). Minimal contents:#import <Foundation/Foundation.h> FOUNDATION_EXPORT double <Pascal>PluginVersionNumber; FOUNDATION_EXPORT const unsigned char <Pascal>PluginVersionString[]; -
Generate a standalone Xcode framework project
ppmplugin/staging/ios-build/<Pascal>Plugin.xcodeproj, product/target name<Pascal>Plugin(=entrypoints.ios.framework), compiling the copied sources, with the umbrella as the Public header. Derive from the canonical podspec:- System frameworks to link: from the podspec
s.frameworks(e.g. pen-input βPencilKit, UIKit, CoreGraphics, QuartzCore). - Deployment target: from
s.platform(e.g.:ios, "14.0") β but floor it at the supported PAM shell minimum iOS 16.0. - xcodeproj-gem trap (if generating via the
xcodeprojgem): when a group already carries its path (e.g.Sources), add file refs filename-only βnew_group('Sources','Sources')+new_reference("Sources/<file>")doubles toSources/Sources/<file>β file-not-found. Pin a known-goodgen_project.rbrather than re-deriving it each run.
- System frameworks to link: from the podspec
-
Set the build settings (each maps to a documented wrap/on-device failure β see
ppmplugin-format Β§5b):| Setting | Value | |---|---| | Mach-O Type | Dynamic Library (NOT Static) | | Dead Code Stripping | NO (preserves the
+moduleNameclass method andRCT_EXPORT_METHODmetadata the host reads afterdlopen) | | Defines Module | YES | | Enable Bitcode | NO | |HEADER_SEARCH_PATHS|$(inherited) $(SRCROOT)/include(header-only React from Step 2) | |OTHER_LDFLAGS|-undefined dynamic_lookup(weak-link React; host-provided at runtime) | |BUILD_LIBRARY_FOR_DISTRIBUTION| YES | |SKIP_INSTALL| NO | |GENERATE_INFOPLIST_FILE| YES (REQUIRED β a framework with no Info.plist is rejected by the wrap codesign step) | |INFOPLIST_KEY_CFBundleDisplayName|<Pascal>Plugin| |MARKETING_VERSION|<version from manifest>| |CURRENT_PROJECT_VERSION|1| |PRODUCT_BUNDLE_IDENTIFIER|com.powerapps.<lowername>|
The canonical ios/ + podspec are never modified β report the staging adjustments applied.
Step 4 β Assert manifest conformance
Before building, verify the source matches the manifest (the iOS analogue of the Android DexClassLoader asserts):
- Class name in
ios/RCT<Pascal>Module.h==manifest.entrypoints.ios.moduleClass. - Class name in the
.m==manifest.entrypoints.ios.moduleClass, and+ (NSString *)moduleNamereturnsmanifest.receivers[].nativeModule. - Each
RCT_EXPORT_METHOD(<name>:β¦)name is onmanifest.receivers[].methods. - The module class instantiates via no-arg
[cls new]β the runtime resolvesmoduleClassafter loading the framework and constructs it with[cls new]. A custom designated initializer that takes arguments breaks instantiation β the plugin is skipped at load. If the.mdeclares an- (instancetype)initWithβ¦and no plaininit, STOP withBLOCKED: <moduleClass> must support no-arg initialization. - Each
RCT_EXPORT_METHODtakes oneNSDictionary *requestfirst param (then resolver/rejecter) β the wrap proxy spreads the PCF'sargs: [request]positionally. A method expanding the request into multiple positional params won't receive its data; surface a WARNING (a no-arg op likegetStatustaking only resolver/rejecter is fine β ppmplugin-format Β§2).
A mismatch means the manifest and the binary disagree β the call won't reach the module on device. STOP with the specific mismatch rather than building a broken pair.
Truncated for display β read the full file on GitHub.
Related Skills
ai-job-search
45.1kThe job search that runs on your machine. AI job application framework built on Claude Code: evaluate postings, tailor CVs, write cover letters, prep interviews. Fork it and own it.
claude-howto
41.8kA visual, example-driven guide to Claude Code β from basic concepts to advanced agents, with copy-paste templates that bring immediate value.
algorithmic-art
177.9kCreating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems.
pptx
177.9kUse this skill any time a .pptx or .potx file is involved in any way β as input, output, or both. This includes: creating slide decks, pitch decks, or presentations; reading, parsing, or extracting text from any .pptx or .potx file (even if the extracted content will be used elsewhere, like in an emβ¦
Languages
Trust signals
From repository metadata: license, adoption, age and documentation. Not a code audit β see the Safety scan above for what the skill file itself contains.
