FreeBSD Handbook : Installing Applications: The Ports collection : Making a port yourself : Do's and Dont's
Previous: Upgrading
Next: A Sample Makefile

4.7.8. Do's and Dont's

Here is a list of common do's and dont's that you encounter during the porting process. You should check your own port against this list, but you can also check ports in the PR database that others have submitted. Submit any comments on ports you check as described in Bug Reports and General Commentary. Checking ports in the PR database will both make it faster for us to commit them, and prove that you know what you are doing.

4.7.8.1. Strip Binaries

Do strip binaries. If the original source already strips the binaries, fine; otherwise you should add a post-install rule to do it yourself. Here is an example:

 post-install:
	 strip ${PREFIX}/bin/xdl

Use the file command on the installed executable to check whether the binary is stripped or not. If it does not say `not stripped', it is stripped.

4.7.8.2. INSTALL_* macros

Do use the macros provided in bsd.port.mk to ensure correct modes and ownership of files in your own *-install targets. They are:

These are basically the install command with all the appropriate flags. See below for an example on how to use them.

4.7.8.3. WRKDIR

Do not write anything to files outside WKRDIR. WRKDIR is the only place that is guaranteed to be writable during the port build (see compiling ports from CDROM for an example of building ports from a read-only tree). If you need to modify some file in ${PKGDIR}, do so by redefining a variable, not by writing over it.

4.7.8.4. WRKDIRPREFIX

Make sure your port honors WRKDIRPREFIX. (Most ports don't have to worry about this.) In particular, if you are referring to a ${WRKDIR} of another port, note that the correct location is ${WRKDIRPREFIX}${PORTSDIR}/subdir/name/work, not ${PORTSDIR}/subdir/name/work or ${.CURDIR}/../../subdir/name/work or some such.

Also, if you are defining WRKDIR yourself, make sure you prepend ${WRKDIRPREFIX}${.CURDIR} in the front.

4.7.8.5. Differentiating operating systems and OS versions

You may come across code that needs modifications or conditional compilation based upon what version of UNIX it is running under. If you need to make such changes to the code for conditional compilation, make sure you make the changes as general as possible so that we can back-port code to FreeBSD 1.x systems and cross-port to other BSD systems such as 4.4BSD from CSRG, BSD/386, 386BSD, NetBSD, and OpenBSD.

The preferred way to tell 4.3BSD/Reno (1990) and newer versions of the BSD code apart is by using the `BSD' macro defined in <sys/param.h>. Hopefully that file is already included; if not, add the code:

#if (defined(__unix__) || defined(unix)) && !defined(USG)
#include <sys/param.h>
#endif

to the proper place in the .c file. We believe that every system that defines these two symbols has sys/param.h. If you find a system that doesn't, we would like to know. Please send mail to the FreeBSD ports mailing list <freebsd-ports@FreeBSD.ORG>.

Another way is to use the GNU Autoconf style of doing this:

#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif

Don't forget to add -DHAVE_SYS_PARAM_H to the CFLAGS in the Makefile for this method.

Once you have <sys/param.h> included, you may use:

#if (defined(BSD) && (BSD >= 199103))

to detect if the code is being compiled on a 4.3 Net2 code base or newer (e.g. FreeBSD 1.x, 4.3/Reno, NetBSD 0.9, 386BSD, BSD/386 1.1 and below).

Use:

#if (defined(BSD) && (BSD >= 199306))

to detect if the code is being compiled on a 4.4 code base or newer (e.g. FreeBSD 2.x, 4.4, NetBSD 1.0, BSD/386 2.0 or above).

The value of the BSD macro is 199506 for the 4.4BSD-Lite2 code base. This is stated for informational purposes only. It should not be used to distinguish between versions of FreeBSD based only on 4.4-Lite vs. versions that have merged in changes from 4.4-Lite2. The __FreeBSD__ macro should be used instead.

Use sparingly:

