1. Introduction
2. Installing MacPorts
2.1. Install Xcode
2.2. Install MacPorts
2.3. Upgrade MacPorts
2.4. Uninstall MacPorts
2.5. MacPorts and the Shell
3. Using MacPorts
3.1. The port Command
3.2. Port Variants
3.3. Common Tasks
3.4. Port Binaries
4. Portfile Development
4.1. Portfile Introduction
4.2. Creating a Portfile
4.3. Example Portfiles
4.4. Port Variants
4.5. Patch Files
4.6. Local Portfile Repositories
4.7. Portfile Best Practices
4.8. MacPorts' buildbot
5. Portfile Reference
5.1. Global Keywords
5.2. Global Variables
5.3. Port Phases
5.4. Dependencies
5.5. Variants
5.6. Tcl Extensions & Useful Tcl Commands
5.7. StartupItems
5.8. Livecheck / Distcheck
5.9. PortGroups
6. MacPorts Internals
6.1. File Hierarchy
6.2. Configuration Files
6.3. Port Images
6.4. APIs and Libs
6.5. The MacPorts Registry
6.6. Tests
7. MacPorts Project
7.1. Using Trac for Tickets
7.2. Using Git and GitHub
7.3. Contributing to MacPorts
7.4. Port Update Policies
7.5. Updating Documentation
7.6. MacPorts Membership
7.7. The PortMgr Team
8. MacPorts Guide Glossary
Glossary

5.9. PortGroups

5.9.1. PortGroup Introduction

PortGroups are simply include files for portfiles. They can define as much or as little as a portgroup author feels is necessary to provide a set of definitions or behaviors common to a group of portfiles, in order that those portfiles can be expressed as simply as possible with minimum redundancy.

See the following folder for PortGroup definitions:

${prefix}/var/macports/sources/rsync.macports.org/macports/release/tarballs/ports/_resources/port1.0/group/

or if you prefer directly in GitHub .

A sample listing follows:

%% ls -1 /opt/local/var/macports/sources/rsync.macports.org/macports/release/tarballs/ports/_resources/port1.0/group/

active_variants-1.1.tcl
apache2-1.0.tcl
app-1.0.tcl
archcheck-1.0.tcl
bitbucket-1.0.tcl
cmake-1.0.tcl
cmake-1.1.tcl
compiler_blacklist_versions-1.0.tcl
compilers-1.0.tcl
conflicts_build-1.0.tcl
crossbinutils-1.0.tcl
crossgcc-1.0.tcl
cxx11-1.0.tcl
cxx11-1.1.tcl
debug-1.0.tcl
elisp-1.0.tcl
github-1.0.tcl
...

The requirements of a minimum portfile using a portgroup varies by portgroup. The sections below devoted to each portgroup (or, for portgroups not documented there yet, the comments in the header of the portgroup file itself) should provide guidance on how each portgroup is used. Prospective MacPorts developers are also encouraged to examine existing portfiles that use these portgroups.

5.9.2. PortGroup github

The github portgroup allows for efficient porting of software hosted on GitHub.

5.9.2.1. Description

This portgroup greatly simplifies the porting of software hosted on GitHub. Provided a GitHub repository author follows common GitHub practices, a port can be almost fully configured simply by declaring the repository coordinates. The github portgroup is indeed capable of configuring, amongst other things:

  • The port name.

  • The port version.

  • The distfiles (if the project uses GitHub releases).

  • The livecheck parameters.

5.9.2.2. Setting up the GitHub repository coordinates

The main port configuration is triggered by the usage of the github.setup keyword:

PortGroup           github 1.0
github.setup        author project version [tag_prefix]

By default, the port name will be set to the GitHub project name (project) and version will be set to the GitHub project version. The port name can be overridden by using the name keyword.

The tag_prefix is optional, and it's used to specify a prefix to use when constructing the tag name. If, for example, the project uses tags such as v1.0.0, then the tag_prefix should be set to v, as in the following example:

github.setup        author project version v

5.9.2.3. Choosing a distfile strategy

GitHub, and as a consequence the github portgroup, offers multiple mechanisms to get a distfile:

  • Distfile from a git commit or tag.

  • Distfile from a GitHub release.

  • Distfile from a GitHub download.

  • Distfile from Github auto-generated archive downloads

