MacPorts tooling richness

I wrote earlier about my experience switching to MacPorts. My appreciation for its tooling grows the more I use it. port(1) is the canonical program to manage MacPorts packages, and it provides a rich set of commands.

Special expressions

In general, the command port echo [expression] prints the list of packages matching an expression. Some special expressions, such as requested and leaves below, are expressions expanded using MacPorts’ internal rules.

The command port echo requested prints the list of explicitly requested packages (for instance, packages explicitly installed using port install).

$ port echo requested
bash                           @5.2.15_0
clang-16                       @16.0.6_0+analyzer
darcs                          @2.16.5_0
...

The command port echo leaves prints the list of installed packages that have zero dependent packages. Think: leaf nodes in a tree of dependency relationships.

$ port echo leaves
autoconf                       @2.71_1
autoconf-archive               @2023.02.20_0
...

The man page can be read with man port-echo.

Dependency relationships

To list the packages that depend on a specified package, use the special expressions depends: or rdepends: (the recursive version).

$ port echo depends:ffmpeg
aubio
audacious-plugins
audacity
...

And to list the packages that a specified package depends on, use the dependents or rdependents subcommands.

$ port dependents ffmpeg
ffmpeg has no dependents.

Handling unused packages

Special expressions, such as leaves, can be used elsewhere, too. For example, the command to remove leaf packages that aren’t depended upon by other packages is:

$ sudo port uninstall leaves

Note that more leaves may rise as the present leaves are removed, so to remove all packages with no dependents you have to repeat the command, as follows. (I appreciate how nicely this fits into a simple shell loop.)

$ while sudo port uninstall leaves; do :; done

MacPorts also has the concept of inactive packages, which are old versions 1 of packages. Combined with the above, the command to remove all unused packages becomes:

$ sudo port uninstall inactive
$ while sudo port uninstall leaves; do :; done

Upgrades and linking inconsistencies

Sometimes binaries installed by MacPorts may have linking inconsistencies. The subcommand rev-upgrade can detect these issues attempt to fix them.

$ sudo port rev-upgrade

If this doesn’t address the issue, upgrading the tree and packages can fix the issue.

$ sudo port selfupdate
$ sudo port upgrade outdated

Of course, outdated itself is a special expression, like leaves from earlier. So you can use it with port echo to see which packages will be upgraded, before upgrading them:

$ port echo outdated
jansson                        @2.13.1_0
librsvg                        @2.54.5_0
...

Miscellanea

To mark an already installed package as explicitly requested, use the setrequested subcommand. You may need to do this, for example, if the package had originally been installed as a dependency for another package, but now you want to keep the package around explicitly.

$ sudo port setrequested gsed

To see the filelist for a package—an essential operation in a package manager—use the contents subcommand:

$ port contents gmp
Port gmp contains:
  /opt/local/include/gmp.h
  /opt/local/include/gmpxx.h
...
  1. By default port upgrade does not remove old versions of packages during upgrades; they’re only deactivated and the files kept around.