MacOS软件包管理器--MacPorts

摘要

  • MacPorts 是 macOS 上的软件包管理器,用来安装命令行工具和库,例如 gitwgetnginx。角色和 MacOS软件包管理器--brew 相同,默认目录是 /opt/local,可以和 Homebrew 装在同一台机器上。
  • 安装脚本叫 Portfile,对应 Homebrew 的 formula。日常命令是 port,改动系统的操作要加 sudo
  • Homebrew 计划在 2027 年 9 月或更晚停止在 Intel Mac 上运行,官方建议改用 MacPorts。已经用 brew 装好的软件不会自动搬过来,要在 MacPorts 里重新装。
  • 本文命令对照 MacPorts Guide,安装包版本以指南页上的 2.12.6 为例。本机是 MacOS Intel Sequoia 15.7.9,安装包选带 15-Sequoia 的 pkg。

安装

  • 需要 Xcode Command Line Tools。系统里已经为 Homebrew 装过的话,不用再装一遍。

1
2
3
xcode-select --version
xcode-select --install # 没有装过时才需要
xcode-select -p # /Library/Developer/CommandLineTools

用 pkg 安装

  • 官方推荐用和当前 macOS 版本对应的 pkg,不要用源码安装,除非你不想装到 /opt/local。下载页:GitHub releases,各系统的直链写在 Install MacPorts

  • Sequoia 15 对应 MacPorts-2.12.6-15-Sequoia.pkg。pkg 按 macOS 大版本区分,15.7.8 升到 15.7.9 不用换包。一个系统版本一个包,Intel 和 Apple Silicon 用同一个 pkg。双击安装即可。安装程序会自己改 shell 配置,并把 ports 树更新到最新。

  • 新开一个终端再验证:

1
2
3
4
5
$ port version
Version: 2.12.6

$ which port
/opt/local/bin/port
  • 安装程序会把下面这行写进 ~/.zprofile~/.profile,让 MacPorts 的命令排在 PATH 前面:

1
export PATH=/opt/local/bin:/opt/local/sbin:$PATH
  • 提示 command not found 时,先新开终端。仍没有,就检查上面的 PATH 是否写进了当前 shell 会读的文件。说明见指南 MacPorts and the Shell

升级 macOS 之后

  • 同一个大版本里的小更新,例如 Sequoia 15.7 升到 15.7.9,原来的安装继续用。更新 MacPorts 和已装软件:

1
2
sudo port selfupdate
sudo port upgrade outdated
  • 跨大版本,例如 Sequoia 15 升到 Tahoe 26,已装的 port 是按旧系统编译的,只跑 selfupdate 不够。MacPorts 2.10.0 起用 port migrate,它会按当前系统重装 MacPorts 本体,并重装和当前系统不兼容的 port。步骤见 Migration

1
2
3
4
5
6
7
# 1. 先把 Xcode Command Line Tools 更新到新系统对应的版本
xcode-select --install

# 2. 重装本体和不兼容的 port。默认只处理你点名安装的包及其依赖
sudo port migrate
# 连自动装上的依赖一起迁移
sudo port migrate --all
  • 迁移前会给已安装的包做快照。有的包装失败时,等上游修好后再执行 sudo port restore --last。快照不再需要时,用 port snapshot --list 看编号,再 sudo port snapshot --delete <编号> 删掉。

  • 2.10.0 之前没有 port migrate。那种情况要先装上当前系统对应的 pkg(已安装的 port 还在),再执行上面的 sudo port migrate

目录

1
2
3
4
5
6
/opt/local                  # 安装前缀,对应 brew --prefix
/opt/local/bin # 命令
/opt/local/sbin
/opt/local/etc/macports # MacPorts 自己的配置,sources.conf、macports.conf
/opt/local/var/macports # 下载缓存、编译中间文件、软件仓库索引
/Applications/MacPorts # 个别带图形界面的 port 会装到这里
  • 通过 MacPorts 安装的软件在 /opt/local 下面,不在 Homebrew 的 /usr/local/Cellar/opt/homebrew/Cellar

卸载

  • 先卸掉所有 port,再删掉 MacPorts 本体。配置和数据库在 /opt/local/etc,需要保留就先挪走。完整步骤见 Uninstall MacPorts

1
2
3
4
5
6
7
8
9
10
11
12
sudo port -fp uninstall installed

sudo dscl . -delete /Users/macports
sudo dscl . -delete /Groups/macports

sudo rm -rf \
/opt/local \
/Applications/MacPorts \
/Library/LaunchDaemons/org.macports.* \
/Library/Receipts/MacPorts*.pkg \
/Library/Tcl/macports1.0 \
~/.macports
  • Catalina 及更新的系统开着 SIP 时,要先删 macports 用户,再删 /opt/local

