# Chapter 5. Configuring the Makefile

This translation may be out of date. To help with the translations please access the FreeBSD translations instance.

Configuring the Makefile is pretty simple, and again we suggest looking at existing examples before starting. Also, there is a sample Makefile in this handbook, so take a look and please follow the ordering of variables and sections in that template to make the port easier for others to read.

Consider these problems in sequence during the design of the new Makefile:

## 5.1. The Original Source

Does it live in `DISTDIR` as a standard `gzip`ped tarball named something like foozolix-1.2.tar.gz? If so, go on to the next step. If not, the distribution file format might require overriding one or more of `DISTVERSION`, `DISTNAME`, `EXTRACT_CMD`, `EXTRACT_BEFORE_ARGS`, `EXTRACT_AFTER_ARGS`, `EXTRACT_SUFX`, or `DISTFILES`.

In the worst case, create a custom `do-extract` target to override the default. This is rarely, if ever, necessary.

## 5.2. Naming

The first part of the port’s Makefile names the port, describes its version number, and lists it in the correct category.

### 5.2.1. `PORTNAME`

Set `PORTNAME` to the base name of the software. It is used as the base for the FreeBSD package, and for `DISTNAME`.

| The package name must be unique across the entire ports tree. Make sure that the `PORTNAME` is not already in use by an existing port, and that no other port already has the same `PKGBASE`. If the name has already been used, add either `PKGNAMEPREFIX` or `PKGNAMESUFFIX`.

### 5.2.2. Versions, `DISTVERSION` or `PORTVERSION`

Set `DISTVERSION` to the version number of the software.

`PORTVERSION` is the version used for the FreeBSD package. It will be automatically derived from `DISTVERSION` to be compatible with FreeBSD’s package versioning scheme. If the version contains letters, it might be needed to set `PORTVERSION` and not `DISTVERSION`.

| Only one of `PORTVERSION` and `DISTVERSION` can be set at a time.

From time to time, some software will use a version scheme that is not compatible with how `DISTVERSION` translates in `PORTVERSION`.

| When updating a port, it is possible to use pkg-version(8)'s `-t` argument to check if the new version is greater or lesser than before. See Using pkg-version(8) to Compare Versions.

例 1. Using pkg-version(8) to Compare Versions

`pkg version -t` takes two versions as arguments, it will respond with `<`, `=` or `>` if the first version is less, equal, or more than the second version, respectively.

    % pkg version -t 1.2 1.3
    < (1)
    % pkg version -t 1.2 1.2
    = (2)
    % pkg version -t 1.2 1.2.0
    = (3)
    % pkg version -t 1.2 1.2.p1
    > (4)
    % pkg version -t 1.2.a1 1.2.b1
    < (5)
    % pkg version -t 1.2 1.2p1
    < (6)

1 | `1.2` is before `1.3`.
2 | `1.2` and `1.2` are equal as they have the same version.
3 | `1.2` and `1.2.0` are equal as nothing equals zero.
4 | `1.2` is after `1.2.p1` as `.p1`, think "pre-release 1".
5 | `1.2.a1` is before `1.2.b1`, think "alpha" and "beta", and `a` is before `b`.
6 | `1.2` is before `1.2p1` as `2p1`, think "2, patch level 1" which is a version after any `2.X` but before `3`.

In here, the `a`, `b`, and `p` are used as if meaning "alpha", "beta" or "pre-release" and "patch level", but they are only letters and are sorted alphabetically, so any letter can be used, and they will be sorted appropriately.

表 1. Examples of `DISTVERSION` and the Derived `PORTVERSION`
DISTVERSION | PORTVERSION
--- | ---
0.7.1d | 0.7.1.d
10Alpha3 | 10.a3
3Beta7-pre2 | 3.b7.p2
8:f_17 | 8f.17

例 2. Using `DISTVERSION`

When the version only contains numbers separated by dots, dashes or underscores, use `DISTVERSION`.

    PORTNAME=   nekoto
    DISTVERSION=	1.2-4

It will generate a `PORTVERSION` of `1.2.4`.

例 3. Using `DISTVERSION` When the Version Starts with a Letter or a Prefix

When the version starts or ends with a letter, or a prefix or a suffix that is not part of the version, use `DISTVERSIONPREFIX`, `DISTVERSION`, and `DISTVERSIONSUFFIX`.

If the version is `v1.2-4`:

    PORTNAME=   nekoto
    DISTVERSIONPREFIX=  v
    DISTVERSION=	1_2_4

Some of the time, projects using GitHub will use their name in their versions. For example, the version could be `nekoto-1.2-4`:

    PORTNAME=   nekoto
    DISTVERSIONPREFIX=  nekoto-
    DISTVERSION=	1.2_4

Those projects also sometimes use some string at the end of the version, for example, `1.2-4_RELEASE`:

    PORTNAME=   nekoto
    DISTVERSION=	1.2-4
    DISTVERSIONSUFFIX=  _RELEASE

Or they do both, for example, `nekoto-1.2-4_RELEASE`:

    PORTNAME=   nekoto
    DISTVERSIONPREFIX=  nekoto-
    DISTVERSION=	1.2-4
    DISTVERSIONSUFFIX=  _RELEASE

`DISTVERSIONPREFIX` and `DISTVERSIONSUFFIX` will not be used while constructing `PORTVERSION`, but only used in `DISTNAME`.

All will generate a `PORTVERSION` of `1.2.4`.

例 4. Using `DISTVERSION` When the Version Contains Letters Meaning "alpha", "beta", or "pre-release"

When the version contains numbers separated by dots, dashes or underscores, and letters are used to mean "alpha", "beta" or "pre-release", which is, before the version without the letters, use `DISTVERSION`.

    PORTNAME=   nekoto
    DISTVERSION=	1.2-pre4

    PORTNAME=   nekoto
    DISTVERSION=	1.2p4

Both will generate a `PORTVERSION` of `1.2.p4` which is before than 1.2. pkg-version(8) can be used to check that fact:

    % pkg version -t 1.2.p4 1.2
    <

例 5. Not Using `DISTVERSION` When the Version Contains Letters Meaning "Patch Level"

When the version contains letters that are not meant as "alpha", "beta", or "pre", but more in a "patch level", and meaning after the version without the letters, use `PORTVERSION`.

    PORTNAME=   nekoto
    PORTVERSION=	1.2p4

In this case, using `DISTVERSION` is not possible because it would generate a version of `1.2.p4` which would be before `1.2` and not after. pkg-version(8) will verify this:

    % pkg version -t 1.2 1.2.p4
    > (1)
    % pkg version -t 1.2 1.2p4
    < (2)

1 | `1.2` is after `1.2.p4`, which is wrong in this case.
2 | `1.2` is before `1.2p4`, which is what was needed.

For some more advanced examples of setting `PORTVERSION`, when the software’s versioning is really not compatible with FreeBSD’s, or `DISTNAME` when the distribution file does not contain the version itself, see `DISTNAME`.

### 5.2.3. `PORTREVISION` and `PORTEPOCH`

#### 5.2.3.1. `PORTREVISION`

`PORTREVISION` is a monotonically increasing value which is reset to 0 with every increase of `DISTVERSION`, typically every time there is a new official vendor release. If `PORTREVISION` is non-zero, the value is appended to the package name. Changes to `PORTREVISION` are used by automated tools like pkg-version(8) to determine that a new package is available.

`PORTREVISION` must be increased each time a change is made to the port that changes the generated package in any way. That includes changes that only affect a package built with non-default options.

Examples of when `PORTREVISION` must be bumped:

- Addition of patches to correct security vulnerabilities, bugs, or to add new functionality to the port.

- Changes to the port Makefile to enable or disable compile-time options in the package.

- Changes in the packing list or the install-time behavior of the package. For example, a change to a script which generates initial data for the package, like ssh(1) host keys.

- Version bump of a port’s shared library dependency (in this case, someone trying to install the old package after installing a newer version of the dependency will fail since it will look for the old libfoo.x instead of libfoo.(x+1)).

- Silent changes to the port distfile which have significant functional differences. For example, changes to the distfile requiring a correction to distinfo with no corresponding change to `DISTVERSION`, where a `diff -ru` of the old and new versions shows non-trivial changes to the code.

Examples of changes which do not require a `PORTREVISION` bump:

- Style changes to the port skeleton with no functional change to what appears in the resulting package.

- Changes to `MASTER_SITES` or other functional changes to the port which do not affect the resulting package.

- Trivial patches to the distfile such as correction of typos, which are not important enough that users of the package have to go to the trouble of upgrading.

- Build fixes which cause a package to become compilable where it was previously failing. As long as the changes do not introduce any functional change on any other platforms on which the port did previously build. Since `PORTREVISION` reflects the content of the package, if the package was not previously buildable then there is no need to increase `PORTREVISION` to mark a change.

A rule of thumb is to decide whether a change committed to a port is something which some people would benefit from having. Either because of an enhancement, fix, or by virtue that the new package will actually work at all. Then weigh that against that fact that it will cause everyone who regularly updates their ports tree to be compelled to update. If yes, `PORTREVISION` must be bumped.

| People using binary packages will never see the update if `PORTREVISION` is not bumped. Without increasing `PORTREVISION`, the package builders have no way to detect the change and thus, will not rebuild the package.

#### 5.2.3.2. `PORTEPOCH`

From time to time a software vendor or FreeBSD porter will do something silly and release a version of their software which is actually numerically less than the previous version. An example of this is a port which goes from foo-20000801 to foo-1.0 (the former will be incorrectly treated as a newer version since 20000801 is a numerically greater value than 1).

| The results of version number comparisons are not always obvious. `pkg version` (see pkg-version(8)) can be used to test the comparison of two version number strings. For example:
    % pkg version -t 0.031 0.29
    >
The `>` output indicates that version 0.031 is considered greater than version 0.29, which may not have been obvious to the porter.

In situations such as this, `PORTEPOCH` must be increased. If `PORTEPOCH` is nonzero it is appended to the package name as described in section 0 above. `PORTEPOCH` must never be decreased or reset to zero, because that would cause comparison to a package from an earlier epoch to fail. For example, the package would not be detected as out of date. The new version number, `1.0,1` in the above example, is still numerically less than the previous version, 20000801, but the `,1` suffix is treated specially by automated tools and found to be greater than the implied suffix `,0` on the earlier package.

Dropping or resetting `PORTEPOCH` incorrectly leads to no end of grief. If the discussion above was not clear enough, please consult the FreeBSD ports 郵遞論壇.

It is expected that `PORTEPOCH` will not be used for the majority of ports, and that sensible use of `DISTVERSION`, or that use `PORTVERSION` carefully, can often preempt it becoming necessary if a future release of the software changes the version structure. However, care is needed by FreeBSD porters when a vendor release is made without an official version number - such as a code "snapshot" release. The temptation is to label the release with the release date, which will cause problems as in the example above when a new "official" release is made.

For example, if a snapshot release is made on the date `20000917`, and the previous version of the software was version `1.2`, do not use `20000917` for `DISTVERSION`. The correct way is a `DISTVERSION` of `1.2.20000917`, or similar, so that the succeeding release, say `1.3`, is still a numerically greater value.

#### 5.2.3.3. Example of `PORTREVISION` and `PORTEPOCH` Usage

The `gtkmumble` port, version `0.10`, is committed to the ports collection:

    PORTNAME=	gtkmumble
    DISTVERSION=	0.10

`PKGNAME` becomes `gtkmumble-0.10`.

A security hole is discovered which requires a local FreeBSD patch. `PORTREVISION` is bumped accordingly.

    PORTNAME=	gtkmumble
    DISTVERSION=	0.10
    PORTREVISION=	1

`PKGNAME` becomes `gtkmumble-0.10_1`

A new version is released by the vendor, numbered `0.2` (it turns out the author actually intended `0.10` to actually mean `0.1.0`, not "what comes after 0.9" - oops, too late now). Since the new minor version `2` is numerically less than the previous version `10`, `PORTEPOCH` must be bumped to manually force the new package to be detected as "newer". Since it is a new vendor release of the code, `PORTREVISION` is reset to 0 (or removed from the Makefile).

    PORTNAME=	gtkmumble
    DISTVERSION=	0.2
    PORTEPOCH=	1

`PKGNAME` becomes `gtkmumble-0.2,1`

The next release is 0.3. Since `PORTEPOCH` never decreases, the version variables are now:

    PORTNAME=	gtkmumble
    DISTVERSION=	0.3
    PORTEPOCH=	1

`PKGNAME` becomes `gtkmumble-0.3,1`

| If `PORTEPOCH` were reset to `0` with this upgrade, someone who had installed the `gtkmumble-0.10_1` package would not detect the `gtkmumble-0.3` package as newer, since `3` is still numerically less than `10`. Remember, this is the whole point of `PORTEPOCH` in the first place.

### 5.2.4. `PKGNAMEPREFIX` and `PKGNAMESUFFIX`

Two optional variables, `PKGNAMEPREFIX` and `PKGNAMESUFFIX`, are combined with `PORTNAME` and `PORTVERSION` to form `PKGNAME` as `${PKGNAMEPREFIX}${PORTNAME}${PKGNAMESUFFIX}-${PORTVERSION}`. Make sure this conforms to our guidelines for a good package name. In particular, the use of a hyphen (`-`) in `PORTVERSION` is not allowed. Also, if the package name has the language- or the -compiled.specifics part (see below), use `PKGNAMEPREFIX` and `PKGNAMESUFFIX`, respectively. Do not make them part of `PORTNAME`.

### 5.2.5. Package Naming Conventions

These are the conventions to follow when naming packages. This is to make the package directory easy to scan, as there are already thousands of packages and users are going to turn away if they hurt their eyes!

Package names take the form of language_region-name-compiled.specifics-version.numbers.

The package name is defined as `${PKGNAMEPREFIX}${PORTNAME}${PKGNAMESUFFIX}-${PORTVERSION}`. Make sure to set the variables to conform to that format.

language_region-

  FreeBSD strives to support the native language of its users. The language- part is a two letter abbreviation of the natural language defined by ISO-639 when the port is specific to a certain language. Examples are `ja` for Japanese, `ru` for Russian, `vi` for Vietnamese, `zh` for Chinese, `ko` for Korean and `de` for German.

  If the port is specific to a certain region within the language area, add the two letter country code as well. Examples are `en_US` for US English and `fr_CH` for Swiss French.

  The language- part is set in `PKGNAMEPREFIX`.

name

  Make sure that the port’s name and version are clearly separated and placed into `PORTNAME` and `DISTVERSION`. The only reason for `PORTNAME` to contain a version part is if the upstream distribution is really named that way, as in the textproc/libxml2 or japanese/kinput2-freewnn ports. Otherwise, `PORTNAME` cannot contain any version-specific information. It is quite normal for several ports to have the same `PORTNAME`, as the www/apache* ports do; in that case, different versions (and different index entries) are distinguished by `PKGNAMEPREFIX` and `PKGNAMESUFFIX` values.

  There is a tradition of naming `Perl 5` modules by prepending `p5-` and converting the double-colon separator to a hyphen. For example, the `Data::Dumper` module becomes `p5-Data-Dumper`.

-compiled.specifics

  If the port can be built with different hardcoded defaults (usually part of the directory name in a family of ports), the -compiled.specifics part states the compiled-in defaults. The hyphen is optional. Examples are paper size and font units.

  The -compiled.specifics part is set in `PKGNAMESUFFIX`.

-version.numbers

  The version string follows a dash (`-`) and is a period-separated list of integers and single lowercase alphabetics. In particular, it is not permissible to have another dash inside the version string. The only exception is the string `pl` (meaning "patchlevel"), which can be used only when there are no major and minor version numbers in the software. If the software version has strings like "alpha", "beta", "rc", or "pre", take the first letter and put it immediately after a period. If the version string continues after those names, the numbers follow the single alphabet without an extra period between them (for example, `1.0b2`).

  The idea is to make it easier to sort ports by looking at the version string. In particular, make sure version number components are always delimited by a period, and if the date is part of the string, use the `dyyyy.mm.dd` format, not `dd.mm.yyyy` or the non-Y2K compliant `yy.mm.dd` format. It is important to prefix the version with a letter, here `d` (for date), in case a release with an actual version number is made, which would be numerically less than `yyyy`.

| Package name must be unique among all of the ports tree, check that there is not already a port with the same `PORTNAME` and if there is add one of `PKGNAMEPREFIX` or `PKGNAMESUFFIX`.

Here are some (real) examples on how to convert the name as called by the software authors to a suitable package name, for each line, only one of `DISTVERSION` or `PORTVERSION` is set in, depending on which would be used in the port’s Makefile:

表 2. Package Naming Examples
Distribution Name | PKGNAMEPREFIX | PORTNAME | PKGNAMESUFFIX | DISTVERSION | PORTVERSION | Reason or comment
--- | --- | --- | --- | --- | --- | ---
mule-2.2.2 | (empty) | mule | (empty) | 2.2.2 |  | No changes required
mule-1.0.1 | (empty) | mule | 1 | 1.0.1 |  | This is version 1 of mule, and version 2 already exists
EmiClock-1.0.2 | (empty) | emiclock | (empty) | 1.0.2 |  | No uppercase names for single programs
rdist-1.3alpha | (empty) | rdist | (empty) | 1.3alpha |  | Version will be `1.3.a`
es-0.9-beta1 | (empty) | es | (empty) | 0.9-beta1 |  | Version will be `0.9.b1`
mailman-2.0rc3 | (empty) | mailman | (empty) | 2.0rc3 |  | Version will be `2.0.r3`
v3.3beta021.src | (empty) | tiff | (empty) |  | 3.3 | What the heck was that anyway?
tvtwm | (empty) | tvtwm | (empty) |  | p11 | No version in the filename, use what upstream says it is
piewm | (empty) | piewm | (empty) | 1.0 |  | No version in the filename, use what upstream says it is
xvgr-2.10pl1 | (empty) | xvgr | (empty) |  | 2.10.pl1 | In that case, `pl1` means patch level, so using DISTVERSION is not possible.
gawk-2.15.6 | ja- | gawk | (empty) | 2.15.6 |  | Japanese language version
psutils-1.13 | (empty) | psutils | -letter | 1.13 |  | Paper size hardcoded at package build time
pkfonts | (empty) | pkfonts | 300 | 1.0 |  | Package for 300dpi fonts

If there is absolutely no trace of version information in the original source and it is unlikely that the original author will ever release another version, just set the version string to `1.0` (like the `piewm` example above). Otherwise, ask the original author or use the date string the source file was released on (`dyyyy.mm.dd`, or `dyyyymmdd`) as the version.

| Use any letter. Here, `d` here stands for date, if the source is a Git repository, `g` followed by the commit date is commonly used, using `s` for snapshot is also common.

## 5.3. Categorization

### 5.3.1. `CATEGORIES`

When a package is created, it is put under /usr/ports/packages/All and links are made from one or more subdirectories of /usr/ports/packages. The names of these subdirectories are specified by the variable `CATEGORIES`. It is intended to make life easier for the user when he is wading through the pile of packages on the FTP site or the CDROM. Please take a look at the current list of categories and pick the ones that are suitable for the port.

This list also determines where in the ports tree the port is imported. If there is more than one category here, the port files must be put in the subdirectory with the name of the first category. See below for more discussion about how to pick the right categories.

### 5.3.2. Current List of Categories

Here is the current list of port categories. Those marked with an asterisk (`*`) are virtual categories-those that do not have a corresponding subdirectory in the ports tree. They are only used as secondary categories, and only for search purposes.

| For non-virtual categories, there is a one-line description in `COMMENT` in that subdirectory’s Makefile.