The default behaviour of the portgroup is using GitHub automatically generated distfile from a git commit or tag. However, the best practice should be using a GitHub release.

5.9.2.4. Distfile from tag or commit

The default behaviour of the github portgroup is leveraging GitHub's ability to create a distfile from a git tag or commit. In this case, the distname is irrelevant and should not be set.

If the project's developers do not tag their releases, they should be encouraged to do so. Until they do, or in the case in which an untagged development version has to be used, port maintainers have the possibility of specifying a git commit hash and manually set the version field. If the project does not assign version numbers the port maintainer has to define one. Such versions typically format the date of the chosen commit using the YYYYMMDD pattern. If, for example, the port maintainer decides to use a changeset with the hash 0ff25277c3842598d919cd3c73d60768, committed on April 1, 2014, then the following would be used:

github.setup        someone someproject 0ff25277c3842598d919cd3c73d60768
version             20140401

5.9.2.5. Distfile from a GitHub release

The github portgroup allows maintainers to easily configure the distfiles when the project uses GitHub releases. A release is the best distfile candidate, and project maintainers should be encouraged to use them. To enable this feature, the following keyword must be used:

github.tarball_from releases

By default, the github portgroup sets distname to:

distname            ${github.project}-${github.version}

However, GitHub does not enforce any rule for release distfiles, so port maintainers may need to override the distname as they would do for other ports.

5.9.2.6. Distfile from a GitHub download

Older projects use the discontinued downloads service. New GitHub downloads can no longer be created, but old ones are still available.

If the project doesn't have GitHub releases but does have GitHub downloads, they can be used using the following keyword:

github.tarball_from downloads

Since GitHub doesn't enforce any naming rules for downloads, the portgroup can only provide a sensible default value for distname, which can be overridden if necessary.

5.9.2.7. Distfile from GitHub archive downloads

Further still, many Github projects have automatically-generated archive URLs that can be used for downloading distfiles. This can be enabled via archive as follows:

github.tarball_from archive

5.9.2.8. Using repositories with git submodules

If the project uses git submodules, some projects' tag- or commit-based distfiles will not contain all the necessary files. Once again, the best distfile candidate (if available) is a distfile from GitHub releases, as described in the previous sections. However, in the case a project doesn't provide any other alternative, a project using submodules can be successfully retrieved by fetching the sources using git and then using a post-fetch to initialize the submodules:

fetch.type          git

post-fetch {
    system -W ${worksrcpath} "git submodule update --init"
}

5.9.3. PortGroup gnustep

PortGroup gnustep allows for efficient porting of GNUstep-based open source software using the GNU objective-C runtime that defines options for the configuration, build, and destroot phases, and also defines some values for GNUstep-based software. A minimum Portfile using the gnustep PortGroup class need only define the fetch and the checksum phases.

5.9.3.1. gnustep PortGroup Specific Keywords

Portfiles using the gnustep PortGroup allow for port authors to set the following keywords in addition to the general Portfile keywords.

gnustep.post_flags

An associative array which specifies the sub-directories relative to ${worksrcpath} and the SHARED_LD_POSTFLAGS variables to be added to GNUmakefile.preamble in those sub-directories. This helps making the patching process easier on Darwin.

  • Type: optional

  • Default: none

  • Example:

    platform darwin {
        array set gnustep.post_flags {
            BundleSubDir "-lfoo -lbar"
        }
    }
gnustep.cc

Define the gcc compiler to use when compiling a port.

  • Type: optional

  • Default: gcc-mp-4.2

  • Example:

    gnustep.cc gcc-mp-4.3
variant with_docs

Many GNUstep packages include a Documentation sub-directory that is not built by default. Enabling this variant builds and installs the included documentation.

  • Type: optional

  • Example:

    %% port install gnustep-gui +with_docs

5.9.3.2. gnustep FilesystemLayout Keywords

PortGroup gnustep supports both the traditional gnustep file layout and the new fhs file layout. However, a given ported application does not necessarily support both. The Portfiles have access to many procedures to handle these two layouts:

set_gnustep_make

Sets GNUSTEP_MAKEFILES according to the FilesystemLayout

set_gnustep_env