In the hundreds of ports that have been done, there have only been one or two cases where __FreeBSD__ should have been used. Just because an earlier port screwed up and used it in the wrong place does not mean you should do so too.

4.7.8.6. Writing something after bsd.port.mk

Do not write anything after the `.include <bsd.port.mk>' line. It usually can be avoided by including bsd.port.pre.mk somewhere in the middle of your Makefile and bsd.port.post.mk at the end. (Note that you need to include either the pre.mk/post.mk pair or bsd.port.mk only; don't mix those two.) The former only defines a few variables, which can be used in tests in Makefiles; the latter defines the rest. Here are some important variables defined in bsd.port.pre.mk. (This is not the entire list; please read bsd.port.mk for the complete list.)

${ARCH}

The architecture, as returned by `uname -m' (e.g., `i386').

${OPSYS}

The operating system type, as returned by `uname -s' (e.g., `FreeBSD').

${OSREL}

The release version of the operating system (e.g., `2.1.5', `2.2.7').

${OSVERSION}

The numeric version of the operating system, same as __FreeBSD_version above.

${PORTOBJFORMAT}

The object format of the system (`aout' or `elf').

${LOCALBASE}

The base of the `local' tree (e.g., `/usr/local/').

${X11BASE}

The base of the `X11' tree (e.g., `/usr/X11R6/').

${PREFIX}

Where the port installs itself (see more on PREFIX).

Note: if you have to define the variables USE_IMAKE, USE_X_PREFIX or MASTERDIR, do so before including bsd.port.pre.mk; everything else can be either before or after bsd.port.pre.mk. Here are some examples of things you can write after bsd.port.pre.mk:

# no need to compile lang/perl5 if perl5 is already in system
.if ${OSVERSION} > 300003
BROKEN= perl is in system
.endif

# only one shlib version number for ELF
.if ${PORTOBJFORMAT} == "elf"
TCL_LIB_FILE=	${TCL_LIB}.${SHLIB_MAJOR}
.else
TCL_LIB_FILE=	${TCL_LIB}.${SHLIB_MAJOR}.${SHLIB_MINOR}
.endif

# software already makes link for ELF, but not for a.out
post-install:
.if ${PORTOBJFORMAT} == "aout"
	${LN} -sf liblinpack.so.1.0 ${PREFIX}/lib/liblinpack.so
.endif

4.7.8.7. Install additional documentation

If your software has some documentation other than the standard man and info pages that you think is useful for the user, install it under ${PREFIX}/share/doc. This can be done, like the previous item, in the post-install target.

Create a new directory for your port. The directory name should reflect what the port is. This usually means ${PKGNAME} minus the version part. However, if you think the user might want different versions of the port to be installed at the same time, you can use the whole ${PKGNAME}.

Make the installation dependent on the variable NOPORTDOCS so that users can disable it in /etc/make.conf, like this:

 post-install:
 .if !defined(NOPORTDOCS)
	 ${MKDIR} ${PREFIX}/share/doc/xv
	 ${INSTALL_MAN} ${WRKSRC}/docs/xvdocs.ps ${PREFIX}/share/doc/xv
 .endif

Do not forget to add them to pkg/PLIST too! (Do not worry about NOPORTDOCS here; there is currently no way for the packages to read variables from /etc/make.conf.)

Also, you can use the pkg/MESSAGE file to display messages upon installation. See the using pkg/MESSAGE section for details.

4.7.8.8. DIST_SUBDIR

Do not let your port clutter /usr/ports/distfiles. If your port requires a lot of files to be fetched, or contains a file that has a name that might conflict with other ports (e.g., `Makefile'), set ${DIST_SUBDIR} to the name of the port (${PKGNAME} without the version part should work 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 your port into that subdirectory.

It will also look at the subdirectory with the same name on the backup master site at ftp.freebsd.org. (Setting ${DISTDIR} explicitly in your Makefile will not accomplish this, so please use ${DIST_SUBDIR}.)

Note this does not affect the ${MASTER_SITES} you define in your Makefile.

4.7.8.9. RCS strings

Do not put RCS strings in patches. CVS will mangle them when we put the files into the ports tree, and when we check them out again, they will come out different and the patch will fail. RCS strings are surrounded by dollar (`$') signs, and typically start with `$Id' or `$RCS'.

4.7.8.10. Recursive diff

Using the recurse (`-r') option to diff to generate patches is fine, but please take a look at the resulting patches to make sure you don't have any unnecessary junk in there. In particular, diffs between two backup files, Makefiles when the port uses Imake or GNU configure, etc., are unnecessary and should be deleted. If you had to edit configure.in and run autoconf to regenerate configure, do not take the diffs of configure (it often grows to a few thousand lines!); define USE_AUTOCONF=yes and take the diffs of configure.in.

Also, if you had to delete a file, then you can do it in the post-extract target rather than as part of the patch. Once you are happy with the resulting diff, please split it up into one source file per patch file.

4.7.8.11. PREFIX

Do try to make your port install relative to ${PREFIX}. (The value of this variable will be set to ${LOCALBASE} (default /usr/local), unless ${USE_X_PREFIX} or ${USE_IMAKE} is set, in which case it will be ${X11BASE} (default /usr/X11R6).)

Not hard-coding `/usr/local' or `/usr/X11R6' anywhere in the source will make the port much more flexible and able to cater to the needs of other sites. For X ports that use imake, this is automatic; otherwise, this can often be done by simply replacing the occurrences of `/usr/local' (or `/usr/X11R6' for X ports that do not use imake) in the various scripts/Makefiles in the port to read `${PREFIX}', as this variable is automatically passed down to every stage of the build and install processes.

Do not set USE_X_PREFIX unless your port truly requires it (i.e. it links against X libs or it needs to reference files in ${X11BASE}).

The variable ${PREFIX} can be reassigned in your Makefile or in the user's environment. However, it is strongly discouraged for individual ports to set this variable explicitly in the Makefiles.

Also, refer to programs/files from other ports with the variables mentioned above, not explicit pathnames. For instance, if your port requires a macro PAGER to be the full pathname of less, use the compiler flag:

-DPAGER=\"${PREFIX}/bin/less\"
or
-DPAGER=\"${LOCALBASE}/bin/less\"
if this is an X port, instead of
-DPAGER=\"/usr/local/bin/less\".
This way it will have a better chance of working if the system administrator has moved the whole `/usr/local' tree somewhere else.

4.7.8.12. Subdirectories

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 the a subdirectory of `lib', which does not bode well with the BSD paradigm. Many of the files should be moved to one of the following: `etc' (setup/configuration files), `libexec' (executables started internally), `sbin' (executables for superusers/managers), `info' (documentation for info browser) or `share' (architecture independent files). See man hier(7) for details; the rules governing /usr pretty much apply to /usr/local too. The exceptions are ports dealing with USENET `news'. They may use ${PREFIX}/news as a destination for their files.

4.7.8.13. Cleaning up empty directories

Do make your ports clean up after themselves when they are deinstalled. This is usually accomplished by adding @dirrm lines for all directories that are specifically created by the port. Note you need to delete subdirectories before you can delete parent directories, as in:

 :
lib/X11/oneko/pixmaps/cat.xpm
lib/X11/oneko/sounds/cat.au
 :
@dirrm lib/X11/oneko/pixmaps
@dirrm lib/X11/oneko/sounds
@dirrm lib/X11/oneko

However, sometimes @dirrm will give you errors because other ports also share the same subdirectory. You can call rmdir from @unexec to remove only empty directories without warning:

 :
@unexec rmdir %D/share/doc/gimp 2>/dev/null || true
This will neither print any error messages nor cause pkg_delete to exit abnormally even if ${PREFIX}/share/doc/gimp is not empty due to other ports installing some files in there.

4.7.8.14. UIDs

If your port requires a certain user to be on the installed system, let the pkg/INSTALL script call pw to create it automatically. Look at net/cvsup-mirror for an example.

If your port must use the same user/group ID number when it is installed as a binary package as when it was compiled, then you must choose a free UID from 50 to 99 and register it below. Look at japanese/Wnn for an example.

Make sure you don't use a UID already used by the system or other ports. This is the current list of UIDs between 50 and 99.

majordom:*:54:54:Majordomo Pseudo User:/usr/local/majordomo:/nonexistent
cyrus:*:60:60:the cyrus mail server:/nonexistent:/nonexistent
gnats:*:61:1:GNATS database owner:/usr/local/share/gnats/gnats-db:/bin/sh
uucp:*:66:66:UUCP pseudo-user:/var/spool/uucppublic:/usr/libexec/uucp/uucico
xten:*:67:67:X-10 daemon:/usr/local/xten:/nonexistent
pop:*:68:6:Post Office Owner (popper):/nonexistent:/nonexistent
wnn:*:69:7:Wnn:/nonexistent:/nonexistent
ifmail:*:70:66:Ifmail user:/nonexistent:/nonexistent
pgsql:*:70:70:PostgreSQL pseudo-user:/usr/local/pgsql:/bin/sh
ircd:*:72:72:IRCd hybrid:/nonexistent:/nonexistent
alias:*:81:81:QMail user:/var/qmail/alias:/nonexistent
qmaill:*:83:81:QMail user:/var/qmail:/nonexistent
qmaild:*:82:81:QMail user:/var/qmail:/nonexistent
qmailq:*:85:82:QMail user:/var/qmail:/nonexistent
qmails:*:87:82:QMail user:/var/qmail:/nonexistent
qmailp:*:84:81:QMail user:/var/qmail:/nonexistent
qmailr:*:86:82:QMail user:/var/qmail:/nonexistent
msql:*:87:87:mSQL-2 pseudo-user:/var/db/msqldb:/bin/sh

Please include a notice when you submit a port (or an upgrade) that reserves a new UID or GID in this range. This allows us to keep the list of reserved IDs up to date.

4.7.8.15. Do things rationally

The Makefile should do things simply and reasonably. If you can make it a couple of lines shorter or more readable, then do so. Examples include using a make `.if' construct instead of a shell `if' construct, not redefining do-extract if you can redefine ${EXTRACT*} instead, and using $GNU_CONFIGURE instead of `CONFIGURE_ARGS += --prefix=${PREFIX}'.

4.7.8.16. Respect CFLAGS

The port should respect the ${CFLAGS} variable. If it doesn't, please add `NO_PACKAGE=ignores cflags' to the Makefile.

4.7.8.17. Configuration files

If your port requires some configuration files in ${PREFIX}/etc, do not just install them and list them in pkg/PLIST. That will cause pkg_delete to delete files carefully edited by the user and a new installation to wipe them out.

Instead, install sample files with a suffix (`<filename>.sample' will work well) and print out a message pointing out that the user has to copy and edit the file before the software can be made to work.

4.7.8.18. Portlint

Do check your port with portlint before you submit or commit it.

4.7.8.19. Feedback

Do send applicable changes/patches to the original author/maintainer for inclusion in next release of the code. This will only make your job that much easier for the next release.

4.7.8.20. Miscellanea

The files pkg/DESCR, pkg/COMMENT, and pkg/PLIST should each be double-checked. If you are reviewing a port and feel they can be worded better, do so.

Don't copy more copies of the GNU General Public License into our system, please.

Please be careful to note any legal issues! Don't let us illegally distribute software!

4.7.8.21. If you are stuck....

Do look at existing examples and the bsd.port.mk file before asking us questions! ;)

Do ask us questions if you have any trouble! Do not just beat your head against a wall! :)


FreeBSD Handbook : Installing Applications: The Ports collection : Making a port yourself : Do's and Dont's
Previous: Upgrading
Next: A Sample Makefile