Update native dependencies (libpng, libexpat, zlib, libwebp, harfbuzz, freetype, libjpeg-turbo, etc.) in SkiaSharp's Skia fork. Handles security CVE fixes, bug fixes, and version bumps. Use when user asks to: - Bump/update a native dependency (libpng, zlib, expat, webp, etc.) - Fix a CVE or security vulnerability in a native library - Update Skia's DEPS file - Check what version of a dependency is currently used - Analyze breaking changes between dependency versions Triggers: "bump libpng", "update zlib", "fix CVE in expat", "update native deps", "what version of libpng", "check for breaking changes". For security audits (finding CVEs, checking PR coverage), use the `security-audit` skill instead.
Update native dependencies in SkiaSharp's Skia fork (mono/skia).
You MUST complete ALL phases in order. Do not skip phases to save time.
Before starting, confirm you will:
externals/skiacgmanifest.jsonskiasharp or main)🛑 STOP AND ASK before: Creating PRs, Merging PRs, Force pushing, Any destructive git operations
⛔ POLICY VIOLATION: Direct commits to protected branches are prohibited.
This rule applies to BOTH repositories:
| Repository | Protected Branches | Action Required |
|---|---|---|
| mono/SkiaSharp (parent repo) | main | Create feature branch first |
mono/skia (externals/skia submodule) | main, skiasharp | Create feature branch first |
Before ANY commit in either repository:
dev/issue-NNNN-description or dev/update-{dep}main or skiasharp — All changes require a PR# ✅ CORRECT — Always create feature branch first
cd externals/skia
git checkout skiasharp
git checkout -b dev/update-libpng
# Now make commits...
# ❌ WRONG — Never do this
cd externals/skia
git checkout skiasharp
git commit -m "Update libpng" # POLICY VIOLATION
| Shortcut | Why It's Wrong |
|---|---|
Push directly to skiasharp or main | Bypasses PR review and CI |
| Skip native build phase | CI is too slow; must verify locally first |
| Manually close issues | Breaks audit trail; PR merge auto-closes |
Skip cgmanifest.json update | Security compliance requires it |
Skip externals/skia submodule update | SkiaSharp won't use the new dependency version |
| Revert/undo pushed commits | Fix forward with new commit instead |
| Merge both PRs without updating submodule in between | Squash-merge creates new SHA; submodule points to orphaned commit; BREAKS USERS |
externals/skia/DEPSgit rev-parse {tag}^{commit}Source File Verification (MANDATORY):
cd externals/skia/third_party/externals/{dep}
git diff {old}..{new} --diff-filter=AD --name-only # Added/Deleted files
Cross-reference against externals/skia/third_party/{dep}/BUILD.gn — new source files may need to be added.
👉 See references/breaking-changes.md for risk assessment.
externals/skia/DEPS with new commit hashcgmanifest.json with new version (required for CVE detection)👉 See documentation/dev/dependencies.md for the cgmanifest format.
🛑 MANDATORY: Build locally before creating PRs.
See documentation/dev/building.md for platform-specific build commands.
dotnet cake --target=externals-macos --arch=arm64 # Example
# Run all tests (core + Vulkan + Direct3D — backends self-skip if unavailable)
dotnet test tests/SkiaSharp.Tests.Console.sln
🛑 STOP AND ASK FOR APPROVAL before creating PRs.
Both PRs must be created together — CI requires both.
| Repository | Branch Name | Target Branch |
|---|---|---|
| mono/skia | dev/update-{dep} | skiasharp |
| mono/SkiaSharp | dev/update-{dep} | main |
Example: For libfoo, use dev/update-libwebp in both repos.
In the externals/skia directory, create a branch named dev/update-{dep}, commit the DEPS and BUILD.gn changes, push, and create a PR targeting the skiasharp branch.
⚠️ CRITICAL: You MUST update the submodule reference, not just cgmanifest.json
In the SkiaSharp root, create a branch named dev/update-{dep}. Then:
externals/skia, fetch and checkout the branch you just pushed in Step 1git add externals/skia cgmanifest.json (the submodule AND the manifest)mainEdit both PRs to reference each other:
Required SkiaSharp PR: https://github.com/mono/SkiaSharp/pull/{number}Required skia PR: https://github.com/mono/skia/pull/{number}Before proceeding, verify ALL of these:
dev/update-{dep} conventionskiasharp branchmain branchexternals/skia submodule points to the mono/skia PR branch (check with git submodule status)cgmanifest.json updated with new versionSkiaSharp uses Azure DevOps. mono/skia has no CI — relies on SkiaSharp's.
🛑 STOP AND ASK FOR APPROVAL before each merge.
🚨 CRITICAL: SQUASH MERGE CREATES NEW COMMITS
When you squash-merge mono/skia PR, GitHub creates a NEW commit SHA on the
skiasharpbranch. The original commits ondev/update-{dep}become orphaned when the branch is deleted.If SkiaSharp's submodule still points to the old (orphaned) commit, it will BREAK:
- New clones will fail
- Submodule updates will fail
- Users cannot build SkiaSharp
YOU MUST UPDATE THE SUBMODULE BEFORE MERGING SKIASHARP PR.
skiasharp branchBefore proceeding past each step, verify:
skiasharp branch to get new SHAcd externals/skia && git checkout {new-sha})❌ NEVER merge both PRs in quick succession without updating the submodule in between. ❌ NEVER assume the submodule reference is correct after squash-merging mono/skia.
skiasharp branch — fetch main, check that externals/skia commit exists on origin/skiasharp (not orphaned)| Dependency | DEPS Key |
|---|---|
| libpng | third_party/externals/libpng |
| libexpat | third_party/externals/expat |
| zlib | third_party/externals/zlib |
| libwebp | third_party/externals/libwebp |
| harfbuzz | third_party/externals/harfbuzz |
| freetype | third_party/externals/freetype |
| libjpeg-turbo | third_party/externals/libjpeg-turbo |
For cgmanifest names and upstream URLs, see documentation/dev/dependencies.md.