Sets DYLD_LIBRARY_PATH and PATH for the gnustep FilesystemLayout

gnustep_layout

Returns true (1) if current file layout is gnustep

set_system_library

Sets GNUSTEP_SYSTEM_LIBRARY according to the FilesystemLayout

set_local_library

Sets GNUSTEP_LOCAL_LIBRARY according to the FilesystemLayout

5.9.3.3. gnustep PortGroup Sugar

Portfiles using PortGroup gnustep do not need to define the following variables:

categories

Default: gnustep

homepage

Default: http://www.gnustep.org/

master_sites

Default: gnustep:core

depends_lib

Default: gnustep-core

use_configure

Default: no

configure.env

Default: DYLD_LIBRARY_PATH PATH

configure.pre_args-append

Default: CC=gcc-mp-4.2 GNUSTEP_MAKEFILES

build.type

Default: gnu

build.env

Default: DYLD_LIBRARY_PATH PATH

build.pre_args-append

Default: messages=yes

destroot.env

Default: DYLD_LIBRARY_PATH PATH

destroot.pre_args-append

Default: messages=yes

5.9.4. PortGroup golang

The golang PortGroup allows for efficient porting of Go-based open source software.

5.9.4.1. Description

This PortGroup greatly simplifies the porting of software written in Go, especially when the software and its dependencies are hosted on GitHub or Bitbucket. Provided a project author follows common Go packaging practices, a port can be almost fully configured simply by declaring the package identifier.

In particular, Go has strict requirements relating to the arrangement of code on the filesystem (GOPATH). This PortGroup handles the construction of the GOPATH for you.

5.9.4.2. Setting up the Go package identifier

The main port configuration is triggered by the usage of the go.setup keyword:

PortGroup           golang 1.0
go.setup            domain/author/project version [tag_prefix] [tag_suffix]

By default, the port name will be set to the package name (project) and version will be set to the project version. The port name can be overridden by using the name keyword.

The tag_prefix and tag_suffix are optional, and are used to specify a prefix/suffix to use when constructing the tag name. If, for example, the project uses tags such as v1.0.0, then the tag_prefix should be set to v, as in the following example:

go.setup        domain/author/project version v

When the domain is either github.com or bitbucket.org, the appropriate PortGroup will be applied and set up automatically. See those PortGroups' documentation for details.

Projects hosted elsewhere can be used, but require additional manual setup.

5.9.4.3. Setting up dependencies

The PortGroup provides a keyword to facilitate listing dependencies: go.vendors. Supply a list of vendor package IDs, their versions (git commit hashes, labeled "lock" as in "lockfile"), and their checksums as follows. The packages and their versions can usually be found in a lockfile (e.g. Gopkg.lock, glide.lock) in the upstream code. All checksum types supported by the checksums keyword are supported here as well.

go.vendors      example.com/dep1/foo \
                    lock    abcdef123456... \
                    rmd160  fedcba654321... \
                    sha256  bdface246135... \
                    size    1234 \
                example.com/dep2/bar \
                    lock    abcdef123456... \
                    rmd160  fedcba654321... \
                    sha256  bdface246135... \
                    size    4321

Note that go.vendors cannot be used with dependencies hosted outside of GitHub and Bitbucket. Such dependencies must be handled manually.

After the extraction phase, the vendor packages will be placed alongside the main port code as appropriate in the GOPATH.

5.9.4.4. Building and destroot

By default this PortGroup runs go build from the ${worksrcpath}. Assuming this results in a binary with the same name as the project, and that there are no other files to install, the following is sufficient for the destroot phase:

destroot {
    xinstall -m 755 ${worksrcpath}/${name} ${destroot}${prefix}/bin/
}

Please modify as appropriate for each individual port.

5.9.4.5. golang PortGroup Specific Variables

When the golang PortGroup is declared within a Portfile, the following variables are provided during port install.

go.bin

Default: ${prefix}/bin/go

The Go binary location.

go.package

The package identifier of the port, e.g. example.com/author/project.

go.domain, go.author, go.project

The individual parts of ${go.package}.

gopath

Default: ${workpath}/gopath

The location where source packages will be arranged after the extract phase.

goarch

Default: 386 or amd64, depending on ${build_arch}

goos

Default: ${os.platform}