Category | Description | Notes
--- | --- | ---
accessibility | Ports to help disabled users. |
afterstep`*` | Ports to support the AfterStep window manager. |
arabic | Arabic language support. |
archivers | Archiving tools. |
astro | Astronomical ports. |
audio | Sound support. |
benchmarks | Benchmarking utilities. |
biology | Biology-related software. |
cad | Computer aided design tools. |
chinese | Chinese language support. |
comms | Communication software. | Mostly software to talk to the serial port.
converters | Character code converters. |
databases | Databases. |
deskutils | Things that used to be on the desktop before computers were invented. |
devel | Development utilities. | Do not put libraries here just because they are libraries. They should not be in this category unless they truly do not belong anywhere else.
dns | DNS-related software. |
docs`*` | Meta-ports for FreeBSD documentation. |
editors | General editors. | Specialized editors go in the section for those tools. For example, a mathematical-formula editor will go in math, and have editors as a second category.
education`*` | Education-related software. | This includes applications, utilities, or games primarily or substantially designed to help the user learn a specific topic or study in general. It also includes course-writing applications, course-delivery applications, and classroom or school management applications
elisp`*` | Emacs-lisp ports. |
emulators | Emulators for other operating systems. | Terminal emulators do not belong here. X-based ones go to x11 and text-based ones to either comms or misc, depending on the exact functionality.
enlightenment`*` | Ports related to the Enlightenment window manager. |
finance | Monetary, financial and related applications. |
french | French language support. |
ftp | FTP client and server utilities. | If the port speaks both FTP and HTTP, put it in ftp with a secondary category of www.
games | Games. |
geography`*` | Geography-related software. |
german | German language support. |
gnome`*` | Ports from the GNOME Project. |
gnustep`*` | Software related to the GNUstep desktop environment. |
graphics | Graphics utilities. |
hamradio`*` | Software for amateur radio. |
haskell`*` | Software related to the Haskell language. |
hebrew | Hebrew language support. |
hungarian | Hungarian language support. |
irc | Internet Relay Chat utilities. |
japanese | Japanese language support. |
java | Software related to the Java™ language. | The java category must not be the only one for a port. Save for ports directly related to the Java language, porters are also encouraged not to use java as the main category of a port.
kde`*` | Ports from the KDE Project (generic). |
kde-applications`*` | Applications from the KDE Project. |
kde-frameworks`*` | Add-on libraries from the KDE Project for programming with Qt. |
kde-plasma`*` | Desktop from the KDE Project. |
kld`*` | Kernel loadable modules. |
korean | Korean language support. |
lang | Programming languages. |
linux`*` | Linux applications and support utilities. |
lisp`*` | Software related to the Lisp language. |
mail | Mail software. |
mate`*` | Ports related to the MATE desktop environment, a fork of GNOME 2. |
math | Numerical computation software and other utilities for mathematics. |
mbone`*` | MBone applications. |
misc | Miscellaneous utilities | Things that do not belong anywhere else. If at all possible, try to find a better category for the port than `misc`, as ports tend to be overlooked in here.
multimedia | Multimedia software. |
net | Miscellaneous networking software. |
net-im | Instant messaging software. |
net-mgmt | Networking management software. |
net-p2p | Peer to peer network applications. |
net-vpn`*` | Virtual Private Network applications. |
news | USENET news software. |
parallel`*` | Applications dealing with parallelism in computing. |
pear`*` | Ports related to the Pear PHP framework. |
perl5`*` | Ports that require Perl version 5 to run. |
plan9`*` | Various programs from Plan9. |
polish | Polish language support. |
ports-mgmt | Ports for managing, installing and developing FreeBSD ports and packages. |
portuguese | Portuguese language support. |
print | Printing software. | Desktop publishing tools (previewers, etc.) belong here too.
python`*` | Software related to the Python language. |
ruby`*` | Software related to the Ruby language. |
rubygems`*` | Ports of RubyGems packages. |
russian | Russian language support. |
scheme`*` | Software related to the Scheme language. |
science | Scientific ports that do not fit into other categories such as astro, biology and math. |
security | Security utilities. |
shells | Command line shells. |
spanish`*` | Spanish language support. |
sysutils | System utilities. |
tcl`*` | Ports that use Tcl to run. |
textproc | Text processing utilities. | It does not include desktop publishing tools, which go to print.
tk`*` | Ports that use Tk to run. |
ukrainian | Ukrainian language support. |
vietnamese | Vietnamese language support. |
wayland`*` | Ports to support the Wayland display server. |
windowmaker`*` | Ports to support the Window Maker window manager. |
www | Software related to the World Wide Web. | HTML language support belongs here too.
x11 | The X Window System and friends. | This category is only for software that directly supports the window system. Do not put regular X applications here. Most of them go into other x11-* categories (see below).
x11-clocks | X11 clocks. |
x11-drivers | X11 drivers. |
x11-fm | X11 file managers. |
x11-fonts | X11 fonts and font utilities. |
x11-servers | X11 servers. |
x11-themes | X11 themes. |
x11-toolkits | X11 toolkits. |
x11-wm | X11 window managers. |
xfce`*` | Ports related to the Xfce desktop environment. |
zope`*` | Zope support. |

### 5.3.3. Choosing the Right Category

As many of the categories overlap, choosing which of the categories will be the primary category of the port can be tedious. There are several rules that govern this issue. Here is the list of priorities, in decreasing order of precedence:

- The first category must be a physical category (see above). This is necessary to make the packaging work. Virtual categories and physical categories may be intermixed after that.

- Language specific categories always come first. For example, if the port installs Japanese X11 fonts, then the `CATEGORIES` line would read japanese x11-fonts.

- Specific categories are listed before less-specific ones. For instance, an HTML editor is listed as www editors, not the other way around. Also, do not list net when the port belongs to any of irc, mail, news, security, or www, as net is included implicitly.

- x11 is used as a secondary category only when the primary category is a natural language. In particular, do not put x11 in the category line for X applications.

- Emacs modes are placed in the same ports category as the application supported by the mode, not in editors. For example, an Emacs mode to edit source files of some programming language goes into lang.

- Ports installing loadable kernel modules also have the virtual category kld in their `CATEGORIES` line. This is one of the things handled automatically by adding `USES=kmod`.

- misc does not appear with any other non-virtual category. If there is `misc` with something else in `CATEGORIES`, that means `misc` can safely be deleted and the port placed only in the other subdirectory.

- If the port truly does not belong anywhere else, put it in misc.

If the category is not clearly defined, please put a comment to that effect in the port submission in the bug database so we can discuss it before we import it. As a committer, send a note to the FreeBSD ports 郵遞論壇 so we can discuss it first. Too often, new ports are imported to the wrong category only to be moved right away.

### 5.3.4. Proposing a New Category

As the Ports Collection has grown over time, various new categories have been introduced. New categories can either be virtual categories-those that do not have a corresponding subdirectory in the ports tree- or physical categories-those that do. This section discusses the issues involved in creating a new physical category. Read it thouroughly before proposing a new one.

Our existing practice has been to avoid creating a new physical category unless either a large number of ports would logically belong to it, or the ports that would belong to it are a logically distinct group that is of limited general interest (for instance, categories related to spoken human languages), or preferably both.

The rationale for this is that such a change creates a fair amount of work for both the committers and also for all users who track changes to the Ports Collection. In addition, proposed category changes just naturally seem to attract controversy. (Perhaps this is because there is no clear consensus on when a category is "too big", nor whether categories should lend themselves to browsing (and thus what number of categories would be an ideal number), and so forth.)

Here is the procedure:

1. Propose the new category on FreeBSD ports 郵遞論壇. Include a detailed rationale for the new category, including why the existing categories are not sufficient, and the list of existing ports proposed to move. (If there are new ports pending in Bugzilla that would fit this category, list them too.) If you are the maintainer and/or submitter, respectively, mention that as it may help the case.

2. Participate in the discussion.

3. If it seems that there is support for the idea, file a PR which includes both the rationale and the list of existing ports that need to be moved. Ideally, this PR would also include these patches:

   - Makefiles for the new ports once they are repocopied

   - Makefile for the new category

   - Makefile for the old ports' categories

   - Makefiles for ports that depend on the old ports

   - (for extra credit, include the other files that have to change, as per the procedure in the Committer’s Guide.)

4. Since it affects the ports infrastructure and involves moving and patching many ports but also possibly running regression tests on the build cluster, assign the PR to the Ports Management Team <portmgr@FreeBSD.org>.

5. If that PR is approved, a committer will need to follow the rest of the procedure that is outlined in the Committer’s Guide.

Proposing a new virtual category is similar to the above but much less involved, since no ports will actually have to move. In this case, the only patches to include in the PR would be those to add the new category to `CATEGORIES` of the affected ports.

### 5.3.5. Proposing Reorganizing All the Categories

Occasionally someone proposes reorganizing the categories with either a 2-level structure, or some other kind of keyword structure. To date, nothing has come of any of these proposals because, while they are very easy to make, the effort involved to retrofit the entire existing ports collection with any kind of reorganization is daunting to say the very least. Please read the history of these proposals in the mailing list archives before posting this idea. Furthermore, be prepared to be challenged to offer a working prototype.

## 5.4. The Distribution Files

The second part of the Makefile describes the files that must be downloaded to build the port, and where they can be downloaded.

### 5.4.1. `DISTNAME`

`DISTNAME` is the name of the port as called by the authors of the software. `DISTNAME` defaults to `${PORTNAME}-${DISTVERSIONPREFIX}${DISTVERSION}${DISTVERSIONSUFFIX}`, and if not set, `DISTVERSION` defaults to `${PORTVERSION}` so override `DISTNAME` only if necessary. `DISTNAME` is only used in two places. First, the distribution file list (`DISTFILES`) defaults to `${DISTNAME}${EXTRACT_SUFX}`. Second, the distribution file is expected to extract into a subdirectory named `WRKSRC`, which defaults to work/${DISTNAME}.

Some vendor’s distribution names which do not fit into the `${PORTNAME}-${PORTVERSION}`-scheme can be handled automatically by setting `DISTVERSIONPREFIX`, `DISTVERSION`, and `DISTVERSIONSUFFIX`. `PORTVERSION` will be derived from `DISTVERSION` automatically.

| Only one of `PORTVERSION` and `DISTVERSION` can be set at a time. If `DISTVERSION` does not derive a correct `PORTVERSION`, do not use `DISTVERSION`.

If the upstream version scheme can be derived into a ports-compatible version scheme, set some variable to the upstream version, do not use `DISTVERSION` as the variable name. Set `PORTVERSION` to the computed version based on the variable you created, and set `DISTNAME` accordingly.

If the upstream version scheme cannot easily be coerced into a ports-compatible value, set `PORTVERSION` to a sensible value, and set `DISTNAME` with `PORTNAME` with the verbatim upstream version.

例 6. Deriving `PORTVERSION` Manually

BIND9 uses a version scheme that is not compatible with the ports versions (it has `-` in its versions) and cannot be derived using `DISTVERSION` because after the 9.9.9 release, it will release a "patchlevels" in the form of `9.9.9-P1`. DISTVERSION would translate that into `9.9.9.p1`, which, in the ports versioning scheme means 9.9.9 pre-release 1, which is before 9.9.9 and not after. So `PORTVERSION` is manually derived from an `ISCVERSION` variable to output `9.9.9p1`.

The order into which the ports framework, and pkg, will sort versions is checked using the `-t` argument of pkg-version(8):

    % pkg version -t 9.9.9 9.9.9.p1
    > (1)
    % pkg version -t 9.9.9 9.9.9p1
    < (2)

1 | The `>` sign means that the first argument passed to `-t` is greater than the second argument. `9.9.9` is after `9.9.9.p1`.
2 | The `<` sign means that the first argument passed to `-t` is less than the second argument. `9.9.9` is before `9.9.9p1`.

In the port Makefile, for example dns/bind99, it is achieved by:

    PORTNAME=	bind
    PORTVERSION=	${ISCVERSION:S/-P/P/:S/b/.b/:S/a/.a/:S/rc/.rc/}
    CATEGORIES=	dns net
    MASTER_SITES=	ISC/bind9/${ISCVERSION}
    PKGNAMESUFFIX=	99
    DISTNAME=	${PORTNAME}-${ISCVERSION}

    MAINTAINER=	mat@FreeBSD.org
    COMMENT=	BIND DNS suite with updated DNSSEC and DNS64

    LICENSE=	ISCL

    # ISC releases things like 9.8.0-P1 or 9.8.1rc1, which our versioning does not like
    ISCVERSION=	9.9.9-P6

Define upstream version in `ISCVERSION`, with a comment saying why it is needed. Use `ISCVERSION` to get a ports-compatible `PORTVERSION`. Use `ISCVERSION` directly to get the correct URL for fetching the distribution file. Use `ISCVERSION` directly to name the distribution file.

例 7. Derive `DISTNAME` from `PORTVERSION`

From time to time, the distribution file name has little or no relation to the version of the software.

In comms/kermit, only the last element of the version is present in the distribution file:

    PORTNAME=	kermit
    PORTVERSION=	9.0.304
    CATEGORIES=	comms ftp net
    MASTER_SITES=	ftp://ftp.kermitproject.org/kermit/test/tar/
    DISTNAME=	cku${PORTVERSION:E}-dev20

The `:E` make(1) modifier returns the suffix of the variable, in this case, `304`. The distribution file is correctly generated as `cku304-dev20.tar.gz`.

例 8. Exotic Case 1

Sometimes, there is no relation between the software name, its version, and the distribution file it is distributed in.

From audio/libworkman:

    PORTNAME=       libworkman
    PORTVERSION=    1.4
    CATEGORIES=     audio
    MASTER_SITES=   LOCAL/jim
    DISTNAME=       ${PORTNAME}-1999-06-20

例 9. Exotic Case 2

In comms/librs232, the distribution file is not versioned, so using `DIST_SUBDIR` is needed:

    PORTNAME=       librs232
    PORTVERSION=    20160710
    CATEGORIES=     comms
    MASTER_SITES=   http://www.teuniz.net/RS-232/
    DISTNAME=       RS-232
    DIST_SUBDIR=	${PORTNAME}-${PORTVERSION}

| `PKGNAMEPREFIX` and `PKGNAMESUFFIX` do not affect `DISTNAME`. Also note that if `WRKSRC` is equal to ${WRKDIR}/${DISTNAME} while the original source archive is named something other than `${PORTNAME}-${PORTVERSION}${EXTRACT_SUFX}`, leave `DISTNAME` alone- defining only `DISTFILES` is easier than both `DISTNAME` and `WRKSRC` (and possibly `EXTRACT_SUFX`).

### 5.4.2. `MASTER_SITES`

Record the directory part of the FTP/HTTP-URL pointing at the original tarball in `MASTER_SITES`. Do not forget the trailing slash (/)!

The `make` macros will try to use this specification for grabbing the distribution file with `FETCH` if they cannot find it already on the system.

It is recommended that multiple sites are included on this list, preferably from different continents. This will safeguard against wide-area network problems.

| `MASTER_SITES` must not be blank. It must point to the actual site hosting the distribution files. It cannot point to web archives, or the FreeBSD distribution files cache sites. The only exception to this rule is ports that do not have any distribution files. For example, meta-ports do not have any distribution files, so `MASTER_SITES` does not need to be set.

#### 5.4.2.1. Using `MASTER_SITE_*` Variables

Shortcut abbreviations are available for popular archives like SourceForge (`SOURCEFORGE`), GNU (`GNU`), or Perl CPAN (`PERL_CPAN`). `MASTER_SITES` can use them directly:

    MASTER_SITES=	GNU/make

The older expanded format still works, but all ports have been converted to the compact format. The expanded format looks like this:

    MASTER_SITES=		${MASTER_SITE_GNU}
    MASTER_SITE_SUBDIR=	make

These values and variables are defined in Mk/bsd.sites.mk. New entries are added often, so make sure to check the latest version of this file before submitting a port.

| For any `MASTER_SITE_FOO` variable, the shorthand `FOO` can be used. For example, use:
    MASTER_SITES=	FOO
If `MASTER_SITE_SUBDIR` is needed, use this:
    MASTER_SITES=	FOO/bar

| Some `MASTER_SITE_*` names are quite long, and for ease of use, shortcuts have been defined:
表 3. Shortcuts for `MASTER_SITE_*` Macros
Macro | Shortcut
--- | ---
`PERL_CPAN` | `CPAN`
`GITHUB` | `GH`
`GITHUB_CLOUD` | `GHC`
`LIBREOFFICE_DEV` | `LODEV`
`NETLIB` | `NL`
`RUBYGEMS` | `RG`
`SOURCEFORGE` | `SF`

#### 5.4.2.2. Magic MASTER_SITES Macros

Several "magic" macros exist for popular sites with a predictable directory structure. For these, just use the abbreviation and the system will choose a subdirectory automatically. For a port named `Stardict`, of version `1.2.3`, and hosted on SourceForge, adding this line:

    MASTER_SITES=	SF

infers a subdirectory named `/project/stardict/stardict/1.2.3`. If the inferred directory is incorrect, it can be overridden:

    MASTER_SITES=	SF/stardict/WyabdcRealPeopleTTS/${PORTVERSION}

This can also be written as

    MASTER_SITES=	SF
    MASTER_SITE_SUBDIR=	stardict/WyabdcRealPeopleTTS/${PORTVERSION}

表 4. Magic `MASTER_SITES` Macros
Macro | Assumed subdirectory
--- | ---
`APACHE_COMMONS_BINARIES` | `${PORTNAME:S,commons-,,}`
`APACHE_COMMONS_SOURCE` | `${PORTNAME:S,commons-,,}`
`APACHE_JAKARTA` | `${PORTNAME:S,-,/,}/source`
`BERLIOS` | `${PORTNAME:tl}.berlios`
`CHEESESHOP` | `source/${DISTNAME:C/(.).*/\1/}/${DISTNAME:C/(.*)-[0-9].*/\1/}`
`CPAN` | `${PORTNAME:C/-.*//}`
`DEBIAN` | `pool/main/${PORTNAME:C/^((lib)?.).*$/\1/}/${PORTNAME}`
`FARSIGHT` | `${PORTNAME}`
`FESTIVAL` | `${PORTREVISION}`
`GCC` | `releases/${DISTNAME}`
`GENTOO` | `distfiles`
`GIMP` | `${PORTNAME}/${PORTVERSION:R}/`
`GH` | `${GH_ACCOUNT}/${GH_PROJECT}/tar.gz/${GH_TAGNAME}?dummy=/`
`GHC` | `${GH_ACCOUNT}/${GH_PROJECT}/`
`GNOME` | `sources/${PORTNAME}/${PORTVERSION:C/^(\.[0-9]).*/\1/}`
`GNU` | `${PORTNAME}`
`GNUPG` | `${PORTNAME}`
`GNU_ALPHA` | `${PORTNAME}`
`HORDE` | `${PORTNAME}`
`LODEV` | `${PORTNAME}`
`MATE` | `${PORTVERSION:C/^(\.[0-9]).*/\1/}`
`MOZDEV` | `${PORTNAME:tl}`
`NL` | `${PORTNAME}`
`QT` | `archive/qt/${PORTVERSION:R}`
`SAMBA` | `${PORTNAME}`
`SAVANNAH` | `${PORTNAME:tl}`
`SF` | `${PORTNAME:tl}/${PORTNAME:tl}/${PORTVERSION}`

### 5.4.3. `USE_GITHUB`

If the distribution file comes from a specific commit or tag on GitHub for which there is no officially released file, there is an easy way to set the right `DISTNAME` and `MASTER_SITES` automatically. These variables are available:

表 5. `USE_GITHUB` Description
Variable | Description | Default
--- | --- | ---
`GH_ACCOUNT` | Account name of the GitHub user hosting the project | `${PORTNAME}`
`GH_PROJECT` | Name of the project on GitHub | `${PORTNAME}`
`GH_TAGNAME` | Name of the tag to download (2.0.1, hash, …​) Using the name of a branch here is incorrect. It is also possible to use the hash of a commit id to do a snapshot. | `${DISTVERSIONPREFIX}${DISTVERSION}${DISTVERSIONSUFFIX}`
`GH_SUBDIR` | When the software needs an additional distribution file to be extracted within `${WRKSRC}`, this variable can be used. See the examples in Fetching Multiple Files from GitHub for more information. | (none)

| Do not use `GH_TUPLE` for the default distribution file, as it has no default.

例 10. Simple Use of `USE_GITHUB`