常用命令

  • 查帮助:port help,某个动作再加名字,例如 port help install。完整列表在 man 1 port,在线版是 Using MacPorts

  • 和 Homebrew 的对应关系:

要做的事 Homebrew MacPorts
更新软件列表和工具本身 brew update sudo port selfupdate
搜索 brew search wget port search wget
查看信息 brew info wget port info wget
安装 brew install wget sudo port install wget
已安装 brew list port installed
可升级 brew outdated port outdated
升级 brew upgrade sudo port upgrade outdated
卸载 brew uninstall wget sudo port uninstall wget
依赖 brew deps wget port deps wget
谁依赖它 brew uses wget port dependents wget
不再被需要的依赖 brew autoremove sudo port uninstall leaves
后台服务 brew services start nginx sudo port load nginx
检查环境 brew doctor port diagnose

更新、搜索、安装

1
2
3
4
5
6
7
8
9
10
11
sudo port selfupdate          # 更新 MacPorts 本体和 ports 树。装新软件前先跑一次
port outdated # 已安装、并且 ports 树里有新版本的包
sudo port upgrade outdated # 升级全部过期的包。官方建议整批升,不要只升其中一个

port search wget # 按名字和描述搜索
port search --name --line 'php*'
port info wget # 版本、描述、依赖、homepage、variants
port variants apache2 # 安装前可勾选的编译选项

sudo port install wget
sudo port install apache2 -preforkmpm +workermpm # - 关掉默认 variant,+ 打开另一个
  • port list 会把索引里所有包都打出来,又长又慢。查已安装的包用 port installed,查某个软件用 port search

  • 有预编译包、并且许可证允许再分发时,port install 会从 packages.macports.org 下载,跳过编译。没有二进制包就在本机从源码编译。编译失败时先清理再重试,日志路径会打在终端里:

1
2
3
4
sudo port clean wget
sudo port -v install wget
# 编译被 /usr/local 里的 Homebrew 文件干扰时,加上 -t,安装过程不看这些路径
sudo port -t install wget

已安装的包、卸载、清理

1
2
3
4
5
6
7
8
9
10
11
12
13
port installed                         # 列出已安装的包。active 是当前在用的版本
port installed wget
port contents wget # 这个包装了哪些文件
port echo requested # 你点名安装的包,不含自动拉进来的依赖

sudo port uninstall wget
sudo port uninstall --follow-dependents wget # 连同依赖它的包一起卸。依赖还在时,单独 uninstall 会被拒绝
sudo port uninstall leaves # 卸掉已经没有人依赖、也不是你点名安装的包
port echo leaves # 先看看会卸哪些,再决定要不要执行上一行

sudo port uninstall inactive # 升级后旧版本还留在磁盘上,这条把不在使用的旧版本删掉
sudo port clean --all wget # 删掉这个包的下载文件和编译中间文件
sudo port reclaim # 清 inactive 的包,并删安装过程下载的无用文件
  • upgrade 不会马上删旧版本,只是把它标成 inactive,出问题还可以切回去。确认新版本可用之后,再用 sudo port uninstall inactive 收回空间。

依赖

1
2
3
4
port deps wget
port rdeps wget # 递归依赖
port dependents openssl # 已安装的包里,谁直接依赖 openssl
port rdependents openssl

服务

  • 带后台进程的 port,用 load / unload 交给 launchd。对应 Homebrew 的 brew services

1
2
3
sudo port load nginx
sudo port unload nginx
sudo launchctl list | grep macports # 标签一般是 org.macports.<名字>

和 Homebrew 装在一起

  • 两个前缀不同,文件不会写进对方的目录。安装程序把 /opt/local/bin 放在 PATH 最前面之后,同名命令会先用到 MacPorts 的那一份。用 which git 确认当前是哪一个。

  • 同一个软件不要两套一起用。编译 MacPorts 的包时如果报和 /usr/local 里的库冲突,安装命令加上 -t

  • gem 只安装 Ruby 的库,不能用来装 gitwgetnginx 这种通用软件,也不能代替 MacPorts。

国内镜像

  • 软件列表来自 sources.conf 里带 [default] 的那一行,默认是:

1
rsync://rsync.macports.org/macports/release/tarballs/ports.tar [default]
  • 北京镜像由清华大学维护,主机名是 pek.cn.rsync.macports.org。编辑 /opt/local/etc/macports/sources.conf,把上面那一行换成:

1
rsync://pek.cn.rsync.macports.org/macports/release/tarballs/ports.tar [default]
  • 改完执行 sudo port -v selfupdate。其它地区的镜像列表在 Mirrors

  • 2.10.0 起,MacPorts 本体的更新默认走 HTTP。macports.conf 里的 rsync_serverrsync_dir 只在 HTTP 失败、退回 rsync 时才用到。ports 树仍然看 sources.conf