5.9.4.6. golang PortGroup Sugar

Portfiles using PortGroup golang do not need to define the following variables:

name, version, homepage, distname, master_sites, livecheck.*

Default: see github or bitbucket PortGroups (when project hosted on GitHub or Bitbucket)

depends_build

Default: port:go

use_configure

Default: no

platforms

Default: darwin freebsd linux

Go can target these platforms, but individual ports should override this as necessary if only some are actually supported.

build.cmd

Default: ${go.bin} build

build.args

Default: ""

build.target

Default: ""

build.env

Default: GOPATH=${gopath} GOARCH=${goarch} GOOS=${goos} CC=${configure.cc}

post-extract

Default: arranges the project and vendor source files appropriately in the GOPATH.

5.9.5. PortGroup java

PortGroup java is useful for Java packages.

5.9.5.1. java PortGroup Specific Keywords

Portfiles using the java PortGroup allow for port authors to set the following keywords in addition to the general Portfile keywords.

java.version

This keyword indicates that the port requires a Java installation of the specified version. If no such installation can be located, and no fallback option is specified (see below), the port will fail at the pre-fetch phase.

The version string can indicate a specific version or a range with wildcards "+" and "*". Note that Java 8 and earlier are "1.8", etc., while Java 9 and later are "9", etc.

  • Type: optional

  • Example:

    java.version    1.8+
java.fallback

This keyword indicates an (optional) port dependency that will be added to the ports 'depends-lib' list in the case a prior installation of Java satisfying the requested version can not be found. It is recommended that only an LTS version of Java be specified as the fallback, as non-LTS versions are only supported for 6 months.

  • Type: optional

  • Example:

    java.fallback   openjdk17

5.9.5.2. java PortGroup Sugar

Portfiles using PortGroup java do not need to define the following variables:

configure.env, build.env, destroot.env

Default: JAVA_HOME=(detected value)

5.9.6. PortGroup perl5

PortGroup perl5 allows for efficient porting of perl modules and other perl open source software.

5.9.6.1. perl5 PortGroup Specific Keywords

Portfiles using the perl5 PortGroup allow for port authors to set the following keywords in addition to the general Portfile keywords.

perl5.setup

This keyword sets the ${distfile} and ${version}.

  • Type: required

  • Example:

    perl5.setup          Net-Telnet 3.03
perl5.use_module_build

Perl modules are ordinarily assumed to be built with ExtUtils::MakeMaker. Use this keyword if a module must be built using Module::Build instead.

  • Type: optional

  • Example:

    perl5.use_module_build

5.9.6.2. perl5 PortGroup Sugar

Portfiles using PortGroup perl5 do not need to define the following variables:

categories

Default: perl

master_sites

Default: perl_cpan:${perl5.cpandir}

depends_lib

Default: perl5.26

use_configure

Default: no

5.9.6.3. perl5 PortGroup Specific Variables

When the perl5 PortGroup is declared within a Portfile, the following variables are provided during port install.

perl5.version

The MacPorts Perl version.

perl5.bin

The Perl binary path (i.e., ${prefix}/bin/perl).

perl5.lib

Path to the Perl vendor directory.

perl5.archlib

Path to the Perl architecture-dependent modules directory.

5.9.7. PortGroup python

PortGroup python allows for efficient porting of python-based open source software.

5.9.7.1. python PortGroup Specific Keywords

Portfiles using the python PortGroup allow for port authors to set the following keywords in addition to the general Portfile keywords.

python.versions

Defines the python versions supported by this port. If the port name starts with py-, then a subport will be defined for each version in the list. For example, if a port named py-foo declares python.versions 39 310, subports py39-foo and py310-foo will be created, and will depend on python39 and python310, respectively.

If the port name does not start with py-, it is interpreted as an application written in python rather than a python module. In this case, no subports are defined, and python.versions defaults to the value of python.default_version, which must be set. For example, if a port named mercurial sets python.default_version 310, then python.versions will automatically be set to 310, and a dependency on python310 will be added.

  • Type: required for modules, optional for apps

  • Example:

    python.versions     38 39 310
python.default_version

For modules (i.e., name starts with py-), this sets the subport that will be installed if the user asks to install py-foo rather than, e.g., py39-foo or py310-foo. If not explicitly set, a reasonable default is chosen from the list in python.versions.