While trying to make a port for version `1.2.7` of pkg from the FreeBSD user on github, at https://github.com/freebsd/pkg, The Makefile would end up looking like this (slightly stripped for the example):

    PORTNAME=	pkg
    DISTVERSION=	1.2.7

    USE_GITHUB=	yes
    GH_ACCOUNT=	freebsd

It will automatically have `MASTER_SITES` set to `GH` and `WRKSRC` to `${WRKDIR}/pkg-1.2.7`.

例 11. More Complete Use of `USE_GITHUB`

While trying to make a port for the bleeding edge version of pkg from the FreeBSD user on github, at https://github.com/freebsd/pkg, the Makefile ends up looking like this (slightly stripped for the example):

    PORTNAME=	pkg-devel
    DISTVERSION=	1.3.0.a.20140411

    USE_GITHUB=	yes
    GH_ACCOUNT=	freebsd
    GH_PROJECT=	pkg
    GH_TAGNAME=	6dbb17b

It will automatically have `MASTER_SITES` set to `GH` and `WRKSRC` to `${WRKDIR}/pkg-6dbb17b`.

`20140411` is the date of the commit referenced in `GH_TAGNAME`, not the date the Makefile is edited, or the date the commit is made.

例 12. Use of `USE_GITHUB` with `DISTVERSIONPREFIX`

From time to time, `GH_TAGNAME` is a slight variation from `DISTVERSION`. For example, if the version is `1.0.2`, the tag is `v1.0.2`. In those cases, it is possible to use `DISTVERSIONPREFIX` or `DISTVERSIONSUFFIX`:

    PORTNAME=	foo
    DISTVERSIONPREFIX=	v
    DISTVERSION=	1.0.2

    USE_GITHUB=	yes

It will automatically set `GH_TAGNAME` to `v1.0.2`, while `WRKSRC` will be kept to `${WRKDIR}/foo-1.0.2`.

例 13. Using `USE_GITHUB` When Upstream Does Not Use Versions

If there never was a version upstream, do not invent one like `0.1` or `1.0`. Create the port with a `DISTVERSION` of `gYYYYMMDD`, where `g` is for Git, and `YYYYMMDD` represents the date the commit referenced in `GH_TAGNAME`.

    PORTNAME=	bar
    DISTVERSION=	g20140411

    USE_GITHUB=	yes
    GH_TAGNAME=	c472d66b

This creates a versioning scheme that increases over time, and that is still before version `0` (see Using pkg-version(8) to Compare Versions for details on pkg-version(8)):

    % pkg version -t g20140411 0
    <

Which means using `PORTEPOCH` will not be needed in case upstream decides to cut versions in the future.

例 14. Using `USE_GITHUB` to Access a Commit Between Two Versions

If the current version of the software uses a Git tag, and the port needs to be updated to a newer, intermediate version, without a tag, use git-describe(1) to find out the version to use:

    % git describe --tags f0038b1
    v0.7.3-14-gf0038b1

`v0.7.3-14-gf0038b1` can be split into three parts:

`v0.7.3`

  This is the last Git tag that appears in the commit history before the requested commit.

`-14`

  This means that the requested commit, `f0038b1`, is the 14th commit after the `v0.7.3` tag.

`-gf0038b1`

  The `-g` means "Git", and the `f0038b1` is the commit hash that this reference points to.

    PORTNAME=	bar
    DISTVERSIONPREFIX=  v
    DISTVERSION=	0.7.3-14
    DISTVERSIONSUFFIX=  -gf0038b1

    USE_GITHUB=	yes

This creates a versioning scheme that increases over time (well, over commits), and does not conflict with the creation of a `0.7.4` version. (See Using pkg-version(8) to Compare Versions for details on pkg-version(8)):

    % pkg version -t 0.7.3 0.7.3.14
    <
    % pkg version -t 0.7.3.14 0.7.4
    <

If the requested commit is the same as a tag, a shorter description is shown by default. The longer version is equivalent:

    % git describe --tags c66c71d
    v0.7.3

    % git describe --tags --long c66c71d
    v0.7.3-0-gc66c71d

#### 5.4.3.1. Fetching Multiple Files from GitHub

The `USE_GITHUB` framework also supports fetching multiple distribution files from different places in GitHub. It works in a way very similar to Multiple Distribution or Patches Files from Multiple Locations.

Multiple values are added to `GH_ACCOUNT`, `GH_PROJECT`, and `GH_TAGNAME`. Each different value is assigned a group. The main value can either have no group, or the `:DEFAULT` group. A value can be omitted if it is the same as the default as listed in `USE_GITHUB` Description.

`GH_TUPLE` can also be used when there are a lot of distribution files. It helps keep the account, project, tagname, and group information at the same place.

For each group, a `${WRKSRC_group}` helper variable is created, containing the directory into which the file has been extracted. The `${WRKSRC_group}` variables can be used to move directories around during `post-extract`, or add to `CONFIGURE_ARGS`, or whatever is needed so that the software builds correctly.

| The `:group` part must be used for only one distribution file. It is used as a unique key and using it more than once will overwrite the previous values.

| As this is only syntactic sugar above `DISTFILES` and `MASTER_SITES`, the group names must adhere to the restrictions on group names outlined in Multiple Distribution or Patches Files from Multiple Locations

When fetching multiple files from GitHub, sometimes the default distribution file is not fetched from GitHub. To disable fetching the default distribution, set:

    USE_GITHUB=	nodefault

| When using `USE_GITHUB=nodefault`, the Makefile must set `DISTFILES` in its top block. The definition should be:
    DISTFILES=    ${DISTNAME}${EXTRACT_SUFX}

例 15. Use of `USE_GITHUB` with Multiple Distribution Files

From time to time, there is a need to fetch more than one distribution file. For example, when the upstream git repository uses submodules. This can be done easily using groups in the `GH_*` variables:

    PORTNAME=	foo
    DISTVERSION=	1.0.2

    USE_GITHUB=	yes
    GH_ACCOUNT=	bar:icons,contrib
    GH_PROJECT=	foo-icons:icons foo-contrib:contrib
    GH_TAGNAME=	1.0:icons fa579bc:contrib
    GH_SUBDIR=	ext/icons:icons

    CONFIGURE_ARGS=	--with-contrib=${WRKSRC_contrib}

This will fetch three distribution files from github. The default one comes from foo/foo and is version `1.0.2`. The second one, with the `icons` group, comes from bar/foo-icons and is in version `1.0`. The third one comes from bar/foo-contrib and uses the Git commit `fa579bc`. The distribution files are named foo-foo-1.0.2_GH0.tar.gz, bar-foo-icons-1.0_GH0.tar.gz, and bar-foo-contrib-fa579bc_GH0.tar.gz.

All the distribution files are extracted in `${WRKDIR}` in their respective subdirectories. The default file is still extracted in `${WRKSRC}`, in this case, ${WRKDIR}/foo-1.0.2. Each additional distribution file is extracted in `${WRKSRC_group}`. Here, for the `icons` group, it is called `${WRKSRC_icons}` and it contains ${WRKDIR}/foo-icons-1.0. The file with the `contrib` group is called `${WRKSRC_contrib}` and contains `${WRKDIR}/foo-contrib-fa579bc`.

The software’s build system expects to find the icons in a ext/icons subdirectory in its sources, so `GH_SUBDIR` is used. `GH_SUBDIR` makes sure that ext exists, but that ext/icons does not already exist. Then it does this:

    post-extract:
          @${MV} ${WRKSRC_icons} ${WRKSRC}/ext/icons

例 16. Use of `USE_GITHUB` with Multiple Distribution Files Using `GH_TUPLE`

This is functionally equivalent to Use of `USE_GITHUB` with Multiple Distribution Files, but using `GH_TUPLE`:

    PORTNAME=	foo
    DISTVERSION=	1.0.2

    USE_GITHUB=	yes
    GH_TUPLE=	bar:foo-icons:1.0:icons/ext/icons \
    		bar:foo-contrib:fa579bc:contrib

    CONFIGURE_ARGS=	--with-contrib=${WRKSRC_contrib}

Grouping was used in the previous example with `bar:icons,contrib`. Some redundant information is present with `GH_TUPLE` because grouping is not possible.

例 17. How to Use `USE_GITHUB` with Git Submodules?

Ports with GitHub as an upstream repository sometimes use submodules. See git-submodule(1) for more information.

The problem with submodules is that each is a separate repository. As such, they each must be fetched separately.

Using finance/moneymanagerex as an example, its GitHub repository is https://github.com/moneymanagerex/moneymanagerex. It has a .gitmodules file at the root. This file describes all the submodules used in this repository, and lists additional repositories needed. This file will tell what additional repositories are needed:

    [submodule "lib/wxsqlite3"]
    	path = lib/wxsqlite3
    	url = https://github.com/utelle/wxsqlite3.git
    [submodule "3rd/mongoose"]
    	path = 3rd/mongoose
    	url = https://github.com/cesanta/mongoose.git
    [submodule "3rd/LuaGlue"]
    	path = 3rd/LuaGlue
    	url = https://github.com/moneymanagerex/LuaGlue.git
    [submodule "3rd/cgitemplate"]
    	path = 3rd/cgitemplate
    	url = https://github.com/moneymanagerex/html-template.git
    [...]

