| name | macports |
| description | MacPorts package manager development workflow including Portfile creation, updates, testing, debugging build failures, and port command usage. Use when working with MacPorts ports, Portfiles, port testing, version updates, checksum updates, dependency management, build debugging, or any MacPorts development tasks. |
MacPorts Development
Overview
Comprehensive guide for MacPorts port development workflows: creating and updating Portfiles, testing ports, debugging build failures, and mastering the port command-line tool.
Core Workflows
1. Checking for Updates
Check if any GitHub-hosted or SVN-hosted ports have new versions available:
bash scripts/check-updates.sh
The script will:
- Find all Portfiles using GitHub PortGroup or SVN fetch
- Skip ports where @trodemaster is not listed as a maintainer
- Query GitHub API for latest releases
- Query SourceForge RSS feeds for SVN release commits
- Compare current version/revision with latest
- Display color-coded results (✓ up to date, ✗ update available)
Supported sources:
- GitHub-hosted ports (via GitHub API)
- SourceForge SVN ports (via RSS feed parsing for "Releasing" commits)
Script available: scripts/check-updates.sh (in repo root scripts/) automates version checking.
2. Testing a Port
Standard test sequence for any port modification:
portindex
port lint --nitpick <portname>
sudo port uninstall <portname>
sudo port clean --dist <portname>
sudo port install -sv <portname>
Script available: scripts/test-port.sh <portname> (in repo root scripts/) automates this sequence.
3. Updating Port Version
When bumping version number:
- Update
version field in Portfile
- Keep existing checksums (do NOT delete)
- Run
sudo port checksum <portname>
- MacPorts will fail and output correct checksums
- Copy checksum line from error output
- Update Portfile with new checksums
- Run
sudo port checksum <portname> again to verify
- Test the build
Why keep old checksums: MacPorts needs them present to fetch the new file and calculate correct checksums.
Script available: scripts/update-checksums.sh <portname> (in repo root scripts/) guides this workflow.
4. Creating New Port
mkdir -p category/portname
cd category/portname
portindex
sudo port checksum portname
port lint --nitpick portname
sudo port install -sv portname
Template available: assets/Portfile.template provides standard structure.
5. Submitting to MacPorts (Creating PRs)
CRITICAL REQUIREMENTS:
- STOP AND WAIT before running
gh pr create — always show the full PR description to the user and wait for explicit approval. This is a strict rule with no exceptions.
- STOP AND WAIT before committing — always show the commit message to the user and wait for explicit approval.
- MacPorts PRs must contain exactly ONE commit - squash/amend if needed
- Port lint must pass with 0 errors and 0 warnings (use
--nitpick)
- GitHub pull requests are STRONGLY PREFERRED over Trac tickets (faster workflow)
Reference: https://guide.macports.org/chunked/project.contributing.html
Commit Message Format (Official MacPorts Guidelines)
Reference: https://trac.macports.org/wiki/CommitMessages
Subject line (50-55 characters, max 60):
- List modified ports first, followed by colon
- Be specific - avoid vague subjects like "Update to latest version"
- Include version numbers when updating
- Use glob notation for multiple related ports (e.g., "py3*-numpy:", "clang-3.[6-9]:")
Examples:
portname: update to 3.0.3
autoconf, libtool: fix build on arm64
py3*-numpy: add maintainer handle
Blank line - Required between subject and body
Body (wrap at 72 characters):
- Say what the commit itself cannot - provide context
- What was previous behavior, why incorrect, how this changes it
- Don't just translate the diff into English
- Use full URLs for Trac tickets: https://trac.macports.org/ticket/12345
- For GitHub PRs: full URL or #n syntax
- Do NOT mention checksums updates (always required, redundant)
Keywords (for Trac integration):
- "References", "Addresses", "See": adds comment to ticket
- "Closes", "Fixes": closes ticket and adds comment
Example:
portname: update to 3.0.3
* update to version 3.0.3
* add maintainer's github handle
* remove obsolete patches
Closes: https://trac.macports.org/ticket/12345
What to avoid:
- ❌ Revision numbers (SVN r1234, git SHA)
- ❌ "Update checksums" (always required)
- ❌ Overly detailed implementation explanations
- ❌ Describing what the software does
PR Description Format
ALWAYS use the official MacPorts PR template as the starting point.
📋 Template: See pr-template.md for the complete official template.
Key requirements:
- Use the template structure (Description, Type(s), Tested on, Verification)
- Fill in system info using the provided shell command
- Check all applicable verification items
- Omit the entire Type(s) section if none apply - update/submission are auto-detected from title, only include Type(s) if bugfix/enhancement/security fix applies
- Keep description concise and focused
- Do NOT repeat commit message verbatim
- Do NOT mention checksums (redundant)
- Do NOT describe software functionality
Workflow:
- Run lint check:
port lint --nitpick category/portname
- Fix all warnings and errors
- Fetch upstream and create branch from
upstream/master (not fork master, which may lag):
git fetch upstream master
git checkout -b category/portname-update-X.Y.Z upstream/master
- Copy/modify files from blakeports to macports-ports
- Stage changes:
git add category/portname/
- Draft commit message (following guidelines above)
- SHOW commit message to user — STOP and wait for explicit approval before proceeding
- Commit after approval:
git commit -m "message"
- Rebase onto latest upstream/master before pushing (catches any commits that landed since branch creation):
git fetch upstream master
git rebase upstream/master
- Push to fork:
git push -u origin branch-name
- Extract "Tested on" system info from CI runner logs (see pr-template.md) — do NOT use local machine info
- Draft PR description using the official template with CI-sourced system info
- SHOW PR description to user — STOP and wait for explicit approval before proceeding
- Create PR only after approval:
gh pr create --repo macports/macports-ports
- If reviewer feedback requires changes: apply fix to blakeports → run CI (both modern and legacy runners) → verify all passing → THEN amend commit and force push to macports-ports
- If PR doesn't receive attention within a few days, email macports-dev@lists.macports.org
For new ports:
- Set ticket type to "submission" (if using Trac)
- Attach Portfile and any required patchfiles
For port updates/enhancements:
Note: Feature branches can be force-pushed after amendments. Master branch commits are immutable.
6. Debugging Build Failures
When builds fail:
cat $(port logfile <portname>)
grep -i error $(port logfile <portname>)
cd $(port work <portname>)
sudo port configure <portname>
sudo port build <portname>
See debugging.md for comprehensive debugging techniques.
7. Creating Patches
CRITICAL: MacPorts applies patches with patch -p0. This means paths in the diff must be bare — no a//b/ prefixes. Using git diff without --no-prefix produces a/foo.go/b/foo.go paths that -p0 cannot resolve, causing "No file to patch" failures.
From a git branch (upstream PR candidates)
Always use --no-prefix when generating patches from git branches:
git diff --no-prefix origin/master..upstream-pr/<branch> -- [files...] > files/patch-name.diff
Verify the patch header looks like this (no a//b/):
diff --git pkg/foo/bar.go pkg/foo/bar.go
--- pkg/foo/bar.go
+++ pkg/foo/bar.go
Never edit patch files directly — always make the fix on the branch in the fork, then regenerate:
git -C /path/to/repo checkout upstream-pr/<branch>
git -C /path/to/repo diff --no-prefix origin/master..upstream-pr/<branch> -- [files] \
> sysutils/<port>/files/patch-name.diff
From plain file edits
For simple single-file patches not tracked in a branch:
diff -u original.txt modified.txt > files/patch-name.diff
diff -u does not add a//b/ prefixes, so it is -p0 compatible by default.
Adding to Portfile
patchfiles patch-name.diff
MacPorts approach: Use system libraries in place, avoid bundling.
Port Command Usage
Essential Commands
Installation:
sudo port install -sv <portname>
sudo port install -d <portname>
Cleanup:
sudo port uninstall <portname>
sudo port clean --dist <portname>
sudo port clean --all <portname>
Clean rebuild after source changes (preferred):
sudo port uninstall stash && sudo port clean --all stash && sudo port install stash
port clean --all must come after uninstall to clear the cached work directory so the next install re-fetches and rebuilds from scratch.
Rebuild only the port, skip dependency processing:
sudo port -n upgrade --force <portname>
The -n flag skips all dependency processing. Use this when dependencies are already up to date and you only want to rebuild the target port itself.
Avoid: sudo port upgrade --force <portname> without -n — this forces a rebuild of the port AND its outdated dependencies, which can trigger a large cascade of rebuilds.
Quality Checks:
port lint --nitpick <portname>
port checksum <portname>
Information:
port info <portname>
port deps <portname>
port variants <portname>
port work <portname>
port dir <portname>
port logfile <portname>
Development:
portindex
port test <portname>
Full reference: See port-commands.md for comprehensive command documentation.
Portfile Structure
IMPORTANT: When creating or modifying Portfiles, consult the official Port Phases reference:
📚 https://guide.macports.org/chunked/reference.phases.html
This comprehensive reference covers all available keywords for each phase:
- Fetch Phase - master_sites, distfiles, fetch.type (git/svn/etc)
- Checksum Phase - checksums format (rmd160, sha256, size)
- Extract Phase - compression formats (use_zip, use_xz, etc)
- Patch Phase - patchfiles, patch.args, patch.dir
- Configure Phase - configure.args, compiler flags (configure.cflags-append), environment variables
- Build Phase - build.cmd, build.args, use_parallel_build
- Test Phase - test.run, test.target, test.env
- Destroot Phase - destroot.args, destroot.destdir, destroot.keepdirs
Use this reference to:
- Choose appropriate configure options and compiler flags
- Set build/configure environment variables correctly
- Handle non-standard build systems (CMake, SCons, etc)
- Debug phase-specific failures
- Understand keyword modifiers (-append, -delete, -replace)
Minimal Portfile
# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
PortSystem 1.0
PortGroup github 1.0
github.setup owner repo 1.2.3
revision 0
categories category
maintainers {@username provider} openmaintainer
license MIT
description Short description
long_description {*}${description}. Extended details.
checksums rmd160 HASH \
sha256 HASH \
size SIZE
depends_lib-append port:dependency
Key Sections
Dependencies:
depends_build - Build-time only (compilers, build tools)
depends_lib - Runtime libraries (linked)
depends_run - Runtime only (not linked)
Configuration:
configure.args --prefix=${prefix} \
--enable-feature
Variants:
variant feature description {
configure.args-append --with-feature
depends_lib-append port:feature-lib
}
Full syntax reference: See portfile-syntax.md for complete Portfile documentation.
Build Phase Debugging
Phase Order
fetch - Download source
checksum - Verify integrity
extract - Unpack archive
patch - Apply patches
configure - Run configure script
build - Compile source
test - Run tests (optional)
destroot - Stage installation
install - Install to system
Test Individual Phases
sudo port configure <portname>
sudo port build <portname>
sudo port destroot <portname>
Inspect Work Directory
cd $(port work <portname>)
cd $(port work <portname>)/<portname>-<version>
cat config.log
Common Issues and Solutions
Checksum Mismatch
sudo port clean --dist <portname>
sudo port checksum <portname>
Missing Dependencies
error: 'some_header.h' file not found
Solution: Find providing port and add to depends_lib:
port provides /path/to/header.h
Build Errors
cat $(port logfile <portname>)
grep -B 5 -A 10 error $(port logfile <portname>)
Lint Warnings
Fix before submitting:
port lint --nitpick <portname>
Common issues:
- Line length >80 characters
- Missing long_description
- Inconsistent indentation
Quick Reference
Standard Test Workflow
portindex && \
port lint --nitpick <portname> && \
sudo port clean --dist <portname> && \
sudo port uninstall <portname> && \
sudo port install -sv <portname>
Clean Rebuild After Source Changes
sudo port uninstall <portname> && sudo port clean --all <portname> && sudo port install <portname>
Rebuild Only This Port (dependencies already installed)
sudo port -n upgrade --force <portname>
Checksum Update Workflow
sudo port checksum <portname>
sudo port checksum <portname>
Debug Build Failure
sudo port install -sv <portname>
cat $(port logfile <portname>) | less
cd $(port work <portname>)
Resources
Scripts (scripts/ in repo root)
All scripts live in the scripts/ directory in the repository root.
scripts/test-port.sh - Automate standard port testing workflow
scripts/update-checksums.sh - Guide checksum update process
scripts/check-updates.sh - Check ports for available updates; only reports ports where @trodemaster is a maintainer
Execute without reading into context for efficiency.
References (references/)
port-commands.md - Comprehensive port CLI reference with all commands, options, and workflows. Load when working with port commands or needing command syntax.
debugging.md - Build failure debugging techniques including log analysis, common error patterns, work directory inspection, and environment troubleshooting. Load when diagnosing build failures.
portfile-syntax.md - Complete Portfile syntax reference covering structure, PortGroups, dependencies, variants, platform checks, and style guide. Load when writing or modifying Portfiles.
pr-template.md - Official MacPorts PR template. ALWAYS use as the starting point when creating pull requests. Includes verification checklist and system info helper command.
Assets (assets/)
Portfile.template - Standard Portfile template for new ports
Best Practices
- Always run
portindex after modifying Portfiles
- Use
port lint --nitpick before submitting - must pass with 0 errors and 0 warnings
- Clean distribution files (
--dist) when updating versions
- Keep old checksums during version updates (MacPorts needs them)
- Test with verbose output (
-sv flag) for debugging
- Inspect build logs (
port logfile) when builds fail
- Check work directory for build artifacts and logs
- Test individual phases to isolate failures
- Use 4 spaces for indentation in Portfiles (no tabs)
- Align continuation lines for readability
- ALWAYS stop and show commit messages and PR descriptions for explicit user approval — never commit or create a PR without approval
- Follow official commit message format - see https://trac.macports.org/wiki/CommitMessages
- Subject line: 50-55 characters, max 60 - list ports first with colon
- Body: wrap at 72 characters - provide context, not implementation details
- Use full URLs for Trac tickets and GitHub PRs in commit messages
- Don't mention checksums updates - always required, redundant
- Don't mention revision numbers (SVN r1234, git SHA) in commits
- MacPorts PRs must contain exactly ONE commit - squash or amend if needed
- Feature branches can be force-pushed - use
--force-with-lease after amends
- Use system libraries in place - avoid bundling frameworks in MacPorts builds
platform darwin version blocks: sort highest os.major threshold first (affects most systems), down to lowest; merge multiple blocks with the same threshold into one
- Never update the upstream macports-ports PR before CI passes — always fix in blakeports, run CI, verify green, then amend upstream
- Always branch from
upstream/master, not from fork master — fork master can lag behind, causing conflicts when upstream merges a concurrent change to the same port before your PR lands
- Bump
revision when fixing a dependency or build flag without changing the version — users with the port already installed at version_0 won't get the fix automatically unless revision increments. Required for: adding a missing dependency, removing an incorrect one, or changing configure args that affect the built binary