For applications (i.e., name does not start with py-), this chooses which version of python to use, and must be set. It can be changed in variants if desired.

  • Type: required for apps, optional for modules

  • Example:

    python.default_version     310
python.pep517

If set to yes, the port will be built as per PEP 517. Dependencies on appropriate front end tools will be added automatically. This is supported when using Python 3.6 or later, though the supporting module ports for 3.6 and other EOL Python versions may be removed in future.

If set to no, the port will be built with the traditional distutils/setuptools setup.py commands.

  • Type: optional

  • Default (Python >= 3.7): yes

    Default (Python <= 3.6): no

  • Example:

    python.pep517     yes
python.pep517_backend

This can be set to the name of the PEP 517 build back-end used by the port. If python.pep517 is set to yes, dependencies on the ports that provide the specified back-end will be added automatically. Currently supported values are setuptools, flit, poetry, hatch, maturin, and meson. Clearing this option or setting it to an unsupported value will result in no back-end dependencies being added.

  • Type: optional

  • Default: setuptools

  • Example:

    python.pep517_backend     flit
python.test_framework

This can be set to the name of testing framework used by the port. If test.run is set to yes, dependencies on the port that provides the specified framework will be added automatically. Currently supported values are pytest, nose, and unittest. Clearing this option or setting it to an unsupported value will result in no framework dependency being added.

  • Type: optional

  • Default: pytest

  • Example:

    python.test_framework     nose
python.add_dependencies

If set to yes, a dependency on a python interpreter will be added as per python.version, and if python.pep517 is also set to yes, dependencies on appropriate front- and back-end tools will also be added.

If set to no, the portgroup will not add any dependencies, and all required dependencies need to be declared in the Portfile.

  • Type: optional

  • Default: yes

  • Example:

    python.add_dependencies     no
python.link_binaries

When yes (the default), tells the PortGroup to automatically link any executable binaries installed in the bin/ directory within the framework into ${prefix}/bin.

  • Type: optional

  • Example:

    python.link_binaries     no
python.link_binaries_suffix

Suffix to add to the names of the links created in ${prefix}/bin when ${python.link_binaries} is enabled. Can be cleared if no suffix is desired.

  • Type: optional

  • Default: -${python.branch}

python.add_archflags

When yes (the default), the PortGroup will automatically try to pass the correct arch-specific flags during build time (via the standard CFLAGS, LDFLAGS, etc environment variables). Set this to no and set up those variables in build.env manually if the default does not work.

  • Type: optional

  • Example:

    python.add_archflags     no

5.9.7.2. python PortGroup Specific Variables

When the python PortGroup is declared within a Portfile, the following variables are provided.

python.version

The python version in use in the current subport. This will be one of the versions listed in python.versions.

python.branch

The python version in use in the current subport, in normal dotted notation. For example, if python.version is 310, python.branch will be 3.10.

python.prefix

The prefix in which the current python version is installed. For framework builds, this is ${frameworks_dir}/Python.framework/Versions/${python.branch}, whereas for non-framework builds, it is the same as ${prefix}.

python.bin

The path to the MacPorts Python executable.

python.lib

The Python dynamic library path, i.e., ${python.prefix}/Python (framework builds) or ${prefix}/lib/libpython2.7.dylib (python27).

python.libdir

The path to python's lib directory, i.e., ${python.prefix}/lib/python${python.branch}.

python.include

Path to the Python include directory.

python.pkgd

Path to the Python site-packages directory. (i.e., ${python.prefix}/lib/python${python.branch}/site-packages).

5.9.7.3. python PortGroup Sugar

Portfiles using PortGroup python do not need to define the following variables:

categories

Default: python

depends_lib

Default: port:python${python.version}

use_configure

Default: no

build.cmd

Default (python.pep517 no): ${python.bin} setup.py --no-user-cfg

Default (python.pep517 yes): ${python.bin} -m build --wheel --no-isolation --outdir ${workpath}

build.target

Default (python.pep517 no): build

Default (python.pep517 yes): (empty)

destroot.cmd

Default (python.pep517 no): ${python.bin} setup.py --no-user-cfg

