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.
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.
Do use the macros provided in bsd.port.mk
to
ensure correct modes and ownership of files in your own
*-install targets. They are:
${INSTALL_PROGRAM}
is a command to install
binary executables.${INSTALL_SCRIPT}
is a command to install
executable scripts.${INSTALL_DATA}
is a command to install
sharable data.${INSTALL_MAN}
is a command to install
manpages and other documentation (it doesn't compress anything).These are basically the install
command with all
the appropriate flags. See below for an example on how to
use them.
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.
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.
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:
__FreeBSD__
is defined in all versions of
FreeBSD. Use it if the change you are making ONLY affects
FreeBSD. Porting gotchas like the use of
sys_errlist[]
vs strerror()
are
Berkeleyisms, not FreeBSD changes.
__FreeBSD__
is defined to be
2
. In earlier versions, it is 1
. Later
versions will bump it to match their major version number.
BSD
macros described above. If there
actually is a FreeBSD specific change (such as special
shared library options when using `ld
') then it is
OK to use __FreeBSD__
and `#if __FreeBSD__ >
1
' to detect a FreeBSD 2.x and later system.
If you need more granularity in detecting FreeBSD systems since
2.0-RELEASE you can use the following:
#if __FreeBSD__ >= 2
#include <osreldate.h>
# if __FreeBSD_version >= 199504
/* 2.0.5+ release specific code here */
# endif
#endif
__FreeBSD_version
values:
2.0-RELEASE: 199411
2.1-CURRENT's: 199501, 199503
2.0.5-RELEASE: 199504
2.2-CURRENT before 2.1: 199508
2.1.0-RELEASE: 199511
2.2-CURRENT before 2.1.5: 199512
2.1.5-RELEASE: 199607
2.2-CURRENT before 2.1.6: 199608
2.1.6-RELEASE: 199612
2.1.7-RELEASE: 199612
2.2-RELEASE: 220000
2.2.1-RELEASE: 220000 (yes, no change)
2.2-STABLE after 2.2.1-RELEASE: 220000 (yes, still no change)
2.2-STABLE after texinfo-3.9: 221001
2.2-STABLE after top: 221002
2.2.2-RELEASE: 222000
2.2-STABLE after 2.2.2-RELEASE: 222001
2.2.5-RELEASE: 225000
2.2-STABLE after 2.2.5-RELEASE: 225001
2.2-STABLE after ldconfig -R merge: 225002
2.2.6-RELEASE: 226000
2.2.7-RELEASE: 227000
2.2-STABLE after 2.2.7-RELEASE: 227001
2.2-STABLE after semctl(2) change: 227002
2.2.8-RELEASE: 228000
2.2-STABLE after 2.2.8-RELEASE: 228001
3.0-CURRENT before mount(2) change: 300000
3.0-CURRENT after mount(2) change: 300001
3.0-CURRENT after semctl(2) change: 300002
3.0-CURRENT after ioctl arg changes: 300003
3.0-CURRENT after ELF conversion: 300004
3.0-RELEASE: 300005
3.0-CURRENT after 3.0-RELEASE: 300006
3.0-STABLE after 3/4 branch: 300007
3.1-RELEASE: 310000
3.1-STABLE after 3.1-RELEASE: 310001
4.0-CURRENT after 3/4 branch: 400000
(Note that 2.2-STABLE sometimes identifies itself as
"2.2.[5678]-STABLE" after the 2.2.5-RELEASE.)
The pattern used to be year followed by the month, but we
decided to change it to a more straightforward major/minor
system starting from 2.2. This is because the parallel
development on several branches made it infeasible to
classify the releases simply by their real release dates.
(Note that if you are making a port now, you don't have to
worry about old -CURRENT's; they are listed here just for
your reference.)
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.
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.)
The architecture, as returned by
`uname -m
' (e.g., `i386').
The operating system type, as returned by
`uname -s
' (e.g., `FreeBSD').
The release version of the operating system (e.g., `2.1.5', `2.2.7').
The numeric version of the operating system, same as __FreeBSD_version above.
The object format of the system (`aout' or `elf').
The base of the `local' tree (e.g., `/usr/local/').
The base of the `X11' tree (e.g., `/usr/X11R6/').
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
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.
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.
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
'.
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.
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.
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.
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.
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.
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}
'.
The port should respect the ${CFLAGS}
variable.
If it doesn't, please add `NO_PACKAGE=ignores cflags
'
to the Makefile.
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.
Do check your port with portlint before you submit or commit it.
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.
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!
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! :)