The only information missing from that file is the commit hash or tag to use as a version. This information is found after cloning the repository:

    % git clone --recurse-submodules https://github.com/moneymanagerex/moneymanagerex.git
    Cloning into 'moneymanagerex'...
    remote: Counting objects: 32387, done.
    [...]
    Submodule '3rd/LuaGlue' (https://github.com/moneymanagerex/LuaGlue.git) registered for path '3rd/LuaGlue'
    Submodule '3rd/cgitemplate' (https://github.com/moneymanagerex/html-template.git) registered for path '3rd/cgitemplate'
    Submodule '3rd/mongoose' (https://github.com/cesanta/mongoose.git) registered for path '3rd/mongoose'
    Submodule 'lib/wxsqlite3' (https://github.com/utelle/wxsqlite3.git) registered for path 'lib/wxsqlite3'
    [...]
    Cloning into '/home/mat/work/freebsd/ports/finance/moneymanagerex/moneymanagerex/3rd/LuaGlue'...
    Cloning into '/home/mat/work/freebsd/ports/finance/moneymanagerex/moneymanagerex/3rd/cgitemplate'...
    Cloning into '/home/mat/work/freebsd/ports/finance/moneymanagerex/moneymanagerex/3rd/mongoose'...
    Cloning into '/home/mat/work/freebsd/ports/finance/moneymanagerex/moneymanagerex/lib/wxsqlite3'...
    [...]
    Submodule path '3rd/LuaGlue': checked out 'c51d11a247ee4d1e9817dfa2a8da8d9e2f97ae3b'
    Submodule path '3rd/cgitemplate': checked out 'cd434eeeb35904ebcd3d718ba29c281a649b192c'
    Submodule path '3rd/mongoose': checked out '2140e5992ab9a3a9a34ce9a281abf57f00f95cda'
    Submodule path 'lib/wxsqlite3': checked out 'fb66eb230d8aed21dec273b38c7c054dcb7d6b51'
    [...]
    % cd moneymanagerex
    % git submodule status
     c51d11a247ee4d1e9817dfa2a8da8d9e2f97ae3b 3rd/LuaGlue (heads/master)
     cd434eeeb35904ebcd3d718ba29c281a649b192c 3rd/cgitemplate (cd434ee)
     2140e5992ab9a3a9a34ce9a281abf57f00f95cda 3rd/mongoose (6.2-138-g2140e59)
     fb66eb230d8aed21dec273b38c7c054dcb7d6b51 lib/wxsqlite3 (v3.4.0)
    [...]

It can also be found on GitHub. Each subdirectory that is a submodule is shown as `directory @ hash`, for example, `mongoose @ 2140e59`.

While getting the information from GitHub seems more straightforward, the information found using `git submodule status` will provide more meaningful information. For example, here, `lib/wxsqlite3`'s commit hash `fb66eb2` correspond to `v3.4.0`. Both can be used interchangeably, but when a tag is available, use it.

Now that all the required information has been gathered, the Makefile can be written (only GitHub-related lines are shown):

    PORTNAME=	moneymanagerex
    DISTVERSIONPREFIX=	v
    DISTVERSION=	1.3.0

    USE_GITHUB=	yes
    GH_TUPLE=	utelle:wxsqlite3:v3.4.0:wxsqlite3/lib/wxsqlite3 \
    		moneymanagerex:LuaGlue:c51d11a:lua_glue/3rd/LuaGlue \
    		moneymanagerex:html-template:cd434ee:html_template/3rd/cgitemplate \
    		cesanta:mongoose:2140e59:mongoose/3rd/mongoose \
    		[...]

### 5.4.4. `USE_GITLAB`

Similar to GitHub, if the distribution file comes from gitlab.com or is hosting the GitLab software, these variables are available for use and might need to be set.

表 6. `USE_GITLAB` Description
Variable | Description | Default
--- | --- | ---
`GL_SITE` | Site name hosting the GitLab project | https://gitlab.com
`GL_ACCOUNT` | Account name of the GitLab user hosting the project | `${PORTNAME}`
`GL_PROJECT` | Name of the project on GitLab | `${PORTNAME}`
`GL_COMMIT` | The commit hash to download. Must be the full 160 bit, 40 character hex sha1 hash. This is a required variable for GitLab. | `(none)`
`GL_SUBDIR` | When the software needs an additional distribution file to be extracted within `${WRKSRC}`, this variable can be used. See the examples in Fetching Multiple Files from GitLab for more information. | (none)

例 18. Simple Use of `USE_GITLAB`

While trying to make a port for version `1.14` of libsignon-glib from the accounts-sso user on gitlab.com, at https://gitlab.com/accounts-sso/libsignon-glib, The Makefile would end up looking like this for fetching the distribution files:

    PORTNAME=	libsignon-glib
    DISTVERSION=	1.14

    USE_GITLAB=	yes
    GL_ACCOUNT=	accounts-sso
    GL_COMMIT=	e90302e342bfd27bc8c9132ab9d0ea3d8723fd03

It will automatically have `MASTER_SITES` set to gitlab.com and `WRKSRC` to `${WRKDIR}/libsignon-glib-e90302e342bfd27bc8c9132ab9d0ea3d8723fd03-e90302e342bfd27bc8c9132ab9d0ea3d8723fd03`.

例 19. More Complete Use of `USE_GITLAB`

A more complete use of the above if port had no versioning and foobar from the foo user on project bar on a self hosted GitLab site `https://gitlab.example.com`, the Makefile ends up looking like this for fetching distribution files:

    PORTNAME=	foobar
    DISTVERSION=	g20170906

    USE_GITLAB=	yes
    GL_SITE=	https://gitlab.example.com
    GL_ACCOUNT=	foo
    GL_PROJECT=	bar
    GL_COMMIT=	9c1669ce60c3f4f5eb43df874d7314483fb3f8a6

It will have `MASTER_SITES` set to `"https://gitlab.example.com"` and `WRKSRC` to `${WRKDIR}/bar-9c1669ce60c3f4f5eb43df874d7314483fb3f8a6-9c1669ce60c3f4f5eb43df874d7314483fb3f8a6`.

| `20170906` is the date of the commit referenced in `GL_COMMIT`, not the date the Makefile is edited, or the date the commit to the FreeBSD ports tree is made.

| `GL_SITE`'s protocol, port and webroot can all be modified in the same variable.

#### 5.4.4.1. Fetching Multiple Files from GitLab

The `USE_GITLAB` framework also supports fetching multiple distribution files from different places from GitLab and GitLab hosted sites. It works in a way very similar to Multiple Distribution or Patches Files from Multiple Locations and Fetching Multiple Files from GitLab.

Multiple values are added to `GL_SITE`, `GL_ACCOUNT`, `GL_PROJECT` and `GL_COMMIT`. Each different value is assigned a group. `USE_GITLAB` Description.

`GL_TUPLE` can also be used when there are a lot of distribution files. It helps keep the site, account, project, commit, and group information at the same place.

For each group, a `${WRKSRC_group}` helper variable is created, containing the directory into which the file has been extracted. The `${WRKSRC_group}` variables can be used to move directories around during `post-extract`, or add to `CONFIGURE_ARGS`, or whatever is needed so that the software builds correctly.

| The `:group` part must be used for only one distribution file. It is used as a unique key and using it more than once will overwrite the previous values.

| As this is only syntactic sugar above `DISTFILES` and `MASTER_SITES`, the group names must adhere to the restrictions on group names outlined in Multiple Distribution or Patches Files from Multiple Locations

When fetching multiple files using GitLab, sometimes the default distribution file is not fetched from a GitLab site. To disable fetching the default distribution, set:

    USE_GITLAB=	nodefault

| When using `USE_GITLAB=nodefault`, the Makefile must set `DISTFILES` in its top block. The definition should be:
    DISTFILES=    ${DISTNAME}${EXTRACT_SUFX}

例 20. Use of `USE_GITLAB` with Multiple Distribution Files

From time to time, there is a need to fetch more than one distribution file. For example, when the upstream git repository uses submodules. This can be done easily using groups in the `GL_*` variables:

    PORTNAME=	foo
    DISTVERSION=	1.0.2

    USE_GITLAB=	yes
    GL_SITE=	https://gitlab.example.com:9434/gitlab:icons
    GL_ACCOUNT=	bar:icons,contrib
    GL_PROJECT=	foo-icons:icons foo-contrib:contrib
    GL_COMMIT=	c189207a55da45305c884fe2b50e086fcad4724b ae7368cab1ca7ca754b38d49da064df87968ffe4:icons 9e4dd76ad9b38f33fdb417a4c01935958d5acd2a:contrib
    GL_SUBDIR=	ext/icons:icons

    CONFIGURE_ARGS= --with-contrib=${WRKSRC_contrib}

This will fetch two distribution files from gitlab.com and one from `gitlab.example.com` hosting GitLab. The default one comes from https://gitlab.com/foo/foo and commit is `c189207a55da45305c884fe2b50e086fcad4724b`. The second one, with the `icons` group, comes from https://gitlab.example.com:9434/gitlab/bar/foo-icons and commit is `ae7368cab1ca7ca754b38d49da064df87968ffe4`. The third one comes from https://gitlab.com/bar/foo-contrib and is commit `9e4dd76ad9b38f33fdb417a4c01935958d5acd2a`. The distribution files are named foo-foo-c189207a55da45305c884fe2b50e086fcad4724b_GL0.tar.gz, bar-foo-icons-ae7368cab1ca7ca754b38d49da064df87968ffe4_GL0.tar.gz, and bar-foo-contrib-9e4dd76ad9b38f33fdb417a4c01935958d5acd2a_GL0.tar.gz.

All the distribution files are extracted in `${WRKDIR}` in their respective subdirectories. The default file is still extracted in `${WRKSRC}`, in this case, ${WRKDIR}/foo-c189207a55da45305c884fe2b50e086fcad4724b-c189207a55da45305c884fe2b50e086fcad4724b. Each additional distribution file is extracted in `${WRKSRC_group}`. Here, for the `icons` group, it is called `${WRKSRC_icons}` and it contains ${WRKDIR}/foo-icons-ae7368cab1ca7ca754b38d49da064df87968ffe4-ae7368cab1ca7ca754b38d49da064df87968ffe4. The file with the `contrib` group is called `${WRKSRC_contrib}` and contains `${WRKDIR}/foo-contrib-9e4dd76ad9b38f33fdb417a4c01935958d5acd2a-9e4dd76ad9b38f33fdb417a4c01935958d5acd2a`.

The software’s build system expects to find the icons in a ext/icons subdirectory in its sources, so `GL_SUBDIR` is used. `GL_SUBDIR` makes sure that ext exists, but that ext/icons does not already exist. Then it does this:

    post-extract:
            @${MV} ${WRKSRC_icons} ${WRKSRC}/ext/icons

例 21. Use of `USE_GITLAB` with Multiple Distribution Files Using `GL_TUPLE`

This is functionally equivalent to Use of `USE_GITLAB` with Multiple Distribution Files, but using `GL_TUPLE`:

    PORTNAME=	foo
    DISTVERSION=	1.0.2

    USE_GITLAB=	yes
    GL_COMMIT=	c189207a55da45305c884fe2b50e086fcad4724b
    GL_TUPLE=	https://gitlab.example.com:9434/gitlab:bar:foo-icons:ae7368cab1ca7ca754b38d49da064df87968ffe4:icons/ext/icons \
    		bar:foo-contrib:9e4dd76ad9b38f33fdb417a4c01935958d5acd2a:contrib

    CONFIGURE_ARGS= --with-contrib=${WRKSRC_contrib}

Grouping was used in the previous example with `bar:icons,contrib`. Some redundant information is present with `GL_TUPLE` because grouping is not possible.

### 5.4.5. `EXTRACT_SUFX`

If there is one distribution file, and it uses an odd suffix to indicate the compression mechanism, set `EXTRACT_SUFX`.

For example, if the distribution file was named foo.tar.gzip instead of the more normal foo.tar.gz, write:

    DISTNAME=	foo
    EXTRACT_SUFX=	.tar.gzip

The `USES=tar[:xxx]`, `USES=lha` or `USES=zip` automatically set `EXTRACT_SUFX` to the most common archives extensions as necessary, see Using `USES` Macros for more details. If neither of these are set then `EXTRACT_SUFX` defaults to `.tar.gz`.

| As `EXTRACT_SUFX` is only used in `DISTFILES`, only set one of them..

### 5.4.6. `DISTFILES`

Sometimes the names of the files to be downloaded have no resemblance to the name of the port. For example, it might be called source.tar.gz or similar. In other cases the application’s source code might be in several different archives, all of which must be downloaded.

If this is the case, set `DISTFILES` to be a space separated list of all the files that must be downloaded.

    DISTFILES=	source1.tar.gz source2.tar.gz

If not explicitly set, `DISTFILES` defaults to `${DISTNAME}${EXTRACT_SUFX}`.

### 5.4.7. `EXTRACT_ONLY`

If only some of the `DISTFILES` must be extracted-for example, one of them is the source code, while another is an uncompressed document-list the filenames that must be extracted in `EXTRACT_ONLY`.

    DISTFILES=	source.tar.gz manual.html
    EXTRACT_ONLY=	source.tar.gz

When none of the `DISTFILES` need to be uncompressed, set `EXTRACT_ONLY` to the empty string.

    EXTRACT_ONLY=

### 5.4.8. `PATCHFILES`

If the port requires some additional patches that are available by FTP or HTTP, set `PATCHFILES` to the names of the files and `PATCH_SITES` to the URL of the directory that contains them (the format is the same as `MASTER_SITES`).

If the patch is not relative to the top of the source tree (that is, `WRKSRC`) because it contains some extra pathnames, set `PATCH_DIST_STRIP` accordingly. For instance, if all the pathnames in the patch have an extra `foozolix-1.0/` in front of the filenames, then set `PATCH_DIST_STRIP=-p1`.

Do not worry if the patches are compressed; they will be decompressed automatically if the filenames end with .Z, .gz, .bz2 or .xz.

If the patch is distributed with some other files, such as documentation, in a compressed tarball, using `PATCHFILES` is not possible. If that is the case, add the name and the location of the patch tarball to `DISTFILES` and `MASTER_SITES`. Then, use `EXTRA_PATCHES` to point to those files and bsd.port.mk will automatically apply them. In particular, do not copy patch files into ${PATCHDIR}. That directory may not be writable.

| If there are multiple patches and they need mixed values for the strip parameter, it can be added alongside the patch name in `PATCHFILES`, e.g:
    PATCHFILES=	patch1 patch2:-p1
This does not conflict with the master site grouping feature, adding a group also works:
    PATCHFILES=	patch2:-p1:source2

| The tarball will have been extracted alongside the regular source by then, so there is no need to explicitly extract it if it is a regular compressed tarball. Take extra care not to overwrite something that already exists in that directory if extracting it manually. Also, do not forget to add a command to remove the copied patch in the `pre-clean` target.

### 5.4.9. Multiple Distribution or Patches Files from Multiple Locations

(Consider this to be a somewhat "advanced topic"; those new to this document may wish to skip this section at first).

This section has information on the fetching mechanism known as both `MASTER_SITES:n` and `MASTER_SITES_NN`. We will refer to this mechanism as `MASTER_SITES:n`.

A little background first. OpenBSD has a neat feature inside `DISTFILES` and `PATCHFILES` which allows files and patches to be postfixed with `:n` identifiers. Here, `n` can be any word containing `[0-9a-zA-Z_]` and denote a group designation. For example:

    DISTFILES=	alpha:0 beta:1

In OpenBSD, distribution file alpha will be associated with variable `MASTER_SITES0` instead of our common `MASTER_SITES` and beta with `MASTER_SITES1`.

This is a very interesting feature which can decrease that endless search for the correct download site.

Just picture 2 files in `DISTFILES` and 20 sites in `MASTER_SITES`, the sites slow as hell where beta is carried by all sites in `MASTER_SITES`, and alpha can only be found in the 20th site. It would be such a waste to check all of them if the maintainer knew this beforehand, would it not? Not a good start for that lovely weekend!

Now that you have the idea, just imagine more `DISTFILES` and more `MASTER_SITES`. Surely our "distfiles survey meister" would appreciate the relief to network strain that this would bring.

In the next sections, information will follow on the FreeBSD implementation of this idea. We improved a bit on OpenBSD’s concept.

| The group names cannot have dashes in them (`-`), in fact, they cannot have any characters out of the `[a-zA-Z0-9_]` range. This is because, while make(1) is ok with variable names containing dashes, sh(1) is not.

#### 5.4.9.1. Simplified Information

This section explains how to quickly prepare fine grained fetching of multiple distribution files and patches from different sites and subdirectories. We describe here a case of simplified `MASTER_SITES:n` usage. This will be sufficient for most scenarios. More detailed information are available in Detailed Information.

Some applications consist of multiple distribution files that must be downloaded from a number of different sites. For example, Ghostscript consists of the core of the program, and then a large number of driver files that are used depending on the user’s printer. Some of these driver files are supplied with the core, but many others must be downloaded from a variety of different sites.

To support this, each entry in `DISTFILES` may be followed by a colon and a "group name". Each site listed in `MASTER_SITES` is then followed by a colon, and the group that indicates which distribution files are downloaded from this site.

For example, consider an application with the source split in two parts, source1.tar.gz and source2.tar.gz, which must be downloaded from two different sites. The port’s Makefile would include lines like Simplified Use of `MASTER_SITES:n` with One File Per Site.

例 22. Simplified Use of `MASTER_SITES:n` with One File Per Site

    MASTER_SITES=	ftp://ftp1.example.com/:source1 \
    		http://www.example.com/:source2
    DISTFILES=	source1.tar.gz:source1 \
    		source2.tar.gz:source2

Multiple distribution files can have the same group. Continuing the previous example, suppose that there was a third distfile, source3.tar.gz, that is downloaded from `ftp.example2.com`. The Makefile would then be written like Simplified Use of `MASTER_SITES:n` with More Than One File Per Site.

例 23. Simplified Use of `MASTER_SITES:n` with More Than One File Per Site

    MASTER_SITES=	ftp://ftp.example.com/:source1 \
    		http://www.example.com/:source2
    DISTFILES=	source1.tar.gz:source1 \
    		source2.tar.gz:source2 \
    		source3.tar.gz:source2

#### 5.4.9.2. Detailed Information

Okay, so the previous example did not reflect the new port’s needs? In this section we will explain in detail how the fine grained fetching mechanism `MASTER_SITES:n` works and how it can be used.

1. Elements can be postfixed with `:n` where n is ``, that is, _n_ could conceptually be any alphanumeric string but we will limit it to `[a-zA-Z_][0-9a-zA-Z_]` for now.

   Moreover, string matching is case sensitive; that is, `n` is different from `N`.

   However, these words cannot be used for postfixing purposes since they yield special meaning: `default`, `all` and `ALL` (they are used internally in item ii). Furthermore, `DEFAULT` is a special purpose word (check item 3).

2. Elements postfixed with `:n` belong to the group `n`, `:m` belong to group `m` and so forth.

3. Elements without a postfix are groupless, they all belong to the special group `DEFAULT`. Any elements postfixed with `DEFAULT`, is just being redundant unless an element belongs to both `DEFAULT` and other groups at the same time (check item 5).

   These examples are equivalent but the first one is preferred:

       MASTER_SITES=	alpha

       MASTER_SITES=	alpha:DEFAULT

4. Groups are not exclusive, an element may belong to several different groups at the same time and a group can either have either several different elements or none at all.

5. When an element belongs to several groups at the same time, use the comma operator (`,`).

   Instead of repeating it several times, each time with a different postfix, we can list several groups at once in a single postfix. For instance, `:m,n,o` marks an element that belongs to group `m`, `n` and `o`.

   All these examples are equivalent but the last one is preferred:

       MASTER_SITES=	alpha alpha:SOME_SITE

       MASTER_SITES=	alpha:DEFAULT alpha:SOME_SITE

       MASTER_SITES=	alpha:SOME_SITE,DEFAULT

       MASTER_SITES=	alpha:DEFAULT,SOME_SITE

6. All sites within a given group are sorted according to `MASTER_SORT_AWK`. All groups within `MASTER_SITES` and `PATCH_SITES` are sorted as well.

7. Group semantics can be used in any of the variables `MASTER_SITES`, `PATCH_SITES`, `MASTER_SITE_SUBDIR`, `PATCH_SITE_SUBDIR`, `DISTFILES`, and `PATCHFILES` according to this syntax:

   1. All `MASTER_SITES`, `PATCH_SITES`, `MASTER_SITE_SUBDIR` and `PATCH_SITE_SUBDIR` elements must be terminated with the forward slash `/` character. If any elements belong to any groups, the group postfix `:n` must come right after the terminator `/`. The `MASTER_SITES:n` mechanism relies on the existence of the terminator `/` to avoid confusing elements where a `:n` is a valid part of the element with occurrences where `:n` denotes group `n`. For compatibility purposes, since the `/` terminator was not required before in both `MASTER_SITE_SUBDIR` and `PATCH_SITE_SUBDIR` elements, if the postfix immediate preceding character is not a `/` then `:n` will be considered a valid part of the element instead of a group postfix even if an element is postfixed with `:n`. See both Detailed Use of `MASTER_SITES:n` in `MASTER_SITE_SUBDIR` and Detailed Use of `MASTER_SITES:n` with Comma Operator, Multiple Files, Multiple Sites and Multiple Subdirectories.

      例 24. Detailed Use of `MASTER_SITES:n` in `MASTER_SITE_SUBDIR`

          MASTER_SITE_SUBDIR=	old:n new/:NEW

      - Directories within group `DEFAULT` → old:n

      - Directories within group `NEW` → new

      例 25. Detailed Use of `MASTER_SITES:n` with Comma Operator, Multiple Files, Multiple Sites and Multiple Subdirectories

          MASTER_SITES=	http://site1/%SUBDIR%/ http://site2/:DEFAULT \
          		http://site3/:group3 http://site4/:group4 \
          		http://site5/:group5 http://site6/:group6 \
          		http://site7/:DEFAULT,group6 \
          		http://site8/%SUBDIR%/:group6,group7 \
          		http://site9/:group8
          DISTFILES=	file1 file2:DEFAULT file3:group3 \
          		file4:group4,group5,group6 file5:grouping \
          		file6:group7
          MASTER_SITE_SUBDIR=	directory-trial:1 directory-n/:groupn \
          		directory-one/:group6,DEFAULT \
          		directory

      The previous example results in this fine grained fetching. Sites are listed in the exact order they will be used.

      - file1 will be fetched from

        - `MASTER_SITE_OVERRIDE`

        - http://site1/directory-trial:1/

        - http://site1/directory-one/

        - http://site1/directory/

        - http://site2/

        - http://site7/

        - `MASTER_SITE_BACKUP`

      - file2 will be fetched exactly as file1 since they both belong to the same group

        - `MASTER_SITE_OVERRIDE`

        - http://site1/directory-trial:1/

        - http://site1/directory-one/

        - http://site1/directory/

        - http://site2/

        - http://site7/

        - `MASTER_SITE_BACKUP`

      - file3 will be fetched from

        - `MASTER_SITE_OVERRIDE`

        - http://site3/

        - `MASTER_SITE_BACKUP`

      - file4 will be fetched from

        - `MASTER_SITE_OVERRIDE`

        - http://site4/

        - http://site5/

        - http://site6/

        - http://site7/

        - http://site8/directory-one/

        - `MASTER_SITE_BACKUP`

      - file5 will be fetched from

        - `MASTER_SITE_OVERRIDE`

        - `MASTER_SITE_BACKUP`

      - file6 will be fetched from

        - `MASTER_SITE_OVERRIDE`

        - http://site8/

        - `MASTER_SITE_BACKUP`

8. How do I group one of the special macros from bsd.sites.mk, for example, SourceForge (`SF`)?

   This has been simplified as much as possible. See Detailed Use of `MASTER_SITES:n` with SourceForge (`SF`).

   例 26. Detailed Use of `MASTER_SITES:n` with SourceForge (`SF`)

       MASTER_SITES=	http://site1/ SF/something/1.0:sourceforge,TEST
       DISTFILES=	something.tar.gz:sourceforge

   something.tar.gz will be fetched from all sites within SourceForge.

9. How do I use this with `PATCH*`?

   All examples were done with `MASTER*` but they work exactly the same for `PATCH*` ones as can be seen in Simplified Use of `MASTER_SITES:n` with `PATCH_SITES`.

   例 27. Simplified Use of `MASTER_SITES:n` with `PATCH_SITES`

       PATCH_SITES=	http://site1/ http://site2/:test
       PATCHFILES=	patch1:test

#### 5.4.9.3. What Does Change for Ports? What Does Not?

1. All current ports remain the same. The `MASTER_SITES:n` feature code is only activated if there are elements postfixed with `:n` like elements according to the aforementioned syntax rules, especially as shown in item 7.

2. The port targets remain the same: `checksum`, `makesum`, `patch`, `configure`, `build`, etc. With the obvious exceptions of `do-fetch`, `fetch-list`, `master-sites` and `patch-sites`.

   - `do-fetch`: deploys the new grouping postfixed `DISTFILES` and `PATCHFILES` with their matching group elements within both `MASTER_SITES` and `PATCH_SITES` which use matching group elements within both `MASTER_SITE_SUBDIR` and `PATCH_SITE_SUBDIR`. Check Detailed Use of `MASTER_SITES:n` with Comma Operator, Multiple Files, Multiple Sites and Multiple Subdirectories.

   - `fetch-list`: works like old `fetch-list` with the exception that it groups just like `do-fetch`.

   - `master-sites` and `patch-sites`: (incompatible with older versions) only return the elements of group `DEFAULT`; in fact, they execute targets `master-sites-default` and `patch-sites-default` respectively.

     Furthermore, using target either `master-sites-all` or `patch-sites-all` is preferred to directly checking either `MASTER_SITES` or `PATCH_SITES`. Also, directly checking is not guaranteed to work in any future versions. Check item B for more information on these new port targets.

3. New port targets

   1. There are `master-sites-n` and `patch-sites-n` targets which will list the elements of the respective group n within `MASTER_SITES` and `PATCH_SITES` respectively. For instance, both `master-sites-DEFAULT` and `patch-sites-DEFAULT` will return the elements of group `DEFAULT`, `master-sites-test` and `patch-sites-test` of group `test`, and thereon.

   2. There are new targets `master-sites-all` and `patch-sites-all` which do the work of the old `master-sites` and `patch-sites` ones. They return the elements of all groups as if they all belonged to the same group with the caveat that it lists as many `MASTER_SITE_BACKUP` and `MASTER_SITE_OVERRIDE` as there are groups defined within either `DISTFILES` or `PATCHFILES`; respectively for `master-sites-all` and `patch-sites-all`.

### 5.4.10. `DIST_SUBDIR`

Do not let the port clutter /usr/ports/distfiles. If the port requires a lot of files to be fetched, or contains a file that has a name that might conflict with other ports (for example, Makefile), set `DIST_SUBDIR` to the name of the port (`${PORTNAME}` or `${PKGNAMEPREFIX}${PORTNAME}` are fine). This will change `DISTDIR` from the default /usr/ports/distfiles to /usr/ports/distfiles/${DIST_SUBDIR}, and in effect puts everything that is required for the port into that subdirectory.

It will also look at the subdirectory with the same name on the backup master site at http://distcache.FreeBSD.org (Setting `DISTDIR` explicitly in Makefile will not accomplish this, so please use `DIST_SUBDIR`.)

| This does not affect `MASTER_SITES` defined in the Makefile.

## 5.5. `MAINTAINER`

Set your mail-address here. Please. :-)

Only a single address without the comment part is allowed as a `MAINTAINER` value. The format used is `user@hostname.domain`. Please do not include any descriptive text such as a real name in this entry. That merely confuses the Ports infrastructure and most tools using it.

The maintainer is responsible for keeping the port up to date and making sure that it works correctly. For a detailed description of the responsibilities of a port maintainer, refer to The challenge for port maintainers.

| A maintainer volunteers to keep a port in good working order. Maintainers have the primary responsibility for their ports, but not exclusive ownership. Ports exist for the benefit of the community and, in reality, belong to the community. What this means is that people other than the maintainer can make changes to a port. Large changes to the Ports Collection might require changes to many ports. The FreeBSD Ports Management Team or members of other teams might modify ports to fix dependency issues or other problems, like a version bump for a shared library update. Some types of fixes have "blanket approval" from the Ports Management Team <portmgr@FreeBSD.org>, allowing any committer to fix those categories of problems on any port. These fixes do not need approval from the maintainer. Blanket approval for most ports applies to fixes like infrastructure changes, or trivial and tested build and runtime fixes. The current list is available in Ports section of the Committer’s Guide.

Other changes to the port will be sent to the maintainer for review and approval before being committed. If the maintainer does not respond to an update request after two weeks (excluding major public holidays), then that is considered a maintainer timeout, and the update can be made without explicit maintainer approval. If the maintainer does not respond within three months, or if there have been three consecutive timeouts, then that maintainer is considered absent without leave, and all of their ports can be assigned back to the pool. Exceptions to this are anything maintained by the Ports Management Team <portmgr@FreeBSD.org>, or the Security Officer Team <security-officer@FreeBSD.org>. No unauthorized commits may ever be made to ports maintained by those groups.

We reserve the right to modify the maintainer’s submission to better match existing policies and style of the Ports Collection without explicit blessing from the submitter or the maintainer. Also, large infrastructural changes can result in a port being modified without the maintainer’s consent. These kinds of changes will never affect the port’s functionality.

The Ports Management Team <portmgr@FreeBSD.org> reserves the right to revoke or override anyone’s maintainership for any reason, and the Security Officer Team <security-officer@FreeBSD.org> reserves the right to revoke or override maintainership for security reasons.

## 5.6. `COMMENT`

The comment is a one-line description of a port shown by `pkg info`. Please follow these rules when composing it:

1. The COMMENT string should be 70 characters or less.

2. Do not include the package name or version number of software.

3. The comment must begin with a capital and end without a period.

4. Do not start with an indefinite article (that is, A or An).

5. Capitalize names such as Apache, JavaScript, or Perl.

6. Use a serial comma for lists of words: "green, red, and blue."

7. Check for spelling errors.

Here is an example:

    COMMENT=	Cat chasing a mouse all over the screen

The COMMENT variable immediately follows the MAINTAINER variable in the Makefile.

## 5.7. Licenses

Each port must document the license under which it is available. If it is not an OSI approved license it must also document any restrictions on redistribution.

### 5.7.1. `LICENSE`

A short name for the license or licenses if more than one license apply.

If it is one of the licenses listed in Predefined License List, only `LICENSE_FILE` and `LICENSE_DISTFILES` variables can be set.

If this is a license that has not been defined in the ports framework (see Predefined License List), the `LICENSE_PERMS` and `LICENSE_NAME` must be set, along with either `LICENSE_FILE` or `LICENSE_TEXT`. `LICENSE_DISTFILES` and `LICENSE_GROUPS` can also be set, but are not required.

The predefined licenses are shown in Predefined License List. The current list is always available in Mk/bsd.licenses.db.mk.

例 28. Simplest Usage, Predefined Licenses

When the README of some software says "This software is under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version." but does not provide the license file, use this:

    LICENSE=	LGPL21+

When the software provides the license file, use this:

    LICENSE=	LGPL21+
    LICENSE_FILE=	${WRKSRC}/COPYING

For the predefined licenses, the default permissions are `dist-mirror dist-sell pkg-mirror pkg-sell auto-accept`.

表 7. Predefined License List
Short Name | Name | Group | Permissions
--- | --- | --- | ---
`AGPLv3` | GNU Affero General Public License version 3 | `FSF GPL OSI` | (default)
`AGPLv3+` | GNU Affero General Public License version 3 (or later) | `FSF GPL OSI` | (default)
`APACHE10` | Apache License 1.0 | `FSF` | (default)
`APACHE11` | Apache License 1.1 | `FSF OSI` | (default)
`APACHE20` | Apache License 2.0 | `FSF OSI` | (default)
`ART10` | Artistic License version 1.0 | `OSI` | (default)
`ART20` | Artistic License version 2.0 | `FSF GPL OSI` | (default)
`ARTPERL10` | Artistic License (perl) version 1.0 | `OSI` | (default)
`BSD` | BSD license Generic Version (deprecated) | `FSF OSI COPYFREE` | (default)
`BSD2CLAUSE` | BSD 2-clause "Simplified" License | `FSF OSI COPYFREE` | (default)
`BSD3CLAUSE` | BSD 3-clause "New" or "Revised" License | `FSF OSI COPYFREE` | (default)
`BSD4CLAUSE` | BSD 4-clause "Original" or "Old" License | `FSF` | (default)
`BSL` | Boost Software License | `FSF OSI COPYFREE` | (default)
`CC-BY-1.0` | Creative Commons Attribution 1.0 |  | (default)
`CC-BY-2.0` | Creative Commons Attribution 2.0 |  | (default)
`CC-BY-2.5` | Creative Commons Attribution 2.5 |  | (default)
`CC-BY-3.0` | Creative Commons Attribution 3.0 |  | (default)
`CC-BY-4.0` | Creative Commons Attribution 4.0 |  | (default)
`CC-BY-NC-1.0` | Creative Commons Attribution Non Commercial 1.0 |  | `dist-mirror`pkg-mirror`auto-accept`
`CC-BY-NC-2.0` | Creative Commons Attribution Non Commercial 2.0 |  | `dist-mirror`pkg-mirror`auto-accept`
`CC-BY-NC-2.5` | Creative Commons Attribution Non Commercial 2.5 |  | `dist-mirror`pkg-mirror`auto-accept`
`CC-BY-NC-3.0` | Creative Commons Attribution Non Commercial 3.0 |  | `dist-mirror`pkg-mirror`auto-accept`
`CC-BY-NC-4.0` | Creative Commons Attribution Non Commercial 4.0 |  | `dist-mirror`pkg-mirror`auto-accept`
`CC-BY-NC-ND-1.0` | Creative Commons Attribution Non Commercial No Derivatives 1.0 |  | `dist-mirror`pkg-mirror`auto-accept`
`CC-BY-NC-ND-2.0` | Creative Commons Attribution Non Commercial No Derivatives 2.0 |  | `dist-mirror`pkg-mirror`auto-accept`
`CC-BY-NC-ND-2.5` | Creative Commons Attribution Non Commercial No Derivatives 2.5 |  | `dist-mirror`pkg-mirror`auto-accept`
`CC-BY-NC-ND-3.0` | Creative Commons Attribution Non Commercial No Derivatives 3.0 |  | `dist-mirror`pkg-mirror`auto-accept`
`CC-BY-NC-ND-4.0` | Creative Commons Attribution Non Commercial No Derivatives 4.0 |  | `dist-mirror`pkg-mirror`auto-accept`
`CC-BY-NC-SA-1.0` | Creative Commons Attribution Non Commercial Share Alike 1.0 |  | `dist-mirror`pkg-mirror`auto-accept`
`CC-BY-NC-SA-2.0` | Creative Commons Attribution Non Commercial Share Alike 2.0 |  | `dist-mirror`pkg-mirror`auto-accept`
`CC-BY-NC-SA-2.5` | Creative Commons Attribution Non Commercial Share Alike 2.5 |  | `dist-mirror`pkg-mirror`auto-accept`
`CC-BY-NC-SA-3.0` | Creative Commons Attribution Non Commercial Share Alike 3.0 |  | `dist-mirror`pkg-mirror`auto-accept`
`CC-BY-NC-SA-4.0` | Creative Commons Attribution Non Commercial Share Alike 4.0 |  | `dist-mirror`pkg-mirror`auto-accept`
`CC-BY-ND-1.0` | Creative Commons Attribution No Derivatives 1.0 |  | (default)
`CC-BY-ND-2.0` | Creative Commons Attribution No Derivatives 2.0 |  | (default)
`CC-BY-ND-2.5` | Creative Commons Attribution No Derivatives 2.5 |  | (default)
`CC-BY-ND-3.0` | Creative Commons Attribution No Derivatives 3.0 |  | (default)
`CC-BY-ND-4.0` | Creative Commons Attribution No Derivatives 4.0 |  | (default)
`CC-BY-SA-1.0` | Creative Commons Attribution Share Alike 1.0 |  | (default)
`CC-BY-SA-2.0` | Creative Commons Attribution Share Alike 2.0 |  | (default)
`CC-BY-SA-2.5` | Creative Commons Attribution Share Alike 2.5 |  | (default)
`CC-BY-SA-3.0` | Creative Commons Attribution Share Alike 3.0 |  | (default)
`CC-BY-SA-4.0` | Creative Commons Attribution Share Alike 4.0 |  | (default)
`CC0-1.0` | Creative Commons Zero v1.0 Universal | `FSF GPL COPYFREE` | (default)
`CDDL` | Common Development and Distribution License | `FSF OSI` | (default)
`CPAL-1.0` | Common Public Attribution License | `FSF OSI` | (default)
`ClArtistic` | Clarified Artistic License | `FSF GPL OSI` | (default)
`EPL` | Eclipse Public License | `FSF OSI` | (default)
`GFDL` | GNU Free Documentation License | `FSF` | (default)
`GMGPL` | GNAT Modified General Public License | `FSF GPL OSI` | (default)
`GPLv1` | GNU General Public License version 1 | `FSF GPL OSI` | (default)
`GPLv1+` | GNU General Public License version 1 (or later) | `FSF GPL OSI` | (default)
`GPLv2` | GNU General Public License version 2 | `FSF GPL OSI` | (default)
`GPLv2+` | GNU General Public License version 2 (or later) | `FSF GPL OSI` | (default)
`GPLv3` | GNU General Public License version 3 | `FSF GPL OSI` | (default)
`GPLv3+` | GNU General Public License version 3 (or later) | `FSF GPL OSI` | (default)
`GPLv3RLE` | GNU GPL version 3 Runtime Library Exception | `FSF GPL OSI` | (default)
`GPLv3RLE+` | GNU GPL version 3 Runtime Library Exception (or later) | `FSF GPL OSI` | (default)
`ISCL` | Internet Systems Consortium License | `FSF GPL OSI COPYFREE` | (default)
`LGPL20` | GNU Library General Public License version 2.0 | `FSF GPL OSI` | (default)
`LGPL20+` | GNU Library General Public License version 2.0 (or later) | `FSF GPL OSI` | (default)
`LGPL21` | GNU Lesser General Public License version 2.1 | `FSF GPL OSI` | (default)
`LGPL21+` | GNU Lesser General Public License version 2.1 (or later) | `FSF GPL OSI` | (default)
`LGPL3` | GNU Lesser General Public License version 3 | `FSF GPL OSI` | (default)
`LGPL3+` | GNU Lesser General Public License version 3 (or later) | `FSF GPL OSI` | (default)
`LPPL10` | LaTeX Project Public License version 1.0 | `FSF OSI` | `dist-mirror dist-sell`
`LPPL11` | LaTeX Project Public License version 1.1 | `FSF OSI` | `dist-mirror dist-sell`
`LPPL12` | LaTeX Project Public License version 1.2 | `FSF OSI` | `dist-mirror dist-sell`
`LPPL13` | LaTeX Project Public License version 1.3 | `FSF OSI` | `dist-mirror dist-sell`
`LPPL13a` | LaTeX Project Public License version 1.3a | `FSF OSI` | `dist-mirror dist-sell`
`LPPL13b` | LaTeX Project Public License version 1.3b | `FSF OSI` | `dist-mirror dist-sell`
`LPPL13c` | LaTeX Project Public License version 1.3c | `FSF OSI` | `dist-mirror dist-sell`
`MIT` | MIT license / X11 license | `COPYFREE FSF GPL OSI` | (default)
`MPL10` | Mozilla Public License version 1.0 | `FSF OSI` | (default)
`MPL11` | Mozilla Public License version 1.1 | `FSF OSI` | (default)
`MPL20` | Mozilla Public License version 2.0 | `FSF OSI` | (default)
`NCSA` | University of Illinois/NCSA Open Source License | `COPYFREE FSF GPL OSI` | (default)
`NONE` | No license specified |  | `none`
`OFL10` | SIL Open Font License version 1.0 (http://scripts.sil.org/OFL) | `FONTS` | (default)
`OFL11` | SIL Open Font License version 1.1 (http://scripts.sil.org/OFL) | `FONTS` | (default)
`OWL` | Open Works License (owl.apotheon.org) | `COPYFREE` | (default)
`OpenSSL` | OpenSSL License | `FSF` | (default)
`PD` | Public Domain | `GPL COPYFREE` | (default)
`PHP202` | PHP License version 2.02 | `FSF OSI` | (default)
`PHP30` | PHP License version 3.0 | `FSF OSI` | (default)
`PHP301` | PHP License version 3.01 | `FSF OSI` | (default)
`PSFL` | Python Software Foundation License | `FSF GPL OSI` | (default)
`PostgreSQL` | PostgreSQL License | `FSF GPL OSI COPYFREE` | (default)
`RUBY` | Ruby License | `FSF` | (default)
`UNLICENSE` | The Unlicense | `COPYFREE FSF GPL` | (default)
`WTFPL` | Do What the Fuck You Want To Public License version 2 | `GPL FSF COPYFREE` | (default)
`WTFPL1` | Do What the Fuck You Want To Public License version 1 | `GPL FSF COPYFREE` | (default)
`ZLIB` | zlib License | `GPL FSF OSI` | (default)
`ZPL21` | Zope Public License version 2.1 | `GPL OSI` | (default)

### 5.7.2. `LICENSE_PERMS` and `LICENSE_PERMS_NAME_`

Permissions. use `none` if empty.

License Permissions List

`dist-mirror`

  Redistribution of the distribution files is permitted. The distribution files will be added to the FreeBSD `MASTER_SITE_BACKUP` CDN.

`no-dist-mirror`

  Redistribution of the distribution files is prohibited. This is equivalent to setting `RESTRICTED`. The distribution files will not be added to the FreeBSD `MASTER_SITE_BACKUP` CDN.

`dist-sell`

  Selling of distribution files is permitted. The distribution files will be present on the installer images.

`no-dist-sell`

  Selling of distribution files is prohibited. This is equivalent to setting `NO_CDROM`.

`pkg-mirror`

  Free redistribution of package is permitted. The package will be distributed on the FreeBSD package CDN https://pkg.freebsd.org/.

`no-pkg-mirror`

  Free redistribution of package is prohibited. Equivalent to setting `NO_PACKAGE`. The package will not be distributed from the FreeBSD package CDN https://pkg.freebsd.org/.

`pkg-sell`

  Selling of package is permitted. The package will be present on the installer images.

`no-pkg-sell`

  Selling of package is prohibited. This is equivalent to setting `NO_CDROM`. The package will not be present on the installer images.

`auto-accept`

  License is accepted by default. Prompts to accept a license are not displayed unless the user has defined `LICENSES_ASK`. Use this unless the license states the user must accept the terms of the license.

`no-auto-accept`

  License is not accepted by default. The user will always be asked to confirm the acceptance of this license. This must be used if the license states that the user must accept its terms.

When both `permission` and `no-permission` is present the `no-permission` will cancel `permission`.

When `permission` is not present, it is considered to be a `no-permission`.

| Some missing permissions will prevent a port (and all ports depending on it) from being usable by package users: A port without the `auto-accept` permission will never be be built and all the ports depending on it will be ignored. A port without the `pkg-mirror` permission will be removed, as well as all the ports depending on it, after the build and they will ever end up being distributed.

例 29. Nonstandard License

Read the terms of the license and translate those using the available permissions.

    LICENSE=        UNKNOWN
    LICENSE_NAME=   unknown
    LICENSE_TEXT=   This program is NOT in public domain.\
                    It can be freely distributed for non-commercial purposes only.
    LICENSE_PERMS=  dist-mirror no-dist-sell pkg-mirror no-pkg-sell auto-accept

例 30. Standard and Nonstandard Licenses

Read the terms of the license and express those using the available permissions. In case of doubt, please ask for guidance on the FreeBSD ports 郵遞論壇.

    LICENSE=        WARSOW GPLv2
    LICENSE_COMB=   multi
    LICENSE_NAME_WARSOW=    Warsow Content License
    LICENSE_FILE_WARSOW=    ${WRKSRC}/docs/license.txt
    LICENSE_PERMS_WARSOW=   dist-mirror pkg-mirror auto-accept

When the permissions of the GPLv2 and the UNKNOWN licenses are mixed, the port ends up with `dist-mirror dist-sell pkg-mirror pkg-sell auto-accept dist-mirror no-dist-sell pkg-mirror no-pkg-sell auto-accept`. The `no-permissions` cancel the permissions. The resulting list of permissions are dist-mirror pkg-mirror auto-accept. The distribution files and the packages will not be available on the installer images.

### 5.7.3. `LICENSE_GROUPS` and `LICENSE_GROUPS_NAME`

Groups the license belongs.

Predefined License Groups List

`FSF`

  Free Software Foundation Approved, see the FSF Licensing & Compliance Team.

`GPL`

  GPL Compatible

`OSI`

  OSI Approved, see the Open Source Initiative Open Source Licenses page.

`COPYFREE`

  Comply with Copyfree Standard Definition, see the Copyfree Licenses page.

`FONTS`

  Font licenses

### 5.7.4. `LICENSE_NAME` and `LICENSE_NAME_NAME`

Full name of the license.

例 31. `LICENSE_NAME`

    LICENSE=        UNRAR
    LICENSE_NAME=   UnRAR License
    LICENSE_FILE=   ${WRKSRC}/license.txt
    LICENSE_PERMS=  dist-mirror dist-sell pkg-mirror pkg-sell auto-accept

### 5.7.5. `LICENSE_FILE` and `LICENSE_FILE_NAME`

Full path to the file containing the license text, usually ${WRKSRC}/some/file. If the file is not in the distfile, and its content is too long to be put in `LICENSE_TEXT`, put it in a new file in ${FILESDIR}.

例 32. `LICENSE_FILE`

    LICENSE=	GPLv3+
    LICENSE_FILE=	${WRKSRC}/COPYING

### 5.7.6. `LICENSE_TEXT` and `LICENSE_TEXT_NAME`

Text to use as a license. Useful when the license is not in the distribution files and its text is short.

例 33. `LICENSE_TEXT`

    LICENSE=        UNKNOWN
    LICENSE_NAME=   unknown
    LICENSE_TEXT=   This program is NOT in public domain.\
                    It can be freely distributed for non-commercial purposes only,\
                    and THERE IS NO WARRANTY FOR THIS PROGRAM.
    LICENSE_PERMS=  dist-mirror no-dist-sell pkg-mirror no-pkg-sell auto-accept

### 5.7.7. `LICENSE_DISTFILES` and `LICENSE_DISTFILES_NAME`

The distribution files to which the licenses apply. Defaults to all the distribution files.

例 34. `LICENSE_DISTFILES`

Used when the distribution files do not all have the same license. For example, one has a code license, and another has some artwork that cannot be redistributed:

    MASTER_SITES=   SF/some-game
    DISTFILES=      ${DISTNAME}${EXTRACT_SUFX} artwork.zip

    LICENSE=        BSD3CLAUSE ARTWORK
    LICENSE_COMB=   dual
    LICENSE_NAME_ARTWORK=      The game artwork license
    LICENSE_TEXT_ARTWORK=      The README says that the files cannot be redistributed
    LICENSE_PERMS_ARTWORK=     pkg-mirror pkg-sell auto-accept
    LICENSE_DISTFILES_BSD3CLAUSE=   ${DISTNAME}${EXTRACT_SUFX}
    LICENSE_DISTFILES_ARTWORK= artwork.zip

### 5.7.8. `LICENSE_COMB`

Set to `multi` if all licenses apply. Set to `dual` if any license applies. Defaults to `single`.

例 35. Dual Licenses

When a port says "This software may be distributed under the GNU General Public License or the Artistic License", it means that either license can be used. Use this:

    LICENSE=	ART10 GPLv1
    LICENSE_COMB=   dual

If license files are provided, use this:

    LICENSE=	ART10 GPLv1
    LICENSE_COMB=   dual
    LICENSE_FILE_ART10=     ${WRKSRC}/Artistic
    LICENSE_FILE_GPLv1=     ${WRKSRC}/Copying

例 36. Multiple Licenses

When part of a port has one license, and another part has a different license, use `multi`:

    LICENSE=	GPLv2 LGPL21+
    LICENSE_COMB=	multi

## 5.8. `PORTSCOUT`

Portscout is an automated distfile check utility for the FreeBSD Ports Collection, described in detail in Portscout: the FreeBSD Ports Distfile Scanner.

`PORTSCOUT` defines special conditions within which the Portscout distfile scanner is restricted.

Situations where `PORTSCOUT` is set include:

- When distfiles have to be ignored for specific versions. For example, to exclude version 8.2 and version 8.3 from distfile version checks because they are known to be broken, add:

      PORTSCOUT=	skipv:8.2,8.3

- When distfile version checks have to be disabled completely. For example, if a port is not going to be updated ever again, add:

      PORTSCOUT=	ignore:1

- When specific versions or specific major and minor revisions of a distfile must be checked. For example, if only version 0.6.4 must be monitored because newer versions have compatibility issues with FreeBSD, add:

      PORTSCOUT=	limit:^0\.6\.4

- When URLs listing the available versions differ from the download URLs. For example, to limit distfile version checks to the download page for the databases/pgtune port, add:

      PORTSCOUT=	site:http://pgfoundry.org/frs/?group_id=1000416

## 5.9. Dependencies

Many ports depend on other ports. This is a very convenient feature of most Unix-like operating systems, including FreeBSD. Multiple ports can share a common dependency, rather than bundling that dependency with every port or package that needs it. There are seven variables that can be used to ensure that all the required bits will be on the user’s machine. There are also some pre-supported dependency variables for common cases, plus a few more to control the behavior of dependencies.

| When software has extra dependencies that provide extra features, the base dependencies listed in `*_DEPENDS` should include the extra dependencies that would benefit most users. The base dependencies should never be a "minimal" dependency set. The goal is not to include every dependency possible. Only include those that will benefit most people.

### 5.9.1. `LIB_DEPENDS`

This variable specifies the shared libraries this port depends on. It is a list of `lib:dir` tuples where `lib` is the name of the shared library, `dir` is the directory in which to find it in case it is not available. For example,

    LIB_DEPENDS=   libjpeg.so:graphics/jpeg

will check for a shared jpeg library with any version, and descend into the graphics/jpeg subdirectory of the ports tree to build and install it if it is not found.

The dependency is checked twice, once from within the `build` target and then from within the `install` target. Also, the name of the dependency is put into the package so that `pkg install` (see pkg-install(8)) will automatically install it if it is not on the user’s system.

### 5.9.2. `RUN_DEPENDS`

This variable specifies executables or files this port depends on during run-time. It is a list of `path:dir`[:`target`] tuples where `path` is the name of the executable or file, dir is the directory in which to find it in case it is not available, and target is the target to call in that directory. If path starts with a slash (`/`), it is treated as a file and its existence is tested with `test -e`; otherwise, it is assumed to be an executable, and `which -s` is used to determine if the program exists in the search path.

For example,

    RUN_DEPENDS=	${LOCALBASE}/news/bin/innd:news/inn \
    		xmlcatmgr:textproc/xmlcatmgr

will check if the file or directory /usr/local/news/bin/innd exists, and build and install it from the news/inn subdirectory of the ports tree if it is not found. It will also see if an executable called `xmlcatmgr` is in the search path, and descend into textproc/xmlcatmgr to build and install it if it is not found.

| In this case, `innd` is actually an executable; if an executable is in a place that is not expected to be in the search path, use the full pathname.

| The official search `PATH` used on the ports build cluster is
    /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin

The dependency is checked from within the `install` target. Also, the name of the dependency is put into the package so that `pkg install` (see pkg-install(8)) will automatically install it if it is not on the user’s system. The target part can be omitted if it is the same as `DEPENDS_TARGET`.

A quite common situation is when `RUN_DEPENDS` is literally the same as `BUILD_DEPENDS`, especially if ported software is written in a scripted language or if it requires the same build and run-time environment. In this case, it is both tempting and intuitive to directly assign one to the other:

    RUN_DEPENDS=	${BUILD_DEPENDS}

However, such assignment can pollute run-time dependencies with entries not defined in the port’s original `BUILD_DEPENDS`. This happens because of make(1)'s lazy evaluation of variable assignment. Consider a Makefile with `USE_*`, which are processed by ports/Mk/bsd.*.mk to augment initial build dependencies. For example, `USES= gmake` adds devel/gmake to `BUILD_DEPENDS`. To prevent such additional dependencies from polluting `RUN_DEPENDS`, create another variable with the current content of `BUILD_DEPENDS` and assign it to both `BUILD_DEPENDS` and `RUN_DEPENDS`:

    MY_DEPENDS=	some:devel/some \
    		other:lang/other
    BUILD_DEPENDS=	${MY_DEPENDS}
    RUN_DEPENDS=	${MY_DEPENDS}

| Do not use `:=` to assign `BUILD_DEPENDS` to `RUN_DEPENDS` or vice-versa. All variables are expanded immediately, which is exactly the wrong thing to do and almost always a failure.

### 5.9.3. `BUILD_DEPENDS`

This variable specifies executables or files this port requires to build. Like `RUN_DEPENDS`, it is a list of `path:dir`[:`target`] tuples. For example,

    BUILD_DEPENDS=	unzip:archivers/unzip

will check for an executable called `unzip`, and descend into the archivers/unzip subdirectory of the ports tree to build and install it if it is not found.

| "build" here means everything from extraction to compilation. The dependency is checked from within the `extract` target. The target part can be omitted if it is the same as `DEPENDS_TARGET`

### 5.9.4. `FETCH_DEPENDS`

This variable specifies executables or files this port requires to fetch. Like the previous two, it is a list of `path:dir`[:`target`] tuples. For example,

    FETCH_DEPENDS=	ncftp2:net/ncftp2

will check for an executable called `ncftp2`, and descend into the net/ncftp2 subdirectory of the ports tree to build and install it if it is not found.

The dependency is checked from within the `fetch` target. The target part can be omitted if it is the same as `DEPENDS_TARGET`.

### 5.9.5. `EXTRACT_DEPENDS`

This variable specifies executables or files this port requires for extraction. Like the previous, it is a list of `path:dir`[:`target`] tuples. For example,

    EXTRACT_DEPENDS=	unzip:archivers/unzip

will check for an executable called `unzip`, and descend into the archivers/unzip subdirectory of the ports tree to build and install it if it is not found.

The dependency is checked from within the `extract` target. The target part can be omitted if it is the same as `DEPENDS_TARGET`.

| Use this variable only if the extraction does not already work (the default assumes `tar`) and cannot be made to work using `USES=tar`, `USES=lha` or `USES=zip` described in Using `USES` Macros.

### 5.9.6. `PATCH_DEPENDS`

This variable specifies executables or files this port requires to patch. Like the previous, it is a list of `path:dir`[:`target`] tuples. For example,

    PATCH_DEPENDS=	${NONEXISTENT}:java/jfc:extract

will descend into the java/jfc subdirectory of the ports tree to extract it.

The dependency is checked from within the `patch` target. The target part can be omitted if it is the same as `DEPENDS_TARGET`.

### 5.9.7. `USES`

Parameters can be added to define different features and dependencies used by the port. They are specified by adding this line to the Makefile:

    USES= feature[:arguments]

For the complete list of values, please see Using `USES` Macros.

| `USES` cannot be assigned after inclusion of bsd.port.pre.mk.

### 5.9.8. `USE_*`

Several variables exist to define common dependencies shared by many ports. Their use is optional, but helps to reduce the verbosity of the port Makefiles. Each of them is styled as `USE_*`. These variables may be used only in the port Makefiles and ports/Mk/bsd.*.mk. They are not meant for user-settable options - use `PORT_OPTIONS` for that purpose.

| It is always incorrect to set any `USE_*` in /etc/make.conf. For instance, setting
    USE_GCC=X.Y
(where X.Y is version number) would add a dependency on gccXY for every port, including `lang/gccXY` itself!

表 8. `USE_*`
Variable | Means
--- | ---
`USE_GCC` | The port requires GCC (`gcc` or `g++`) to build. Some ports need a specific, old GCC version, some require modern, recent versions. It is typically set to `yes` (means always use stable, modern GCC from ports per `GCC_DEFAULT` in Mk/bsd.default-versions.mk). This is also the default value. The exact version can also be specified, with a value such as `10`. The minimal required version can be specified as `10+`. GCC from the base system is used when it satisfies the requested version, otherwise an appropriate compiler is built from ports, and `CC` and `CXX` are adjusted accordingly. The `:build` argument following the version specifier adds only a build time dependency to the port. For example:
    USE_GCC=yes		# port requires a current version of GCC
    USE_GCC=11+:build	# port requires GCC 11 or later at build time only
| `USE_GCC=any` is deprecated and should not be used in new ports

Variables related to gmake and configure are described in Building Mechanisms, while autoconf, automake and libtool are described in Using GNU Autotools. Perl related variables are described in Using Perl. X11 variables are listed in Using X11. Using Gnome deals with GNOME and Using KDE with KDE related variables. Using Java documents Java variables, while Web Applications contains information on Apache, PHP and PEAR modules. Python is discussed in Using Python, while Ruby in Using Ruby. Using SDL provides variables used for SDL applications and finally, Using Xfce contains information on Xfce.

### 5.9.9. Minimal Version of a Dependency

A minimal version of a dependency can be specified in any `*_DEPENDS` except `LIB_DEPENDS` using this syntax:

    p5-Spiffy>=0.26:devel/p5-Spiffy

The first field contains a dependent package name, which must match the entry in the package database, a comparison sign, and a package version. The dependency is satisfied if p5-Spiffy-0.26 or newer is installed on the machine.

### 5.9.10. Notes on Dependencies

As mentioned above, the default target to call when a dependency is required is `DEPENDS_TARGET`. It defaults to `install`. This is a user variable; it is never defined in a port’s Makefile. If the port needs a special way to handle a dependency, use the `:target` part of `*_DEPENDS` instead of redefining `DEPENDS_TARGET`.

When running `make clean`, the port dependencies are automatically cleaned too. If this is not desirable, define `NOCLEANDEPENDS` in the environment. This may be particularly desirable if the port has something that takes a long time to rebuild in its dependency list, such as KDE, GNOME or Mozilla.

To depend on another port unconditionally, use the variable `${NONEXISTENT}` as the first field of `BUILD_DEPENDS` or `RUN_DEPENDS`. Use this only when the source of the other port is needed. Compilation time can be saved by specifying the target too. For instance

    BUILD_DEPENDS=	${NONEXISTENT}:graphics/jpeg:extract

will always descend to the `jpeg` port and extract it.

### 5.9.11. Circular Dependencies Are Fatal

| Do not introduce any circular dependencies into the ports tree!

The ports building technology does not tolerate circular dependencies. If one is introduced, someone, somewhere in the world, will have their FreeBSD installation broken almost immediately, with many others quickly to follow. These can really be hard to detect. If in doubt, before making that change, make sure to run: `cd /usr/ports; make index`. That process can be quite slow on older machines, but it may be able to save a large number of people, including yourself, a lot of grief in the process.

### 5.9.12. Problems Caused by Automatic Dependencies

Dependencies must be declared either explicitly or by using the OPTIONS framework. Using other methods like automatic detection complicates indexing, which causes problems for port and package management.

例 37. Wrong Declaration of an Optional Dependency

    .include <bsd.port.pre.mk>

    .if exists(${LOCALBASE}/bin/foo)
    LIB_DEPENDS=	libbar.so:foo/bar
    .endif

The problem with trying to automatically add dependencies is that files and settings outside an individual port can change at any time. For example: an index is built, then a batch of ports are installed. But one of the ports installs the tested file. The index is now incorrect, because an installed port unexpectedly has a new dependency. The index may still be wrong even after rebuilding if other ports also determine their need for dependencies based on the existence of other files.

例 38. Correct Declaration of an Optional Dependency

    OPTIONS_DEFINE=	BAR
    BAR_DESC=	Calling cellphones via bar

    BAR_LIB_DEPENDS=	libbar.so:foo/bar

Testing option variables is the correct method. It will not cause inconsistencies in the index of a batch of ports, provided the options were defined prior to the index build. Simple scripts can then be used to automate the building, installation, and updating of these ports and their packages.

## 5.10. Slave Ports and `MASTERDIR`

If the port needs to build slightly different versions of packages by having a variable (for instance, resolution, or paper size) take different values, create one subdirectory per package to make it easier for users to see what to do, but try to share as many files as possible between ports. Typically, by using variables cleverly, only a very short Makefile is needed in all but one of the directories. In the sole Makefile, use `MASTERDIR` to specify the directory where the rest of the files are. Also, use a variable as part of `PKGNAMESUFFIX` so the packages will have different names.

This will be best demonstrated by an example. This is part of print/pkfonts300/Makefile;

    PORTNAME=	pkfonts${RESOLUTION}
    PORTVERSION=	1.0
    DISTFILES=	pk${RESOLUTION}.tar.gz

    PLIST=		${PKGDIR}/pkg-plist.${RESOLUTION}

    .if !defined(RESOLUTION)
    RESOLUTION=	300
    .else
    .if ${RESOLUTION} != 118 && ${RESOLUTION} != 240 && \
    	${RESOLUTION} != 300 && ${RESOLUTION} != 360 && \
    	${RESOLUTION} != 400 && ${RESOLUTION} != 600
    .BEGIN:
    	@${ECHO_MSG} "Error: invalid value for RESOLUTION: \"${RESOLUTION}\""
    	@${ECHO_MSG} "Possible values are: 118, 240, 300, 360, 400 and 600."
    	@${FALSE}
    .endif
    .endif

print/pkfonts300 also has all the regular patches, package files, etc. Running `make` there, it will take the default value for the resolution (300) and build the port normally.

As for other resolutions, this is the entire print/pkfonts360/Makefile:

    RESOLUTION=	360
    MASTERDIR=	${.CURDIR}/../pkfonts300

    .include	"${MASTERDIR}/Makefile"

(print/pkfonts118/Makefile, print/pkfonts600/Makefile, and all the other are similar). `MASTERDIR` definition tells bsd.port.mk that the regular set of subdirectories like `FILESDIR` and `SCRIPTDIR` are to be found under pkfonts300. The `RESOLUTION=360` line will override the `RESOLUTION=300` line in pkfonts300/Makefile and the port will be built with resolution set to 360.

## 5.11. Man Pages

If the port anchors its man tree somewhere other than `PREFIX`, use `MANDIRS` to specify those directories. Note that the files corresponding to manual pages must be placed in pkg-plist along with the rest of the files. The purpose of `MANDIRS` is to enable automatic compression of manual pages, therefore the file names are suffixed with .gz.

## 5.12. Info Files

If the package needs to install GNU info files, list them in `INFO` (without the trailing `.info`), one entry per document. These files are assumed to be installed to PREFIX/INFO_PATH. Change `INFO_PATH` if the package uses a different location. However, this is not recommended. These entries contain just the path relative to PREFIX/INFO_PATH. For example, lang/gcc34 installs info files to PREFIX/INFO_PATH/gcc34, and `INFO` will be something like this:

    INFO=	gcc34/cpp gcc34/cppinternals gcc34/g77 ...

Appropriate installation/de-installation code will be automatically added to the temporary pkg-plist before package registration.

## 5.13. Makefile Options

Many applications can be built with optional or differing configurations. Examples include choice of natural (human) language, GUI versus command-line, or type of database to support. Users may need a different configuration than the default, so the ports system provides hooks the port author can use to control which variant will be built. Supporting these options properly will make users happy, and effectively provide two or more ports for the price of one.

### 5.13.1. `OPTIONS`

#### 5.13.1.1. Background

`OPTIONS_*` give the user installing the port a dialog showing the available options, and then saves those options to ${PORT_DBDIR}/${OPTIONS_NAME}/options. The next time the port is built, the options are reused. `PORT_DBDIR` defaults to /var/db/ports. `OPTIONS_NAME` is to the port origin with an underscore as the space separator, for example, for dns/bind99 it will be `dns_bind99`.

When the user runs `make config` (or runs `make build` for the first time), the framework checks for ${PORT_DBDIR}/${OPTIONS_NAME}/options. If that file does not exist, the values of `OPTIONS_*` are used, and a dialog box is displayed where the options can be enabled or disabled. Then options is saved and the configured variables are used when building the port.

If a new version of the port adds new `OPTIONS`, the dialog will be presented to the user with the saved values of old `OPTIONS` prefilled.

`make showconfig` shows the saved configuration. Use `make rmconfig` to remove the saved configuration.

#### 5.13.1.2. Syntax

`OPTIONS_DEFINE` contains a list of `OPTIONS` to be used. These are independent of each other and are not grouped:

    OPTIONS_DEFINE=	OPT1 OPT2

Once defined, `OPTIONS` are described (optional, but strongly recommended):

    OPT1_DESC=	Describe OPT1
    OPT2_DESC=	Describe OPT2
    OPT3_DESC=	Describe OPT3
    OPT4_DESC=	Describe OPT4
    OPT5_DESC=	Describe OPT5
    OPT6_DESC=	Describe OPT6

ports/Mk/bsd.options.desc.mk has descriptions for many common `OPTIONS`. While often useful, override them if the description is insufficient for the port.

| When describing options, view it from the perspective of the user: "What functionality does it change?" and "Why would I want to enable this?" Do not just repeat the name. For example, describing the `NLS` option as "include NLS support" does not help the user, who can already see the option name but may not know what it means. Describing it as "Native Language Support via gettext utilities" is much more helpful.

| Option names are always in all uppercase. They cannot use mixed case or lowercase.

`OPTIONS` can be grouped as radio choices, where only one choice from each group is allowed:

    OPTIONS_SINGLE=		SG1
    OPTIONS_SINGLE_SG1=	OPT3 OPT4

| There must be one of each `OPTIONS_SINGLE` group selected at all times for the options to be valid. One option of each group must be added to `OPTIONS_DEFAULT`.

`OPTIONS` can be grouped as radio choices, where none or only one choice from each group is allowed:

    OPTIONS_RADIO=		RG1
    OPTIONS_RADIO_RG1=	OPT7 OPT8

`OPTIONS` can also be grouped as "multiple-choice" lists, where at least one option must be enabled:

    OPTIONS_MULTI=		MG1
    OPTIONS_MULTI_MG1=	OPT5 OPT6

`OPTIONS` can also be grouped as "multiple-choice" lists, where none or any option can be enabled:

    OPTIONS_GROUP=		GG1
    OPTIONS_GROUP_GG1=	OPT9 OPT10

`OPTIONS` are unset by default, unless they are listed in `OPTIONS_DEFAULT`:

    OPTIONS_DEFAULT=	OPT1 OPT3 OPT6

`OPTIONS` definitions must appear before the inclusion of bsd.port.options.mk. `PORT_OPTIONS` values can only be tested after the inclusion of bsd.port.options.mk. Inclusion of bsd.port.pre.mk can be used instead, too, and is still widely used in ports written before the introduction of bsd.port.options.mk. But be aware that some variables will not work as expected after the inclusion of bsd.port.pre.mk, typically some `USE_*` flags.

例 39. Simple Use of `OPTIONS`

    OPTIONS_DEFINE=	FOO BAR
    OPTIONS_DEFAULT=FOO

    FOO_DESC=	Option foo support
    BAR_DESC=	Feature bar support

    # Will add --with-foo / --without-foo
    FOO_CONFIGURE_WITH=	foo
    BAR_RUN_DEPENDS=	bar:bar/bar

    .include <bsd.port.mk>

例 40. Check for Unset Port `OPTIONS`

    .if ! ${PORT_OPTIONS:MEXAMPLES}
    CONFIGURE_ARGS+=--without-examples
    .endif

The form shown above is discouraged. The preferred method is using a configure knob to really enable and disable the feature to match the option:

    # Will add --with-examples / --without-examples
    EXAMPLES_CONFIGURE_WITH=	examples

例 41. Practical Use of `OPTIONS`

    OPTIONS_DEFINE=		EXAMPLES
    OPTIONS_DEFAULT=	PGSQL LDAP SSL

    OPTIONS_SINGLE=		BACKEND
    OPTIONS_SINGLE_BACKEND=	MYSQL PGSQL BDB

    OPTIONS_MULTI=		AUTH
    OPTIONS_MULTI_AUTH=	LDAP PAM SSL

    EXAMPLES_DESC=		Install extra examples
    MYSQL_DESC=		Use MySQL as backend
    PGSQL_DESC=		Use PostgreSQL as backend
    BDB_DESC=		Use Berkeley DB as backend
    LDAP_DESC=		Build with LDAP authentication support
    PAM_DESC=		Build with PAM support
    SSL_DESC=		Build with OpenSSL support

    # Will add USE_PGSQL=yes
    PGSQL_USE=	pgsql=yes
    # Will add --enable-postgres / --disable-postgres
    PGSQL_CONFIGURE_ENABLE=	postgres

    ICU_LIB_DEPENDS=	libicuuc.so:devel/icu

    # Will add --with-examples / --without-examples
    EXAMPLES_CONFIGURE_WITH=	examples

    # Check other OPTIONS

    .include <bsd.port.mk>

#### 5.13.1.3. Default Options

These options are always on by default.

- `DOCS` - build and install documentation.

- `NLS` - Native Language Support.

- `EXAMPLES` - build and install examples.

- `IPV6` - IPv6 protocol support.

| There is no need to add these to `OPTIONS_DEFAULT`. To have them active, and show up in the options selection dialog, however, they must be added to `OPTIONS_DEFINE`.

### 5.13.2. Feature Auto-Activation

When using a GNU configure script, keep an eye on which optional features are activated by auto-detection. Explicitly disable optional features that are not needed by adding `--without-xxx` or `--disable-xxx` in `CONFIGURE_ARGS`.

例 42. Wrong Handling of an Option

    .if ${PORT_OPTIONS:MFOO}
    LIB_DEPENDS+=		libfoo.so:devel/foo
    CONFIGURE_ARGS+=	--enable-foo
    .endif

In the example above, imagine a library libfoo is installed on the system. The user does not want this application to use libfoo, so he toggled the option off in the `make config` dialog. But the application’s configure script detects the library present in the system and includes its support in the resulting executable. Now when the user decides to remove libfoo from the system, the ports system does not protest (no dependency on libfoo was recorded) but the application breaks.

例 43. Correct Handling of an Option

    FOO_LIB_DEPENDS=		libfoo.so:devel/foo
    # Will add --enable-foo / --disable-foo
    FOO_CONFIGURE_ENABLE=	foo

| Under some circumstances, the shorthand conditional syntax can cause problems with complex constructs. The errors are usually `Malformed conditional`, an alternative syntax can be used.
    .if !empty(VARIABLE:MVALUE)
as an alternative to
    .if ${VARIABLE:MVALUE}

### 5.13.3. Options Helpers

There are some macros to help simplify conditional values which differ based on the options set. For easier access, a comprehensive list is provided:

`PLIST_SUB`, `SUB_LIST`

  For automatic `%%OPT%%` and `%%NOOPT%%` generation, see `OPTIONS_SUB`.

  For more complex usage, see Generic Variables Replacement, `OPT_VARIABLE` and `OPT_VARIABLE_OFF`.

`CONFIGURE_ARGS`

  For `--enable-x` and `--disable-x`, see `OPT_CONFIGURE_ENABLE`.

  For `--with-x` and `--without-x`, see `OPT_CONFIGURE_WITH`.

  For all other cases, see `OPT_CONFIGURE_ON` and `OPT_CONFIGURE_OFF`.

`CMAKE_ARGS`

  For arguments that are booleans (`on`, `off`, `true`, `false`, `0`, `1`) see `OPT_CMAKE_BOOL` and `OPT_CMAKE_BOOL_OFF`.

  For all other cases, see `OPT_CMAKE_ON` and `OPT_CMAKE_OFF`.

`MESON_ARGS`

  For arguments that take `true` or `false`, see `OPT_MESON_TRUE` and `OPT_MESON_FALSE`.

  For arguments that take `yes` or `no`, use `OPT_MESON_YES` and `OPT_MESON_NO`.

  For arguments that take `enabled` or `disabled`, see `OPT_MESON_ENABLED` and `OPT_MESON_DISABLED`.

  For all other cases, use `OPT_MESON_ON` and `OPT_MESON_OFF`.

`QMAKE_ARGS`

  See `OPT_QMAKE_ON` and `OPT_QMAKE_OFF`.

`USE_*`

  See `OPT_USE` and `OPT_USE_OFF`.

`*_DEPENDS`

  See Dependencies, `OPT_DEPTYPE` and `OPT_DEPTYPE_OFF`.

`*` (Any variable)

  The most used variables have direct helpers, see Generic Variables Replacement, `OPT_VARIABLE` and `OPT_VARIABLE_OFF`.

  For any variable without a specific helper, see `OPT_VARS` and `OPT_VARS_OFF`.

Options dependencies

  When an option need another option to work, see `OPT_IMPLIES`.

Options conflicts

  When an option cannot work if another is also enabled, see `OPT_PREVENTS` and `OPT_PREVENTS_MSG`.

Build targets

  When an option need some extra processing, see Additional Build Targets, `target-OPT-on` and `target-OPT-off`.

#### 5.13.3.1. `OPTIONS_SUB`

If `OPTIONS_SUB` is set to `yes` then each of the options added to `OPTIONS_DEFINE` will be added to `PLIST_SUB` and `SUB_LIST`, for example:

    OPTIONS_DEFINE=	OPT1
    OPTIONS_SUB=	yes

is equivalent to:

    OPTIONS_DEFINE=	OPT1

    .include <bsd.port.options.mk>

    .if ${PORT_OPTIONS:MOPT1}
    PLIST_SUB+=	OPT1="" NO_OPT1="@comment "
    SUB_LIST+=	OPT1="" NO_OPT1="@comment "
    .else
    PLIST_SUB+=	OPT1="@comment " NO_OPT1=""
    SUB_LIST+=	OPT1="@comment " NO_OPT1=""
    .endif

| The value of `OPTIONS_SUB` is ignored. Setting it to any value will add `PLIST_SUB` and `SUB_LIST` entries for all options.

#### 5.13.3.2. `OPT_USE` and `OPT_USE_OFF`

When option OPT is selected, for each `key=value` pair in `OPT_USE`, value is appended to the corresponding `USE_KEY`. If value has spaces in it, replace them with commas and they will be changed back to spaces during processing. `OPT_USE_OFF` works the same way, but when `OPT` is not selected. For example:

    OPTIONS_DEFINE=	OPT1
    OPT1_USES=	xorg
    OPT1_USE=	mysql=yes xorg=x11,xextproto,xext,xrandr
    OPT1_USE_OFF=	openssl=yes

is equivalent to:

    OPTIONS_DEFINE=	OPT1

    .include <bsd.port.options.mk>

    .if ${PORT_OPTIONS:MOPT1}
    USE_MYSQL=	yes
    USES+=		xorg
    USE_XORG=	x11 xextproto xext xrandr
    .else
    USE_OPENSSL=	yes
    .endif

#### 5.13.3.3. `CONFIGURE_ARGS` Helpers

##### 5.13.3.3.1. `OPT_CONFIGURE_ENABLE`

When option OPT is selected, for each entry in `OPT_CONFIGURE_ENABLE` then `--enable-entry` is appended to `CONFIGURE_ARGS`. When option OPT is not selected, `--disable-entry` is appended to `CONFIGURE_ARGS`. An optional argument can be specified with an `=` symbol. This argument is only appended to the `--enable-entry` configure option. For example:

    OPTIONS_DEFINE=	OPT1 OPT2
    OPT1_CONFIGURE_ENABLE=	test1 test2
    OPT2_CONFIGURE_ENABLE=	test2=exhaustive

is equivalent to:

    OPTIONS_DEFINE=	OPT1

    .include <bsd.port.options.mk>

    .if ${PORT_OPTIONS:MOPT1}
    CONFIGURE_ARGS+=	--enable-test1 --enable-test2
    .else
    CONFIGURE_ARGS+=	--disable-test1 --disable-test2
    .endif

    .if ${PORT_OPTIONS:MOPT2}
    CONFIGURE_ARGS+=	--enable-test2=exhaustive
    .else
    CONFIGURE_ARGS+=	--disable-test2
    .endif

##### 5.13.3.3.2. `OPT_CONFIGURE_WITH`

When option OPT is selected, for each entry in `OPT_CONFIGURE_WITH` then `--with-_entry` is appended to `CONFIGURE_ARGS`. When option OPT is not selected, `--without-entry` is appended to `CONFIGURE_ARGS`. An optional argument can be specified with an `=` symbol. This argument is only appended to the `--with-entry` configure option. For example:

    OPTIONS_DEFINE=	OPT1 OPT2
    OPT1_CONFIGURE_WITH=	test1
    OPT2_CONFIGURE_WITH=	test2=exhaustive

is equivalent to:

    OPTIONS_DEFINE=	OPT1 OPT2

    .include <bsd.port.options.mk>

    .if ${PORT_OPTIONS:MOPT1}
    CONFIGURE_ARGS+=	--with-test1
    .else
    CONFIGURE_ARGS+=	--without-test1
    .endif

    .if ${PORT_OPTIONS:MOPT2}
    CONFIGURE_ARGS+=	--with-test2=exhaustive
    .else
    CONFIGURE_ARGS+=	--without-test2
    .endif

##### 5.13.3.3.3. `OPT_CONFIGURE_ON` and `OPT_CONFIGURE_OFF`

When option OPT is selected, the value of `OPT_CONFIGURE_ON`, if defined, is appended to `CONFIGURE_ARGS`. `OPT_CONFIGURE_OFF` works the same way, but when `OPT` is not selected. For example:

    OPTIONS_DEFINE=	OPT1
    OPT1_CONFIGURE_ON=	--add-test
    OPT1_CONFIGURE_OFF=	--no-test

is equivalent to:

    OPTIONS_DEFINE=	OPT1

    .include <bsd.port.options.mk>

    .if ${PORT_OPTIONS:MOPT1}
    CONFIGURE_ARGS+=	--add-test
    .else
    CONFIGURE_ARGS+=	--no-test
    .endif

| Most of the time, the helpers in `OPT_CONFIGURE_ENABLE` and `OPT_CONFIGURE_WITH` provide a shorter and more comprehensive functionality.

#### 5.13.3.4. `CMAKE_ARGS` Helpers

##### 5.13.3.4.1. `OPT_CMAKE_ON` and `OPT_CMAKE_OFF`

When option OPT is selected, the value of `OPT_CMAKE_ON`, if defined, is appended to `CMAKE_ARGS`. `OPT_CMAKE_OFF` works the same way, but when `OPT` is not selected. For example:

    OPTIONS_DEFINE=	OPT1
    OPT1_CMAKE_ON=	-DTEST:BOOL=true -DDEBUG:BOOL=true
    OPT1_CMAKE_OFF=	-DOPTIMIZE:BOOL=true

is equivalent to:

    OPTIONS_DEFINE=	OPT1

    .include <bsd.port.options.mk>

    .if ${PORT_OPTIONS:MOPT1}
    CMAKE_ARGS+=	-DTEST:BOOL=true -DDEBUG:BOOL=true
    .else
    CMAKE_ARGS+=	-DOPTIMIZE:BOOL=true
    .endif

| See `OPT_CMAKE_BOOL` and `OPT_CMAKE_BOOL_OFF` for a shorter helper when the value is boolean.

##### 5.13.3.4.2. `OPT_CMAKE_BOOL` and `OPT_CMAKE_BOOL_OFF`

When option OPT is selected, for each entry in `OPT_CMAKE_BOOL` then `-D_entry_:BOOL=true` is appended to `CMAKE_ARGS`. When option OPT is not selected, `-D_entry_:BOOL=false` is appended to `CONFIGURE_ARGS`. `OPT_CMAKE_BOOL_OFF` is the opposite, `-D_entry_:BOOL=false` is appended to `CMAKE_ARGS` when the option is selected, and `-D_entry_:BOOL=true` when the option is not selected. For example:

    OPTIONS_DEFINE=	OPT1
    OPT1_CMAKE_BOOL=	TEST DEBUG
    OPT1_CMAKE_BOOL_OFF=	OPTIMIZE

is equivalent to:

    OPTIONS_DEFINE=	OPT1

    .include <bsd.port.options.mk>

    .if ${PORT_OPTIONS:MOPT1}
    CMAKE_ARGS+=	-DTEST:BOOL=true -DDEBUG:BOOL=true \
    		-DOPTIMIZE:BOOL=false
    .else
    CMAKE_ARGS+=	-DTEST:BOOL=false -DDEBUG:BOOL=false \
    		-DOPTIMIZE:BOOL=true
    .endif

#### 5.13.3.5. `MESON_ARGS` Helpers

##### 5.13.3.5.1. `OPT_MESON_ON` and `OPT_MESON_OFF`

When option OPT is selected, the value of `OPT_MESON_ON`, if defined, is appended to `MESON_ARGS`. `OPT_MESON_OFF` works the same way, but when `OPT` is not selected. For example:

    OPTIONS_DEFINE=	OPT1
    OPT1_MESON_ON=	-Dopt=1
    OPT1_MESON_OFF=	-Dopt=2

is equivalent to:

    OPTIONS_DEFINE=	OPT1

    .include <bsd.port.options.mk>

    .if ${PORT_OPTIONS:MOPT1}
    MESON_ARGS+=	-Dopt=1
    .else
    MESON_ARGS+=	-Dopt=2
    .endif

##### 5.13.3.5.2. `OPT_MESON_TRUE` and `OPT_MESON_FALSE`

When option OPT is selected, for each entry in `OPT_MESON_TRUE` then `-D_entry_=true` is appended to `MESON_ARGS`. When option OPT is not selected, `-D_entry_=false` is appended to `MESON_ARGS`. `OPT_MESON_FALSE` is the opposite, `-D_entry_=false` is appended to `MESON_ARGS` when the option is selected, and `-D_entry_=true` when the option is not selected. For example:

    OPTIONS_DEFINE=	OPT1
    OPT1_MESON_TRUE=	test debug
    OPT1_MESON_FALSE=	optimize

is equivalent to:

    OPTIONS_DEFINE=	OPT1

    .include <bsd.port.options.mk>

    .if ${PORT_OPTIONS:MOPT1}
    MESON_ARGS+=	-Dtest=true -Ddebug=true \
    		-Doptimize=false
    .else
    MESON_ARGS+=	-Dtest=false -Ddebug=false \
    		-Doptimize=true
    .endif

##### 5.13.3.5.3. `OPT_MESON_YES` and `OPT_MESON_NO`

When option OPT is selected, for each entry in `OPT_MESON_YES` then `-D_entry_=yes` is appended to `MESON_ARGS`. When option OPT is not selected, `-D_entry_=no` is appended to `MESON_ARGS`. `OPT_MESON_NO` is the opposite, `-D_entry_=no` is appended to `MESON_ARGS` when the option is selected, and `-D_entry_=yes` when the option is not selected. For example:

    OPTIONS_DEFINE=	OPT1
    OPT1_MESON_YES=	test debug
    OPT1_MESON_NO=	optimize

is equivalent to:

    OPTIONS_DEFINE=	OPT1

    .include <bsd.port.options.mk>

    .if ${PORT_OPTIONS:MOPT1}
    MESON_ARGS+=	-Dtest=yes -Ddebug=yes \
    		-Doptimize=no
    .else
    MESON_ARGS+=	-Dtest=no -Ddebug=no \
    		-Doptimize=yes
    .endif

##### 5.13.3.5.4. `OPT_MESON_ENABLED` and `OPT_MESON_DISABLED`

When option OPT is selected, for each entry in `OPT_MESON_ENABLED` then `-D_entry_=enabled` is appended to `MESON_ARGS`. When option OPT is not selected, `-D_entry_=disabled` is appended to `MESON_ARGS`. `OPT_MESON_DISABLED` is the opposite, `-D_entry_=disabled` is appended to `MESON_ARGS` when the option is selected, and `-D_entry_=enabled` when the option is not selected. For example:

    OPTIONS_DEFINE=	OPT1
    OPT1_MESON_ENABLED=	test
    OPT1_MESON_DISABLED=	debug

is equivalent to:

    OPTIONS_DEFINE=	OPT1

    .include <bsd.port.options.mk>

    .if ${PORT_OPTIONS:MOPT1}
    MESON_ARGS+=	-Dtest=enabled -Ddebug=disabled
    .else
    MESON_ARGS+=	-Dtest=disabled -Ddebug=enabled
    .endif

#### 5.13.3.6. `OPT_QMAKE_ON` and `OPT_QMAKE_OFF`

When option OPT is selected, the value of `OPT_QMAKE_ON`, if defined, is appended to `QMAKE_ARGS`. `OPT_QMAKE_OFF` works the same way, but when `OPT` is not selected. For example:

    OPTIONS_DEFINE=	OPT1
    OPT1_QMAKE_ON=	-DTEST:BOOL=true
    OPT1_QMAKE_OFF=	-DPRODUCTION:BOOL=true

is equivalent to:

    OPTIONS_DEFINE=	OPT1

    .include <bsd.port.options.mk>

    .if ${PORT_OPTIONS:MOPT1}
    QMAKE_ARGS+=	-DTEST:BOOL=true
    .else
    QMAKE_ARGS+=	-DPRODUCTION:BOOL=true
    .endif

#### 5.13.3.7. `OPT_IMPLIES`

Provides a way to add dependencies between options.

When OPT is selected, all the options listed in this variable will be selected too. Using the `OPT_CONFIGURE_ENABLE` described earlier to illustrate:

    OPTIONS_DEFINE=	OPT1 OPT2
    OPT1_IMPLIES=	OPT2

    OPT1_CONFIGURE_ENABLE=	opt1
    OPT2_CONFIGURE_ENABLE=	opt2

Is equivalent to:

    OPTIONS_DEFINE=	OPT1 OPT2

    .include <bsd.port.options.mk>

    .if ${PORT_OPTIONS:MOPT1}
    CONFIGURE_ARGS+=	--enable-opt1
    .else
    CONFIGURE_ARGS+=	--disable-opt1
    .endif

    .if ${PORT_OPTIONS:MOPT2} || ${PORT_OPTIONS:MOPT1}
    CONFIGURE_ARGS+=	--enable-opt2
    .else
    CONFIGURE_ARGS+=	--disable-opt2
    .endif

例 44. Simple Use of `OPT_IMPLIES`

This port has a `X11` option, and a `GNOME` option that needs the `X11` option to be selected to build.

    OPTIONS_DEFINE=	X11 GNOME
    OPTIONS_DEFAULT=	X11

    X11_USES=	xorg
    X11_USE=	xorg=xi,xextproto
    GNOME_USE=	gnome=gtk30
    GNOME_IMPLIES=	X11

#### 5.13.3.8. `OPT_PREVENTS` and `OPT_PREVENTS_MSG`

Provides a way to add conflicts between options.

When OPT is selected, all the options listed in `OPT_PREVENTS` must be un-selected. If `OPT_PREVENTS_MSG` is set and a conflict is triggered, its content will be shown explaining why they conflict. For example:

    OPTIONS_DEFINE=	OPT1 OPT2
    OPT1_PREVENTS=	OPT2
    OPT1_PREVENTS_MSG=	OPT1 and OPT2 enable conflicting options

Is roughly equivalent to:

    OPTIONS_DEFINE=	OPT1 OPT2

    .include <bsd.port.options.mk>

    .if ${PORT_OPTIONS:MOPT2} && ${PORT_OPTIONS:MOPT1}
    BROKEN=	Option OPT1 conflicts with OPT2 (select only one)
    .endif

The only difference is that the first one will write an error after running `make config`, suggesting changing the selected options.

例 45. Simple Use of `OPT_PREVENTS`

This port has `X509` and `SCTP` options. Both options add patches, but the patches conflict with each other, so they cannot be selected at the same time.

    OPTIONS_DEFINE=	X509 SCTP

    SCTP_PATCHFILES=	${PORTNAME}-6.8p1-sctp-2573.patch.gz:-p1
    SCTP_CONFIGURE_WITH=	sctp

    X509_PATCH_SITES=	http://www.roumenpetrov.info/openssh/x509/:x509
    X509_PATCHFILES=	${PORTNAME}-7.0p1+x509-8.5.diff.gz:-p1:x509
    X509_PREVENTS=		SCTP
    X509_PREVENTS_MSG=	X509 and SCTP patches conflict

#### 5.13.3.9. `OPT_VARS` and `OPT_VARS_OFF`

Provides a generic way to set and append to variables.

| Before using `OPT_VARS` and `OPT_VARS_OFF`, see if there is already a more specific helper available in Generic Variables Replacement, `OPT_VARIABLE` and `OPT_VARIABLE_OFF`.

When option OPT is selected, and `OPT_VARS` defined, `key=value` and `key+=value` pairs are evaluated from `OPT_VARS`. An `=` cause the existing value of `KEY` to be overwritten, an `+=` appends to the value. `OPT_VARS_OFF` works the same way, but when `OPT` is not selected.

    OPTIONS_DEFINE=	OPT1 OPT2 OPT3
    OPT1_VARS=	also_build+=bin1
    OPT2_VARS=	also_build+=bin2
    OPT3_VARS=	bin3_build=yes
    OPT3_VARS_OFF=	bin3_build=no

    MAKE_ARGS=	ALSO_BUILD="${ALSO_BUILD}" BIN3_BUILD="${BIN3_BUILD}"

is equivalent to:

    OPTIONS_DEFINE=	OPT1 OPT2

    MAKE_ARGS=	ALSO_BUILD="${ALSO_BUILD}" BIN3_BUILD="${BIN3_BUILD}"

    .include <bsd.port.options.mk>

    .if ${PORT_OPTIONS:MOPT1}
    ALSO_BUILD+=	bin1
    .endif

    .if ${PORT_OPTIONS:MOPT2}
    ALSO_BUILD+=	bin2
    .endif

    .if ${PORT_OPTIONS:MOPT2}
    BIN3_BUILD=	yes
    .else
    BIN3_BUILD=	no
    .endif

| Values containing whitespace must be enclosed in quotes:
    OPT_VARS=	foo="bar baz"
This is due to the way make(1) variable expansion deals with whitespace. When `OPT_VARS= foo=bar baz` is expanded, the variable ends up containing two strings, `foo=bar` and `baz`. But the submitter probably intended there to be only one string, `foo=bar baz`. Quoting the value prevents whitespace from being used as a delimiter. Also, do not add extra spaces after the `var=` sign and before the value, it would also be split into two strings. This will not work:
    OPT_VARS=	foo=	bar

#### 5.13.3.10. Dependencies, `OPT_DEPTYPE` and `OPT_DEPTYPE_OFF`

For any of these dependency types:

- `PKG_DEPENDS`

- `EXTRACT_DEPENDS`

- `PATCH_DEPENDS`

- `FETCH_DEPENDS`

- `BUILD_DEPENDS`

- `LIB_DEPENDS`

- `RUN_DEPENDS`

When option OPT is selected, the value of `OPT_DEPTYPE`, if defined, is appended to `DEPTYPE`. `OPT_DEPTYPE_OFF` works the same, but when `OPT` is not selected. For example:

    OPTIONS_DEFINE=	OPT1
    OPT1_LIB_DEPENDS=	liba.so:devel/a
    OPT1_LIB_DEPENDS_OFF=	libb.so:devel/b

is equivalent to:

    OPTIONS_DEFINE=	OPT1

    .include <bsd.port.options.mk>

    .if ${PORT_OPTIONS:MOPT1}
    LIB_DEPENDS+=	liba.so:devel/a
    .else
    LIB_DEPENDS+=	libb.so:devel/b
    .endif

#### 5.13.3.11. Generic Variables Replacement, `OPT_VARIABLE` and `OPT_VARIABLE_OFF`

For any of these variables:

- `ALL_TARGET`

- `BINARY_ALIAS`

- `BROKEN`

- `CATEGORIES`

- `CFLAGS`

- `CONFIGURE_ENV`

- `CONFLICTS`

- `CONFLICTS_BUILD`

- `CONFLICTS_INSTALL`

- `CPPFLAGS`

- `CXXFLAGS`

- `DESKTOP_ENTRIES`

- `DISTFILES`

- `EXTRACT_ONLY`

- `EXTRA_PATCHES`

- `GH_ACCOUNT`

- `GH_PROJECT`

- `GH_SUBDIR`

- `GH_TAGNAME`

- `GH_TUPLE`

- `GL_ACCOUNT`

- `GL_COMMIT`

- `GL_PROJECT`

- `GL_SITE`

- `GL_SUBDIR`

- `GL_TUPLE`

- `IGNORE`

- `INFO`

- `INSTALL_TARGET`

- `LDFLAGS`

- `LIBS`

- `MAKE_ARGS`

- `MAKE_ENV`

- `MASTER_SITES`

- `PATCHFILES`

- `PATCH_SITES`

- `PLIST_DIRS`

- `PLIST_FILES`

- `PLIST_SUB`

- `PORTDOCS`

- `PORTEXAMPLES`

- `SUB_FILES`

- `SUB_LIST`

- `TEST_TARGET`

- `USES`

When option OPT is selected, the value of `OPT_ABOVEVARIABLE`, if defined, is appended to `ABOVEVARIABLE`. `OPT_ABOVEVARIABLE_OFF` works the same way, but when `OPT` is not selected. For example:

    OPTIONS_DEFINE=	OPT1
    OPT1_USES=	gmake
    OPT1_CFLAGS_OFF=	-DTEST

is equivalent to:

    OPTIONS_DEFINE=	OPT1

    .include <bsd.port.options.mk>

    .if ${PORT_OPTIONS:MOPT1}
    USES+=		gmake
    .else
    CFLAGS+=	-DTEST
    .endif

| Some variables are not in this list, in particular `PKGNAMEPREFIX` and `PKGNAMESUFFIX`. This is intentional. A port must not change its name when its option set changes.

| Some of these variables, at least `ALL_TARGET`, `DISTFILES` and `INSTALL_TARGET`, have their default values set after the options are processed. With these lines in the Makefile:
    ALL_TARGET=	all

    DOCS_ALL_TARGET=	doc
If the `DOCS` option is enabled, `ALL_TARGET` will have a final value of `all doc`; if the option is disabled, it would have a value of `all`. With only the options helper line in the Makefile:
    DOCS_ALL_TARGET=	doc
If the `DOCS` option is enabled, `ALL_TARGET` will have a final value of `doc`; if the option is disabled, it would have a value of `all`.

#### 5.13.3.12. Additional Build Targets, `target-OPT-on` and `target-OPT-off`

These Makefile targets can accept optional extra build targets:

- `pre-fetch`

- `do-fetch`

- `post-fetch`

- `pre-extract`

- `do-extract`

- `post-extract`

- `pre-patch`

- `do-patch`

- `post-patch`

- `pre-configure`

- `do-configure`

- `post-configure`

- `pre-build`

- `do-build`

- `post-build`

- `pre-install`

- `do-install`

- `post-install`

- `post-stage`

- `pre-package`

- `do-package`

- `post-package`

When option OPT is selected, the target `TARGET-OPT-on`, if defined, is executed after `TARGET`. `TARGET-OPT-off` works the same way, but when `OPT` is not selected. For example:

    OPTIONS_DEFINE=	OPT1

    post-patch-OPT1-on:
    	@${REINPLACE_CMD} -e '/opt1/s|/usr/bin/|${EXAMPLESDIR}/|' ${WRKSRC}/Makefile

    post-patch-OPT1-off:
    	@${REINPLACE_CMD} -e '/opt1/s|/usr/bin/|${PREFIX}/bin/|' ${WRKSRC}/Makefile

is equivalent to:

    OPTIONS_DEFINE=	OPT1

    .include <bsd.port.options.mk>

    post-patch:
    .if ${PORT_OPTIONS:MOPT1}
    	@${REINPLACE_CMD} -e '/opt1/s|/usr/bin/|${EXAMPLESDIR}/|' ${WRKSRC}/Makefile
    .else
    	@${REINPLACE_CMD} -e '/opt1/s|/usr/bin/|${PREFIX}/bin/|' ${WRKSRC}/Makefile
    .endif

## 5.14. Specifying the Working Directory

Each port is extracted into a working directory, which must be writable. The ports system defaults to having `DISTFILES` unpack in to a directory called `${DISTNAME}`. In other words, if the Makefile has:

    PORTNAME=	foo
    DISTVERSION=	1.0

then the port’s distribution files contain a top-level directory, foo-1.0, and the rest of the files are located under that directory.

A number of variables can be overridden if that is not the case.

### 5.14.1. `WRKSRC`

The variable lists the name of the directory that is created when the application’s distfiles are extracted. If our previous example extracted into a directory called foo (and not foo-1.0) write:

    WRKSRC=	${WRKDIR}/foo

or possibly

    WRKSRC=	${WRKDIR}/${PORTNAME}

### 5.14.2. `WRKSRC_SUBDIR`

If the source files needed for the port are in a subdirectory of the extracted distribution file, set `WRKSRC_SUBDIR` to that directory.

    WRKSRC_SUBDIR=	src

### 5.14.3. `NO_WRKSUBDIR`

If the port does not extract in to a subdirectory at all, then set `NO_WRKSUBDIR` to indicate that.

    NO_WRKSUBDIR=	yes

| Because `WRKDIR` is the only directory that is supposed to be writable during the build, and is used to store many files recording the status of the build, the port’s extraction will be forced into a subdirectory.

## 5.15. Conflict Handling

There are three different variables to register a conflict between packages and ports: `CONFLICTS`, `CONFLICTS_INSTALL` and `CONFLICTS_BUILD`.

| The conflict variables automatically set the variable `IGNORE`, which is more fully documented in Marking a Port Not Installable with `BROKEN`.

When removing one of several conflicting ports, it is advisable to retain `CONFLICTS` in those other ports for a few months to cater for users who only update once in a while.

`CONFLICTS_INSTALL`

  If the package cannot coexist with other packages (because of file conflicts, runtime incompatibilities, etc.). `CONFLICTS_INSTALL` check is done after the build stage and prior to the install stage.

`CONFLICTS_BUILD`

  If the port cannot be built when other specific ports are already installed. Build conflicts are not recorded in the resulting package.

`CONFLICTS`

  If the port cannot be built if a certain port is already installed and the resulting package cannot coexist with the other package. `CONFLICTS` check is done prior to the build stage and prior to the install stage.

The most common content of one of these variable is the package base of another port. The package base is the package name without the appended version, it can be obtained by running `make -V PKGBASE`.

例 46. Basic usage of `CONFLICTS*`

dns/bind99 cannot be installed if dns/bind910 is present because they install same files. First gather the package base to use:

    % make -C dns/bind99 -V PKGBASE
    bind99
    % make -C dns/bind910 -V PKGBASE
    bind910

Then add to the Makefile of dns/bind99:

    CONFLICTS_INSTALL=	bind910

And add to the Makefile of dns/bind910:

    CONFLICTS_INSTALL=	bind99

Sometimes, only certain versions of another port are incompatible. When this is the case, use the full package name including the version. If necessary, use shell globs like `*` and `?` so that all necessary versions are matched.

例 47. Using `CONFLICTS*` With Globs.

From versions from 2.0 and up-to 2.4.1_2, deskutils/gnotime used to install a bundled version of databases/qof.

To reflect this past, the Makefile of databases/qof contains:

    CONFLICTS_INSTALL=	gnotime-2.[0-3]* \
    			gnotime-2.4.0* gnotime-2.4.1 \
    			gnotime-2.4.1_[12]

The first entry match versions `2.0` through `2.3`, the second all the revisions of `2.4.0`, the third the exact `2.4.1` version, and the last the first and second revisions of the `2.4.1` version.

deskutils/gnotime does not have any conflicts line because its current version does not conflict with anything else.

The variable `DISABLE_CONFLICTS` may be temporarily set when making targets that are not affected by conflicts. The variable is not to be set in port Makefiles.

    % make -DDISABLE_CONFLICTS patch

## 5.16. Installing Files

| The `install` phase is very important to the end user because it adds files to their system. All the additional commands run in the port Makefile's `*-install` targets should be echoed to the screen. Do not silence these commands with `@` or `.SILENT`.

### 5.16.1. `INSTALL_*` Macros

Use the macros provided in bsd.port.mk to ensure correct modes of files in the port’s `*-install` targets. Set ownership directly in pkg-plist with the corresponding entries, such as `@(owner,group,)`, `@owner owner`, and `@group group`. These operators work until overridden, or until the end of pkg-plist, so remember to reset them after they are no longer needed. The default ownership is `root:wheel`. See Base Keywords for more information.

- `INSTALL_PROGRAM` is a command to install binary executables.

- `INSTALL_SCRIPT` is a command to install executable scripts.

- `INSTALL_LIB` is a command to install shared libraries (but not static libraries).

- `INSTALL_KLD` is a command to install kernel loadable modules. Some architectures do not like having the modules stripped, so use this command instead of `INSTALL_PROGRAM`.

- `INSTALL_DATA` is a command to install sharable data, including static libraries.

- `INSTALL_MAN` is a command to install manpages and other documentation (it does not compress anything).

These variables are set to the install(1) command with the appropriate flags for each situation.

| Do not use `INSTALL_LIB` to install static libraries, because stripping them renders them useless. Use `INSTALL_DATA` instead.

### 5.16.2. Stripping Binaries and Shared Libraries

Installed binaries should be stripped. Do not strip binaries manually unless absolutely required. The `INSTALL_PROGRAM` macro installs and strips a binary at the same time. The `INSTALL_LIB` macro does the same thing to shared libraries.

When a file must be stripped, but neither `INSTALL_PROGRAM` nor `INSTALL_LIB` macros are desirable, `${STRIP_CMD}` strips the program or shared library. This is typically done within the `post-install` target. For example:

    post-install:
    	${STRIP_CMD} ${STAGEDIR}${PREFIX}/bin/xdl

When multiple files need to be stripped:

    post-install:
    .for l in geometry media body track world
    	${STRIP_CMD} ${STAGEDIR}${PREFIX}/lib/lib${PORTNAME}-${l}.so.0
    .endfor

Use file(1) on a file to determine if it has been stripped. Binaries are reported by file(1) as `stripped`, or `not stripped`. Additionally, strip(1) will detect programs that have already been stripped and exit cleanly.

| When `WITH_DEBUG` is defined, elf files must not be stripped. The variables (`STRIP_CMD`, `INSTALL_PROGRAM`, `INSTALL_LIB`, …​) and `USES` provided by the framework handle this automatically. Some software, add `-s` to their `LDFLAGS`, in this case, either remove `-s` if `WITH_DEBUG` is set, or remove it unconditionally and use `STRIP_CMD` in `post-install`.

### 5.16.3. Installing a Whole Tree of Files

Sometimes, a large number of files must be installed while preserving their hierarchical organization. For example, copying over a whole directory tree from `WRKSRC` to a target directory under `PREFIX`. Note that `PREFIX`, `EXAMPLESDIR`, `DATADIR`, and other path variables must always be prepended with `STAGEDIR` to respect staging (see Staging).

Two macros exist for this situation. The advantage of using these macros instead of `cp` is that they guarantee proper file ownership and permissions on target files. The first macro, `COPYTREE_BIN`, will set all the installed files to be executable, thus being suitable for installing into PREFIX/bin. The second macro, `COPYTREE_SHARE`, does not set executable permissions on files, and is therefore suitable for installing files under PREFIX/share target.

    post-install:
    	${MKDIR} ${STAGEDIR}${EXAMPLESDIR}
    	(cd ${WRKSRC}/examples && ${COPYTREE_SHARE} . ${STAGEDIR}${EXAMPLESDIR})

This example will install the contents of the examples directory in the vendor distfile to the proper examples location of the port.

    post-install:
    	${MKDIR} ${STAGEDIR}${DATADIR}/summer
    	(cd ${WRKSRC}/temperatures && ${COPYTREE_SHARE} "June July August" ${STAGEDIR}${DATADIR}/summer)

And this example will install the data of summer months to the summer subdirectory of a DATADIR.

Additional `find` arguments can be passed via the third argument to `COPYTREE_*` macros. For example, to install all files from the first example except Makefiles, one can use these commands.

    post-install:
    	${MKDIR} ${STAGEDIR}${EXAMPLESDIR}
    	(cd ${WRKSRC}/examples && \
    	${COPYTREE_SHARE} . ${STAGEDIR}${EXAMPLESDIR} "! -name Makefile")

These macros do not add the installed files to pkg-plist. They must be added manually. For optional documentation (`PORTDOCS`, see Install Additional Documentation) and examples (`PORTEXAMPLES`), the `%%PORTDOCS%%` or `%%PORTEXAMPLES%%` prefixes must be prepended in pkg-plist.

### 5.16.4. Install Additional Documentation

If the software has some documentation other than the standard man and info pages that is useful for the user, install it under `DOCSDIR`. This can be done, like the previous item, in the `post-install` target.

Create a new directory for the port. The directory name is `DOCSDIR`. This usually equals `PORTNAME`. However, if the user might want different versions of the port to be installed at the same time, the whole `PKGNAME` can be used.

Since only the files listed in pkg-plist are installed, it is safe to always install documentation to `STAGEDIR` (see Staging). Hence `.if` blocks are only needed when the installed files are large enough to cause significant I/O overhead.

    post-install:
    	${MKDIR} ${STAGEDIR}${DOCSDIR}
    	${INSTALL_MAN} ${WRKSRC}/docs/xvdocs.ps ${STAGEDIR}${DOCSDIR}

On the other hand, if there is a DOCS option in the port, install the documentation in a `post-install-DOCS-on` target. These targets are described in Additional Build Targets, `target-OPT-on` and `target-OPT-off`.

Here are some handy variables and how they are expanded by default when used in the Makefile:

- `DATADIR` gets expanded to PREFIX/shared/PORTNAME.

- `DATADIR_REL` gets expanded to share/PORTNAME.

- `DOCSDIR` gets expanded to PREFIX/shared/doc/PORTNAME.

- `DOCSDIR_REL` gets expanded to share/doc/PORTNAME.

- `EXAMPLESDIR` gets expanded to PREFIX/shared/examples/PORTNAME.

- `EXAMPLESDIR_REL` gets expanded to share/examples/PORTNAME.

| The `DOCS` option only controls additional documentation installed in `DOCSDIR`. It does not apply to standard man pages and info pages. Things installed in `EXAMPLESDIR` are controlled by the `EXAMPLES` option.

These variables are exported to `PLIST_SUB`. Their values will appear there as pathnames relative to PREFIX if possible. That is, share/doc/PORTNAME will be substituted for `%%DOCSDIR%%` in the packing list by default, and so on. (See more on pkg-plist substitution here.)

All conditionally installed documentation files and directories are included in pkg-plist with the `%%PORTDOCS%%` prefix, for example:

    %%PORTDOCS%%%%DOCSDIR%%/AUTHORS
    %%PORTDOCS%%%%DOCSDIR%%/CONTACT

As an alternative to enumerating the documentation files in pkg-plist, a port can set the variable `PORTDOCS` to a list of file names and shell glob patterns to add to the final packing list. The names will be relative to `DOCSDIR`. Therefore, a port that utilizes `PORTDOCS`, and uses a non-default location for its documentation, must set `DOCSDIR` accordingly. If a directory is listed in `PORTDOCS` or matched by a glob pattern from this variable, the entire subtree of contained files and directories will be registered in the final packing list. If the `DOCS` option has been unset then files and directories listed in `PORTDOCS` would not be installed or added to port packing list. Installing the documentation at `PORTDOCS` as shown above remains up to the port itself. A typical example of utilizing `PORTDOCS`:

    PORTDOCS=	README.* ChangeLog docs/*

| The equivalents of `PORTDOCS` for files installed under `DATADIR` and `EXAMPLESDIR` are `PORTDATA` and `PORTEXAMPLES`, respectively. The contents of pkg-message are displayed upon installation. See the section on using pkg-message for details. pkg-message does not need to be added to pkg-plist.

### 5.16.5. Subdirectories Under `PREFIX`

Try to let the port put things in the right subdirectories of `PREFIX`. Some ports lump everything and put it in the subdirectory with the port’s name, which is incorrect. Also, many ports put everything except binaries, header files and manual pages in a subdirectory of lib, which does not work well with the BSD paradigm. Many of the files must be moved to one of these directories: etc (setup/configuration files), libexec (executables started internally), sbin (executables for superusers/managers), info (documentation for info browser) or share (architecture independent files). See hier(7) for details; the rules governing /usr pretty much apply to /usr/local too. The exception are ports dealing with USENET "news". They may use PREFIX/news as a destination for their files.

## 5.17. Use `BINARY_ALIAS` to Rename Commands Instead of Patching the Build

When `BINARY_ALIAS` is defined it will create symlinks of the given commands in a directory which will be prepended to `PATH`.

Use it to substitute hardcoded commands the build phase relies on without having to patch any build files.

例 48. Using `BINARY_ALIAS` to Make `gsed` Available as `sed`

Some ports expect `sed` to behave like GNU sed and use features that sed(1) does not provide. GNU sed is available from textproc/gsed on FreeBSD.

Use `BINARY_ALIAS` to substitute `sed` with `gsed` for the duration of the build:

    BUILD_DEPENDS=	gsed:textproc/gsed
    ...
    BINARY_ALIAS=	sed=gsed

例 49. Using `BINARY_ALIAS` to Provide Aliases for Hardcoded `python3` Commands

A port that has a hardcoded reference to `python3` in its build scripts will need to have it available in `PATH` at build time. Use `BINARY_ALIAS` to create an alias that points to the right Python 3 binary:

    USES=	python:3.4+,build
    ...
    BINARY_ALIAS=	python3=${PYTHON_CMD}

See Using Python for more information about `USES=python`.

| Binary aliases are created after the dependencies provided via `BUILD_DEPENDS` and `LIB_DEPENDS` are processed and before the `configure` target. This leads to various limitations. For example, programs installed via `TEST_DEPENDS` cannot be used to create a binary alias as test dependencies specified this way are processed after binary aliases are created.

最後修改於: March 9, 2024 由 Danilo G. Baio

Prev
Home
Next