Default (python.pep517 yes): ${python.bin} -m install --verbose

destroot.destdir

Default (python.pep517 no): --prefix=${python.prefix} --root=${destroot}

Default (python.pep517 yes): --destdir ${destroot}

pre-destroot

Default: creates directory ${destroot}${prefix}/share/doc/${subport}/examples.

5.9.8. PortGroup ruby

PortGroup ruby allows for efficient porting of ruby-based open source software.

5.9.8.1. ruby PortGroup Specific Variables

When the ruby PortGroup is declared within a Portfile, the following variables are provided during port install.

ruby.version

The MacPorts Ruby version.

ruby.bin

The Ruby binary location.

ruby.lib

Path to the Ruby vendorlibdir directory (i.e., ${prefix}/lib/ruby/vendor_ruby/${ruby.version})

ruby.arch

The name for the Ruby architecture-dependent directory name (i.e., i686-darwin8.10.1).

ruby.archlib

Path to the Ruby vendor archdir (i.e., ${ruby.lib}/${ruby.arch}).

5.9.9. PortGroup xcode

PortGroup xcode allows for efficient porting of Xcode-based opensource software. A minimum Portfile for PortGroup xcode uses defaults for the configuration, build, and destroot phases. It also defines some values for Xcode-based software.

Using PortGroup xcode is a way to make your port able to tolerate Xcode version updates because the PortGroup is tested against all supported macOS and Xcode versions.

5.9.9.1. xcode PortGroup Specific Keywords

Portfiles using PortGroup xcode allow for port authors to set the following keywords in addition to the general Portfile keywords.

xcode.project

The path relative to ${build.dir} and ${destroot.dir} of the Xcode project. If unset, Xcode Tools should be able to determine it automatically. It usually succeeds if there is only a single project in the directory.

  • Type: optional

  • Default: none

  • Example:

    xcode.project ${name}.xcode
xcode.configuration

Project configuration/buildstyle to use.

  • Type: optional

  • Default: Deployment

  • Example:

    xcode.configuration Main
xcode.target

If present, it overrides build.target and destroot.target.

  • Type: optional

  • Default: none

  • Example:

    xcode.target ${name}
xcode.build.settings

Additional settings passed to the xcodebuild tool during the build phase. These settings should be in the X=Y form.

  • Type: optional

  • Default: none

  • Example:

    xcode.build.settings FRAMEWORK_SEARCH_PATHS=${frameworks_dir}
xcode.destroot.type

Type of project that will be installed. This tells the PortGroup xcode how to destroot the project. Correct values are application and framework.

  • Type: optional

  • Default: application

  • Example:

    xcode.destroot.type framework
xcode.destroot.path

Where to install the build product.

  • Type: optional

  • Default: ${frameworks_dir} or ${applications_dir} depending on xcode.destroot.type.

xcode.destroot.settings

Additional settings passed to the xcodebuild tool during the destroot phase. These settings should be in the X=Y form.

  • Type: optional

  • Default: none

  • Example:

    xcode.destroot.settings SKIP_INSTALL=NO
xcode.universal.settings

Settings passed to the xcodebuild tool when the +universal variant is selected. These settings should be in the X=Y form.

  • Type: optional

  • Default: ARCHS="${universal_archs}" MACOSX_DEPLOYMENT_TARGET=${universal_target}

xcode.universal.sdk

SDK to use when the +universal variant is selected. The argument may be an absolute path to an SDK, or the canonical name of an SDK.

  • Type: optional

  • Default: ${universal_sysroot}

5.9.9.2. xcode PortGroup Sugar

Portfiles using the PortGroup xcode do not need to define the following variables:

categories

Default: aqua

platforms

Default: macosx

use_configure

Default: no

5.9.9.3. Portfile-Phase Keywords Affecting the PortGroup xcode

The following Portfile phase keywords affect the PortGroup xcode in a unique way. In most cases, you will not need to set any of these keywords in the Portfile. See portfile-phase(7)

build.cmd

Default: ${xcodebuildcmd}.

build.target

Default: ""

This variable will be ignored if xcode.target is set.

build.args

Default: build

destroot.cmd

Default: ${xcodebuildcmd}

destroot.target

Default: ""

This variable will be ignored if xcode.target is set.