Break the porters handbook out into individual chapters

like our other books (fdp primer, handbook dev handbook, etc).
I've done some small naming changes for cleaner chapters
but not much.

Thumbs up:      wblock, mat
This commit is contained in:
Tom Rhodes 2014-02-09 01:50:53 +00:00
parent 61c78bc077
commit 58dccdd7be
Notes: svn2git 2020-12-08 03:00:23 +00:00
svn path=/head/; revision=43840
33 changed files with 13152 additions and 12744 deletions

View file

@ -19,6 +19,22 @@ INSTALL_ONLY_COMPRESSED?=
#
# XML content
#SRCS+= quick-porting/chapter.xml
#SRCS+= own-port/chapter.xml
#SRCS+= porting-why/chapter.xml
SRCS+= makefiles/chapter.xml
#SRCS+= plist/chapter.xml
#SRCS+= testing/chapter.xml
#SRCS+= security/chapter.xml
#SRCS+= porting-samplem/chapter.xml
#SRCS+= appendices/chapter.xml
#SRCS+= keeping-up/chapter.xml
#SRCS+= porting-dads/chapter.xml
#SRCS+= upgrading/chapter.xml
#SRCS+= pkg-files/chapter.xml
#SRCS+= specials/chapter.xml
#SRCS+= slow-porting/chapter.xml
SRCS= book.xml
SRCS+= uses.xml
SRCS+= versions.xml
@ -49,4 +65,14 @@ IMAGES_LIB+= callouts/21.png
URL_RELPREFIX?= ../../../..
DOC_PREFIX?= ${.CURDIR}/../../..
# Entities
SRCS+= chapters.ent
SYMLINKS= ${DESTDIR} index.html handbook.html
# Turn on all the chapters.
CHAPTERS?= ${SRCS:M*chapter.xml}
XMLFLAGS+= ${CHAPTERS:S/\/chapter.xml//:S/^/-i chap./}
.include "${DOC_PREFIX}/share/mk/doc.project.mk"

View file

@ -0,0 +1,15 @@
#
# Build the Porters Handbook with just the content from this chapter.
#
# $FreeBSD$
#
CHAPTERS= appendices/chapter.xml
VPATH= ..
MASTERDOC= ${.CURDIR}/../${DOC}.${DOCBOOKSUFFIX}
DOC_PREFIX?= ${.CURDIR}/../../../..
.include "../Makefile"

View file

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!--
The FreeBSD Documentation Project
$FreeBSD$
-->
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="appendencies">
<title>Appendices</title>
<sect1 xml:id="uses-values">
<title>Values of <varname>USES</varname></title>
<table>
<title>Values of <varname>USES</varname></title>
<tgroup cols="3">
<thead>
<row>
<entry>Feature</entry>
<entry>Arguments</entry>
<entry>Description</entry>
</row>
</thead>
<tbody valign="top">
&values.uses;
</tbody>
</tgroup>
</table>
</sect1>
<sect1 xml:id="freebsd-versions">
<title><literal>__FreeBSD_version</literal> Values</title>
<para>Here is a convenient list of
<literal>__FreeBSD_version</literal> values as defined in
<link
xlink:href="http://svnweb.FreeBSD.org/base/head/sys/sys/param.h?view=markup">sys/param.h</link>:</para>
<table frame="none">
<title><literal>__FreeBSD_version</literal> Values</title>
<tgroup cols="3">
<thead>
<row>
<entry>Value</entry>
<entry>Date</entry>
<entry>Release</entry>
</row>
</thead>
<tbody>
&values.versions;
</tbody>
</tgroup>
</table>
<note>
<para>Note that 2.2-STABLE sometimes identifies itself as
<quote>2.2.5-STABLE</quote> 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.
If you are making a port now, you do not have to worry about
old -CURRENTs; they are listed here just for your
reference.</para>
</note>
</sect1>
</chapter>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!--
Creates entities for each chapter in the Porters Handbook. Each entity
is named chap.foo, where foo is the value of the id attribute on that
chapter, and corresponds to the name of the directory in which that
chapter's .xml file is stored.
Chapters should be listed in the order in which they are referenced.
$FreeBSD$
-->
<!ENTITY chap.porting-why SYSTEM "porting-why/chapter.xml">
<!ENTITY chap.new-port SYSTEM "new-port/chapter.xml">
<!ENTITY chap.quick-porting SYSTEM "quick-porting/chapter.xml">
<!ENTITY chap.slow-porting SYSTEM "slow-porting/chapter.xml">
<!ENTITY chap.makefiles SYSTEM "makefiles/chapter.xml">
<!ENTITY chap.special SYSTEM "special/chapter.xml">
<!ENTITY chap.plist SYSTEM "plist/chapter.xml">
<!ENTITY chap.pkg-files SYSTEM "pkg-files/chapter.xml">
<!ENTITY chap.testing SYSTEM "testing/chapter.xml">
<!ENTITY chap.upgrading SYSTEM "upgrading/chapter.xml">
<!ENTITY chap.security SYSTEM "security/chapter.xml">
<!ENTITY chap.porting-dads SYSTEM "porting-dads/chapter.xml">
<!ENTITY chap.porting-samplem SYSTEM "porting-samplem/chapter.xml">
<!ENTITY chap.keeping-up SYSTEM "keeping-up/chapter.xml">
<!ENTITY chap.appendices SYSTEM "appendices/chapter.xml">

View file

@ -0,0 +1,15 @@
#
# Build the Porters Handbook with just the content from this chapter.
#
# $FreeBSD$
#
CHAPTERS= keeping-up/chapter.xml
VPATH= ..
MASTERDOC= ${.CURDIR}/../${DOC}.${DOCBOOKSUFFIX}
DOC_PREFIX?= ${.CURDIR}/../../../..
.include "../Makefile"

View file

@ -0,0 +1,159 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!--
The FreeBSD Documentation Project
$FreeBSD$
-->
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="keeping-up">
<title>Keeping Up</title>
<para>The &os; Ports Collection is constantly changing. Here is
some information on how to keep up.</para>
<sect1 xml:id="freshports">
<title>FreshPorts</title>
<para>One of the easiest ways to learn about updates that have
already been committed is by subscribing to <link
xlink:href="http://www.FreshPorts.org/">FreshPorts</link>.
You can select multiple ports to monitor. Maintainers are
strongly encouraged to subscribe, because they will receive
notification of not only their own changes, but also any
changes that any other &os; committer has made. (These are
often necessary to keep up with changes in the underlying
ports framework&mdash;although it would be most polite to
receive an advance heads-up from those committing such
changes, sometimes this is overlooked or just simply
impractical. Also, in some cases, the changes are very minor
in nature. We expect everyone to use their best judgement in
these cases.)</para>
<para>If you wish to use FreshPorts, all you need is an account.
If your registered email address is
<literal>@FreeBSD.org</literal>, you will see the opt-in link
on the right hand side of the webpages. For those of you who
already have a FreshPorts account, but are not using your
<literal>@FreeBSD.org</literal> email address, just change
your email to <literal>@FreeBSD.org</literal>, subscribe, then
change it back again.</para>
<para>FreshPorts also has a sanity test feature which
automatically tests each commit to the &os; ports tree. If
subscribed to this service, you will be notified of any errors
which FreshPorts detects during sanity testing of your
commits.</para>
</sect1>
<sect1 xml:id="svnweb">
<title>The Web Interface to the Source Repository</title>
<para>It is possible to browse the files in the source
repository by using a web interface. Changes that affect the
entire port system are now documented in the <link
xlink:href="http://svnweb.FreeBSD.org/ports/head/CHANGES">CHANGES</link>
file. Changes that affect individual ports are now documented
in the <link
xlink:href="http://svnweb.FreeBSD.org/ports/head/UPDATING">UPDATING</link>
file. However, the definitive answer to any question is
undoubtedly to read the source code of <link
xlink:href="http://svnweb.FreeBSD.org/ports/head/Mk/bsd.port.mk">bsd.port.mk</link>,
and associated files.</para>
</sect1>
<sect1 xml:id="ports-mailing-list">
<title>The &os; Ports Mailing List</title>
<para>If you maintain ports, you should consider following the
&a.ports;. Important changes to the way ports work will be
announced there, and then committed to
<filename>CHANGES</filename>.</para>
<para>If this mailing list is too high volume you may consider
following &a.ports-announce; which is moderated and has no
discussion.</para>
</sect1>
<sect1 xml:id="build-cluster">
<title>The &os; Port Building Cluster</title>
<para>One of the least-publicized strengths of &os; is that
an entire cluster of machines is dedicated to continually
building the Ports Collection, for each of the major OS
releases and for each Tier-1 architecture.</para>
<para>Individual ports are built unless they are specifically
marked with <varname>IGNORE</varname>. Ports that are
marked with <varname>BROKEN</varname> will still be attempted,
to see if the underlying problem has been resolved. (This
is done by passing <varname>TRYBROKEN</varname> to the
port's <filename>Makefile</filename>.)</para>
</sect1>
<sect1 xml:id="distfile-survey">
<title>Portscout: the &os; Ports Distfile Scanner</title>
<para>The build cluster is dedicated to building the latest
release of each port with distfiles that have already been
fetched. However, as the Internet continually changes,
distfiles can quickly go missing. <link
xlink:href="http://portscout.FreeBSD.org">Portscout</link>,
the &os; Ports distfile scanner, attempts to query every
download site for every port to find out if each distfile is
still available. <application>Portscout</application> can
generate <acronym>HTML</acronym> reports and send emails about
newly available ports to those who request them. Unless not
otherwise subscribed, maintainers are asked to check
periodically for changes, either by hand or using the
<acronym>RSS</acronym> feed.</para>
<para><application>Portscout</application>'s first page gives
the email address of the port maintainer, the number of ports
the maintainer is responsible for, the number of those ports
with new distfiles, and the percentage of those ports that are
out-of-date. The search function allows for searching by
email address for a specific maintainer, and for selecting
whether or not only out-of-date ports should be shown.</para>
<para>Upon clicking on a maintainer's email address, a list of
all of their ports is displayed, along with port category,
current version number, whether or not there is a new version,
when the port was last updated, and finally when it was last
checked. A search function on this page allows the user to
search for a specific port.</para>
<para>Clicking on a port name in the list displays the <link
xlink:href="http://freshports.org">FreshPorts</link> port
information.</para>
</sect1>
<sect1 xml:id="portsmon">
<title>The &os; Ports Monitoring System</title>
<para>Another handy resource is the
<link xlink:href="http://portsmon.FreeBSD.org">&os; Ports
Monitoring System</link> (also known as
<literal>portsmon</literal>). This system comprises a
database that processes information from several sources and
allows it to be browsed via a web interface. Currently, the
ports Problem Reports (PRs), the error logs from the build
cluster, and individual files from the ports collection are
used. In the future, this will be expanded to include the
distfile survey, as well as other sources.</para>
<para>To get started, you can view all information about a
particular port by using the <link
xlink:href="http://portsmon.FreeBSD.org/portoverview.py">Overview
of One Port</link>.</para>
<para>As of this writing, this is the only resource available
that maps GNATS PR entries to portnames. (PR submitters do
not always include the portname in their Synopsis, although we
would prefer that they did.) So, <literal>portsmon</literal>
is a good place to start if you want to find out whether an
existing port has any PRs filed against it and/or any build
errors; or, to find out if a new port that you may be thinking
about creating has already been submitted.</para>
</sect1>
</chapter>

View file

@ -0,0 +1,15 @@
#
# Build the Porters Handbook with just the content from this chapter.
#
# $FreeBSD$
#
CHAPTERS= makefiles/chapter.xml
VPATH= ..
MASTERDOC= ${.CURDIR}/../${DOC}.${DOCBOOKSUFFIX}
DOC_PREFIX?= ${.CURDIR}/../../../..
.include "../Makefile"

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,15 @@
#
# Build the Porters Handbook with just the content from this chapter.
#
# $FreeBSD$
#
CHAPTERS= own-port/chapter.xml
VPATH= ..
MASTERDOC= ${.CURDIR}/../${DOC}.${DOCBOOKSUFFIX}
DOC_PREFIX?= ${.CURDIR}/../../../..
.include "../Makefile"

View file

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!--
The FreeBSD Documentation Project
$FreeBSD$
-->
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="own-port">
<title>Making a New Port</title>
<para>So, you are interested in making your own port or
upgrading an existing one? Great!</para>
<para>What follows are some guidelines for creating a new port for
&os;. If you want to upgrade an existing port, you should
read this and then read <xref linkend="port-upgrading"/>.</para>
<para>When this document is not sufficiently detailed, you should
refer to <filename>/usr/ports/Mk/bsd.port.mk</filename>, which
all port Makefiles include. Even if you do not hack Makefiles
daily, it is well commented, and you will still gain much
knowledge from it. Additionally, you may send specific
questions to the &a.ports;.</para>
<note>
<para>Only a fraction of the variables
(<varname><replaceable>VAR</replaceable></varname>) that can
be overridden are mentioned in this document. Most (if not
all) are documented at the start of
<filename>/usr/ports/Mk/bsd.port.mk</filename>; the others
probably ought to be. Note that this file uses a non-standard
tab setting: <application>Emacs</application> and
<application>Vim</application> should recognize the setting on
loading the file. Both &man.vi.1; and &man.ex.1; can be set
to use the correct value by typing
<command>:set tabstop=4</command> once the file has been
loaded.</para>
</note>
<para>
Looking for something easy to start with? Take a look at the
<link xlink:href="http://wiki.freebsd.org/WantedPorts">list of
requested ports</link> and see if you can work on one (or
more).</para>
</chapter>

View file

@ -0,0 +1,15 @@
#
# Build the Porters Handbook with just the content from this chapter.
#
# $FreeBSD$
#
CHAPTERS= pkg-files/chapter.xml
VPATH= ..
MASTERDOC= ${.CURDIR}/../${DOC}.${DOCBOOKSUFFIX}
DOC_PREFIX?= ${.CURDIR}/../../../..
.include "../Makefile"

View file

@ -0,0 +1,215 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!--
The FreeBSD Documentation Project
$FreeBSD$
-->
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="pkg-files">
<title>The <filename>pkg-*</filename>
Files</title>
<para>There are some tricks we have not mentioned yet about the
<filename>pkg-*</filename> files
that come in handy sometimes.</para>
<sect1 xml:id="porting-message">
<title><filename>pkg-message</filename></title>
<para>If you need to display a message to the installer, you may
place the message in <filename>pkg-message</filename>. This
capability is often useful to display additional installation
steps to be taken after a <command>pkg install</command> or to
display licensing information.</para>
<para>When some lines about the build-time knobs or warnings
have to be displayed, use <varname>ECHO_MSG</varname>. The
<filename>pkg-message</filename> file is only for
post-installation steps. Likewise, the distinction between
<varname>ECHO_MSG</varname> and <varname>ECHO_CMD</varname>
should be kept in mind. The former is for printing
informational text to the screen, while the latter is for
command pipelining:</para>
<programlisting>update-etc-shells:
@${ECHO_MSG} "updating /etc/shells"
@${CP} /etc/shells /etc/shells.bak
@( ${GREP} -v ${PREFIX}/bin/bash /etc/shells.bak; \
${ECHO_CMD} ${PREFIX}/bin/bash) &gt;/etc/shells
@${RM} /etc/shells.bak</programlisting>
<note>
<para>The <filename>pkg-message</filename> file does not need
to be added to <filename>pkg-plist</filename>.</para>
</note>
</sect1>
<sect1 xml:id="pkg-install">
<title><filename>pkg-install</filename></title>
<para>If your port needs to execute commands when the binary
package is installed with <command>pkg add</command> or
<command>pkg install</command> you can do this via the
<filename>pkg-install</filename> script. This script will
automatically be added to the package, and will be run twice
by <command>pkg</command> the first time as
<literal>&dollar;{SH} pkg-install &dollar;{PKGNAME}
PRE-INSTALL</literal> and the second time as
<literal>&dollar;{SH} pkg-install &dollar;{PKGNAME}
POST-INSTALL</literal>. <literal>&dollar;2</literal> can be
tested to determine which mode the script is being run in.
The <envar>PKG_PREFIX</envar> environmental variable will be
set to the package installation directory.</para>
<note>
<para>This script is not run automatically if you install the
port with <command>make install</command>. If you are
depending on it being run, you will have to explicitly call
it from your port's <filename>Makefile</filename>, with a
line like <literal>PKG_PREFIX=&dollar;{PREFIX} &dollar;{SH}
&dollar;{PKGINSTALL} &dollar;{PKGNAME}
PRE-INSTALL</literal>.</para>
</note>
</sect1>
<sect1 xml:id="pkg-deinstall">
<title><filename>pkg-deinstall</filename></title>
<para>This script executes when a package is removed.</para>
<para>This script will be run twice by <command>pkg
delete</command> The first time as <literal>&dollar;{SH}
pkg-deinstall &dollar;{PKGNAME} DEINSTALL</literal> and the
second time as <literal>&dollar;{SH} pkg-deinstall
&dollar;{PKGNAME} POST-DEINSTALL</literal>.</para>
</sect1>
<sect1 xml:id="pkg-names">
<title xml:id="porting-pkgfiles">Changing the Names of
<filename>pkg-*</filename>
Files</title>
<para>All the names of
<filename>pkg-*</filename> files
are defined using variables so you can change them in your
<filename>Makefile</filename> if need be. This is especially
useful when you are sharing the same
<filename>pkg-*</filename> files
among several ports or have to write to one of the above files
(see <link linkend="porting-wrkdir">writing to places other
than <varname>WRKDIR</varname></link> for why it is a bad
idea to write directly into the
<filename>pkg-*</filename>
subdirectory).</para>
<para>Here is a list of variable names and their default values.
(<varname>PKGDIR</varname> defaults to
<varname>${MASTERDIR}</varname>.)</para>
<informaltable frame="none" pgwide="0">
<tgroup cols="2">
<thead>
<row>
<entry>Variable</entry>
<entry>Default value</entry>
</row>
</thead>
<tbody>
<row>
<entry><varname>DESCR</varname></entry>
<entry><literal>${PKGDIR}/pkg-descr</literal></entry>
</row>
<row>
<entry><varname>PLIST</varname></entry>
<entry><literal>${PKGDIR}/pkg-plist</literal></entry>
</row>
<row>
<entry><varname>PKGINSTALL</varname></entry>
<entry><literal>${PKGDIR}/pkg-install</literal></entry>
</row>
<row>
<entry><varname>PKGDEINSTALL</varname></entry>
<entry><literal>${PKGDIR}/pkg-deinstall</literal></entry>
</row>
<row>
<entry><varname>PKGMESSAGE</varname></entry>
<entry><literal>${PKGDIR}/pkg-message</literal></entry>
</row>
</tbody>
</tgroup>
</informaltable>
<para>Please change these variables rather than overriding
<varname>PKG_ARGS</varname>. If you change
<varname>PKG_ARGS</varname>, those files will not correctly be
installed in <filename>/var/db/pkg</filename> upon install
from a port.</para>
</sect1>
<sect1 xml:id="using-sub-files">
<title>Making Use of <varname>SUB_FILES</varname> and
<varname>SUB_LIST</varname></title>
<para>The <varname>SUB_FILES</varname> and
<varname>SUB_LIST</varname> variables are useful for dynamic
values in port files, such as the installation
<varname>PREFIX</varname> in
<filename>pkg-message</filename>.</para>
<para>The <varname>SUB_FILES</varname> variable specifies a list
of files to be automatically modified. Each
<replaceable>file</replaceable> in the
<varname>SUB_FILES</varname> list must have a corresponding
<filename>file.in</filename>
present in <varname>FILESDIR</varname>. A modified version
will be created in <varname>WRKDIR</varname>. Files defined
as a value of <varname>USE_RC_SUBR</varname> (or the
deprecated <varname>USE_RCORDER</varname>) are automatically
added to the <varname>SUB_FILES</varname>. For the files
<filename>pkg-message</filename>,
<filename>pkg-install</filename>,
and
<filename>pkg-deinstall</filename>,
the corresponding Makefile
variable is automatically set to point to the processed
version.</para>
<para>The <varname>SUB_LIST</varname> variable is a list of
<literal>VAR=VALUE</literal> pairs. For each pair
<literal>%%VAR%%</literal> will get replaced with
<literal>VALUE</literal> in each file listed in
<varname>SUB_FILES</varname>. Several common pairs are
automatically defined: <varname>PREFIX</varname>,
<varname>LOCALBASE</varname>, <varname>DATADIR</varname>,
<varname>DOCSDIR</varname>, <varname>EXAMPLESDIR</varname>,
<varname>WWWDIR</varname>, and <varname>ETCDIR</varname>.
Any line beginning with <literal>@comment</literal> will be
deleted from resulting files after a variable
substitution.</para>
<para>The following example will replace
<literal>%%ARCH%%</literal> with the system architecture in a
<filename>pkg-message</filename>:</para>
<programlisting>SUB_FILES= pkg-message
SUB_LIST= ARCH=${ARCH}</programlisting>
<para>Note that for this example, the
<filename>pkg-message.in</filename> file must exist in
<varname>FILESDIR</varname>.</para>
<para>Example of a good
<filename>pkg-message.in</filename>:</para>
<programlisting>Now it is time to configure this package.
Copy %%PREFIX%%/share/examples/putsy/%%ARCH%%.conf into your home directory
as .putsy.conf and edit it.</programlisting>
</sect1>
</chapter>

View file

@ -0,0 +1,15 @@
#
# Build the Porters Handbook with just the content from this chapter.
#
# $FreeBSD$
#
CHAPTERS= plist/chapter.xml
VPATH= ..
MASTERDOC= ${.CURDIR}/../${DOC}.${DOCBOOKSUFFIX}
DOC_PREFIX?= ${.CURDIR}/../../../..
.include "../Makefile"

View file

@ -0,0 +1,288 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!--
The FreeBSD Documentation Project
$FreeBSD$
-->
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="plist">
<title>Advanced <filename>pkg-plist</filename> Practices</title>
<sect1 xml:id="plist-sub">
<title>Changing <filename>pkg-plist</filename> Based on Make
Variables</title>
<para>Some ports, particularly the <literal>p5-</literal> ports,
need to change their <filename>pkg-plist</filename> depending
on what options they are configured with (or version of
<literal>perl</literal>, in the case of <literal>p5-</literal>
ports). To make this easy, any instances in the
<filename>pkg-plist</filename> of
<literal>%%OSREL%%</literal>, <literal>%%PERL_VER%%</literal>,
and <literal>%%PERL_VERSION%%</literal> will be substituted
for appropriately. The value of <literal>%%OSREL%%</literal>
is the numeric revision of the operating system (e.g.,
<literal>4.9</literal>). <literal>%%PERL_VERSION%%</literal>
and <literal>%%PERL_VER%%</literal> is the full version number
of <command>perl</command> (e.g., <literal>5.8.9</literal>).
Several other
<literal>%%VARS%%</literal> related
to port's documentation files are described in
<link linkend="install-documentation">the relevant
section</link>.</para>
<para>If you need to make other substitutions, you can set the
<varname>PLIST_SUB</varname> variable with a list of
<literal>VAR=VALUE</literal>
pairs and instances of
<literal>%%VAR%%</literal> will be
substituted with <replaceable>VALUE</replaceable> in the
<filename>pkg-plist</filename>.</para>
<para>For instance, if you have a port that installs many files
in a version-specific subdirectory, you can put something
like</para>
<programlisting>OCTAVE_VERSION= 2.0.13
PLIST_SUB= OCTAVE_VERSION=${OCTAVE_VERSION}</programlisting>
<para>in the <filename>Makefile</filename> and use
<literal>%%OCTAVE_VERSION%%</literal> wherever the version
shows up in <filename>pkg-plist</filename>. That way, when
you upgrade the port, you will not have to change dozens (or
in some cases, hundreds) of lines in the
<filename>pkg-plist</filename>.</para>
<para>If your port installs files conditionally on the options
set in the port, the usual way of handling it is prefixing the
<filename>pkg-plist</filename> lines with a
<literal>%%TAG%%</literal> and adding that
<literal>TAG</literal> to the <varname>PLIST_SUB</varname>
variable inside the <filename>Makefile</filename> with a
special value of <literal>@comment</literal>, which makes
package tools to ignore the line:</para>
<programlisting>.if defined(WITH_X11)
PLIST_SUB+= X11=""
.else
PLIST_SUB+= X11="@comment "
.endif</programlisting>
<para>and in the <filename>pkg-plist</filename>:</para>
<programlisting>%%X11%%bin/foo-gui</programlisting>
<para>This substitution
will be
done between the <buildtarget>pre-install</buildtarget> and
<buildtarget>do-install</buildtarget> targets, by reading from
<filename>PLIST</filename> and writing to
<filename>TMPPLIST</filename> (default:
<filename>WRKDIR/.PLIST.mktmp</filename>).
So if your port builds
<filename>PLIST</filename> on the fly, do
so in or before <buildtarget>pre-install</buildtarget>. Also,
if your port needs to edit the resulting file, do so in
<buildtarget>post-install</buildtarget> to a file named
<filename>TMPPLIST</filename>.</para>
<para>Another way of modifying a port's packing list is based
on setting the variables <varname>PLIST_FILES</varname>,
<varname>PLIST_DIRS</varname>, and
<varname>PLIST_DIRSTRY</varname>. The value of each variable
is regarded as a list of pathnames to write to
<filename>TMPPLIST</filename> along with
<filename>PLIST</filename> contents. Names
listed in <varname>PLIST_FILES</varname>,
<varname>PLIST_DIRS</varname>, and
<varname>PLIST_DIRSTRY</varname> are subject to
<literal>%%VAR%%</literal>
substitution as described above. Except for that, names from
<varname>PLIST_FILES</varname> will appear in the final
packing list unchanged, while <literal>@dirrm</literal> and
<literal>@dirrmtry</literal> will
be prepended to names from <varname>PLIST_DIRS</varname>
and <varname>PLIST_DIRSTRY</varname>, respectively. To
take effect, <varname>PLIST_FILES</varname>,
<varname>PLIST_DIRS</varname>, and
<varname>PLIST_DIRSTRY</varname> must be set before
<filename>TMPPLIST</filename> is written,
i.e., in <buildtarget>pre-install</buildtarget> or
earlier.</para>
</sect1>
<sect1 xml:id="plist-cleaning">
<title>Empty Directories</title>
<sect2 xml:id="plist-dir-cleaning">
<title>Cleaning Up Empty Directories</title>
<para>Do make your ports remove empty directories when they
are de-installed. This is usually accomplished by adding
<literal>@dirrm</literal> lines for all directories that are
specifically created by the port. You need to delete
subdirectories before you can delete parent
directories.</para>
<programlisting> :
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</programlisting>
<para>However, sometimes <literal>@dirrm</literal> will give
you errors because other ports share the same directory.
You can use <literal>@dirrmtry</literal> to remove only
empty directories without warning.</para>
<programlisting>@dirrmtry share/doc/gimp</programlisting>
<para>This will neither print any error messages nor cause
<command>pkg delete</command> (see &man.pkg-delete.8;) to
exit abnormally even if
<filename>${PREFIX}/share/doc/gimp</filename> is not empty
due to other ports installing some files in there.</para>
</sect2>
<sect2 xml:id="plist-dir-empty">
<title>Creating Empty Directories</title>
<para>Empty directories created during port installation need
special attention. They will not get created when
installing the package, because packages only store the
files, and both <command>pkg add</command> and <command>pkg
install</command> creates directories for them as needed.
To make sure the empty directory is created when installing
the package, add this line to <filename>pkg-plist</filename>
above the corresponding <literal>@dirrm</literal>
line:</para>
<programlisting>@exec mkdir -p %D/share/foo/templates</programlisting>
</sect2>
</sect1>
<sect1 xml:id="plist-config">
<title>Configuration Files</title>
<para>If your port installs configuration files to
<filename>PREFIX/etc</filename> (or
elsewhere) do <emphasis>not</emphasis> simply list them in the
<filename>pkg-plist</filename>. That will cause <command>pkg
delete</command> to remove the files carefully edited by the
user, and a re-installation will wipe them out.</para>
<para>Instead, install sample file(s) with a
<filename>filename.sample</filename>
suffix. Then copy the sample file to the real configuration
file name, if it does not already exist. On deinstall
delete the configuration file, but only if it is identical
to the <filename>.sample</filename> file.
You need to handle this both in the port
<filename>Makefile</filename>, and in the
<filename>pkg-plist</filename> (for installation from the
package).</para>
<para>Example of the <filename>Makefile</filename> part:</para>
<programlisting>post-install:
@if [ ! -f ${PREFIX}/etc/orbit.conf ]; then \
${CP} -p ${PREFIX}/etc/orbit.conf.sample ${STAGEDIR}${PREFIX}/etc/orbit.conf ; \
fi</programlisting>
<para>For each configuration file, create the following three
lines in <filename>pkg-plist</filename>:</para>
<programlisting>@unexec if cmp -s %D/etc/orbit.conf.sample %D/etc/orbit.conf; then rm -f %D/etc/orbit.conf; fi
etc/orbit.conf.sample
@exec if [ ! -f %D/etc/orbit.conf ] ; then cp -p %D/%F %B/orbit.conf; fi</programlisting>
<para>The order of these lines is important. On deinstallation,
the sample file is compared to the actual configuration file.
If these files are identical, no changes have been made by the
user and the actual file can be safely deleted. Because the
sample file must still exist for the comparison, the
<literal>@unexec</literal> line comes before the sample
configuration file name. On installation, if an actual
configuration file is not already present, the sample file is
copied to the actual file. The sample file must be present
before it can be copied, so the <literal>@exec</literal> line
comes after the sample configuration file name.</para>
<para>To debug any issues, temporarily remove the
<literal>-s</literal> flag to &man.cmp.1; for more
output.</para>
<para>See &man.pkg-create.8; for more information on
<literal>%D</literal> and related substitution markers.</para>
<para>If there is a very good reason not to install a working
configuration file by default, leave the
<literal>@exec</literal> line out of
<filename>pkg-plist</filename> and add a
<link linkend="porting-message">message</link> pointing out
that the user must copy and edit the file before the software
will work.</para>
</sect1>
<sect1 xml:id="plist-dynamic">
<title>Dynamic Versus Static Package List</title>
<para>A <emphasis>static package list</emphasis> is a package
list which is available in the Ports Collection either as a
<filename>pkg-plist</filename> file (with or without variable
substitution), or embedded into the
<filename>Makefile</filename> via
<varname>PLIST_FILES</varname>,
<varname>PLIST_DIRS</varname>, and
<varname>PLIST_DIRSTRY</varname>. Even if the contents are
auto-generated by a tool or a target in the Makefile
<emphasis>before</emphasis> the inclusion into the Ports
Collection by a committer, this is still considered a static
list, since it is possible to examine it without having to
download or compile the distfile.</para>
<para>A <emphasis>dynamic package list</emphasis> is a package
list which is generated at the time the port is compiled based
upon the files and directories which are installed. It is not
possible to examine it before the source code of the ported
application is downloaded and compiled, or after running a
<literal>make clean</literal>.</para>
<para>While the use of dynamic package lists is not forbidden,
maintainers should use static package lists wherever possible,
as it enables users to &man.grep.1; through available ports to
discover, for example, which port installs a certain file.
Dynamic lists should be primarily used for complex ports where
the package list changes drastically based upon optional
features of the port (and thus maintaining a static package
list is infeasible), or ports which change the package list
based upon the version of dependent software used (e.g., ports
which generate docs with
<application>Javadoc</application>).</para>
</sect1>
<sect1 xml:id="plist-autoplist">
<title>Automated Package List Creation</title>
<para>First, make sure your port is almost complete, with only
<filename>pkg-plist</filename> missing. You may then run
<command>make makeplist</command> to
generate a <filename>pkg-plist</filename> automatically. This
file must be double checked for correctness.</para>
<para>User configuration files should be
removed, or installed as
<filename>filename.sample</filename>.
The <filename>info/dir</filename> file should not be listed
and appropriate <filename>install-info</filename> lines should
be added as noted in the
<link linkend="makefile-info">info files</link> section. Any
libraries installed by the port should be listed as specified
in the <link linkend="porting-shlibs">shared libraries</link>
section.</para>
</sect1>
</chapter>

View file

@ -0,0 +1,15 @@
#
# Build the Porters Handbook with just the content from this chapter.
#
# $FreeBSD$
#
CHAPTERS= porting-dads/chapter.xml
VPATH= ..
MASTERDOC= ${.CURDIR}/../${DOC}.${DOCBOOKSUFFIX}
DOC_PREFIX?= ${.CURDIR}/../../../..
.include "../Makefile"

View file

@ -0,0 +1,724 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!--
The FreeBSD Documentation Project
$FreeBSD$
-->
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="porting-dads">
<title>Dos and Don'ts</title>
<sect1 xml:id="dads-intro">
<title>Introduction</title>
<para>Here is a list of common dos and don'ts that are
encountered during the porting process. Check the port
against this list, but also check ports in the <link
xlink:href="http://www.FreeBSD.org/cgi/query-pr-summary.cgi?query">PR
database</link> that others have submitted. Submit any
comments on ports you check as described in <link
xlink:href="&url.articles.contributing;/contrib-how.html#CONTRIB-GENERAL">Bug
Reports and General Commentary</link>. 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.</para>
</sect1>
<sect1 xml:id="porting-wrkdir">
<title><varname>WRKDIR</varname></title>
<para>Do not write anything to files outside
<varname>WRKDIR</varname>. <varname>WRKDIR</varname> is the
only place that is guaranteed to be writable during the port
build (see <link
xlink:href="&url.books.handbook;/ports-using.html#PORTS-CD">
installing ports from a CDROM</link> for an example of
building ports from a read-only tree). If you need to modify
one of the <filename>pkg-*</filename> files, do so by
<link linkend="porting-pkgfiles">redefining a variable</link>,
not by writing over it.</para>
</sect1>
<sect1 xml:id="porting-wrkdirprefix">
<title><varname>WRKDIRPREFIX</varname></title>
<para>Make sure your port honors
<varname>WRKDIRPREFIX</varname>. Most ports do not have to
worry about this. In particular, if you are referring to a
<varname>WRKDIR</varname> of another port, note that the
correct location is
<filename>WRKDIRPREFIXPORTSDIR/subdir/name/work</filename>
not
<filename>PORTSDIR/subdir/name/work</filename>
or
<filename>.CURDIR/../../subdir/name/work</filename>
or some such.</para>
<para>Also, if you are defining <varname>WRKDIR</varname>
yourself, make sure you prepend
<literal>&dollar;{WRKDIRPREFIX}&dollar;{.CURDIR}</literal> in
the front.</para>
</sect1>
<sect1 xml:id="porting-versions">
<title>Differentiating Operating Systems and OS Versions</title>
<para>You may come across code that needs modifications or
conditional compilation based upon what version of &os; Unix
it is running under. The preferred way to tell &os; versions
apart are the <literal>__FreeBSD_version</literal> and
<literal>__FreeBSD__</literal> macros defined in <link
xlink:href="http://svnweb.freebsd.org/base/head/sys/sys/param.h?view=markup">sys/param.h</link>.
If this file is not included add the code,</para>
<programlisting>#include &lt;sys/param.h&gt;</programlisting>
<para>to the proper place in the <filename>.c</filename>
file.</para>
<para><literal>__FreeBSD__</literal> is defined in all
versions of &os; as their major version number. For
example, in &os; 9.x, <literal>__FreeBSD__</literal> is
defined to be <literal>9</literal>.</para>
<programlisting>#if __FreeBSD__ &gt;= 9
# if __FreeBSD_version &gt;= 901000
/* 9.1+ release specific code here */
# endif
#endif</programlisting>
</sect1>
<sect1 xml:id="dads-after-port-mk">
<title>Writing Something After
<filename>bsd.port.mk</filename></title>
<para>Do not write anything after the <literal>.include
&lt;bsd.port.mk&gt;</literal> line. It usually can be
avoided by including <filename>bsd.port.pre.mk</filename>
somewhere in the middle of your <filename>Makefile</filename>
and <filename>bsd.port.post.mk</filename> at the end.</para>
<note>
<para>Include either the
<filename>bsd.port.pre.mk</filename>/<filename>bsd.port.post.mk</filename>
pair or <filename>bsd.port.mk</filename> only; do not mix
these two usages.</para>
</note>
<para><filename>bsd.port.pre.mk</filename> only defines a few
variables, which can be used in tests in the
<filename>Makefile</filename>,
<filename>bsd.port.post.mk</filename> defines the rest.</para>
<para>Here are some important variables defined in
<filename>bsd.port.pre.mk</filename> (this is not the complete
list, please read <filename>bsd.port.mk</filename> for the
complete list).</para>
<informaltable frame="none" pgwide="0">
<tgroup cols="2">
<thead>
<row>
<entry>Variable</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry><varname>ARCH</varname></entry>
<entry>The architecture as returned by <command>uname
-m</command> (e.g., <literal>i386</literal>)</entry>
</row>
<row>
<entry><varname>OPSYS</varname></entry>
<entry>The operating system type, as returned by
<command>uname -s</command> (e.g.,
<literal>FreeBSD</literal>)</entry>
</row>
<row>
<entry><varname>OSREL</varname></entry>
<entry>The release version of the operating system
(e.g., <literal>2.1.5</literal> or
<literal>2.2.7</literal>)</entry>
</row>
<row>
<entry><varname>OSVERSION</varname></entry>
<entry>The numeric version of the operating system; the
same as <link
linkend="freebsd-versions"><literal>__FreeBSD_version</literal></link>.</entry>
</row>
<row>
<entry><varname>LOCALBASE</varname></entry>
<entry>The base of the <quote>local</quote> tree (e.g.,
<literal>/usr/local</literal>)</entry>
</row>
<row>
<entry><varname>PREFIX</varname></entry>
<entry>Where the port installs itself (see
<link linkend="porting-prefix">more on
<varname>PREFIX</varname></link>).</entry>
</row>
</tbody>
</tgroup>
</informaltable>
<note>
<para>If you have to define the variable
<varname>MASTERDIR</varname>, do so before including
<filename>bsd.port.pre.mk</filename>.</para>
</note>
<para>Here are some examples of things you can write after
<filename>bsd.port.pre.mk</filename>:</para>
<programlisting># no need to compile lang/perl5 if perl5 is already in system
.if ${OSVERSION} &gt; 300003
BROKEN= perl is in system
.endif</programlisting>
<para>You did remember to use tab instead of spaces after
<literal>BROKEN=</literal> and
<!-- smiley -->:-).</para>
</sect1>
<sect1 xml:id="dads-sh-exec">
<title>Use the <function>exec</function> Statement in Wrapper
Scripts</title>
<para>If the port installs a shell script whose purpose is to
launch another program, and if launching that program is the
last action performed by the script, make sure to launch the
program using the <function>exec</function> statement, for
instance:</para>
<programlisting>#!/bin/sh
exec %%LOCALBASE%%/bin/java -jar %%DATADIR%%/foo.jar "$@"</programlisting>
<para>The <function>exec</function> statement replaces the shell
process with the specified program. If
<function>exec</function> is omitted, the shell process
remains in memory while the program is executing, and
needlessly consumes system resources.</para>
</sect1>
<sect1 xml:id="dads-rational">
<title>Do Things Rationally</title>
<para>The <filename>Makefile</filename> 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
<literal>.if</literal> construct instead of a shell
<literal>if</literal> construct, not redefining
<buildtarget>do-extract</buildtarget> if you can redefine
<varname>EXTRACT*</varname> instead, and using
<varname>GNU_CONFIGURE</varname> instead of
<literal>CONFIGURE_ARGS
+= --prefix=&dollar;{PREFIX}</literal>.</para>
<para>If you find yourself having to write a lot of new code to
try to do something, please go back and review
<filename>bsd.port.mk</filename> to see if it contains an
existing implementation of what you are trying to do. While
hard to read, there are a great many seemingly-hard problems
for which <filename>bsd.port.mk</filename> already provides a
shorthand solution.</para>
</sect1>
<sect1 xml:id="dads-cc">
<title>Respect Both <varname>CC</varname> and
<varname>CXX</varname></title>
<para>The port must respect both <varname>CC</varname> and
<varname>CXX</varname> variables. What we mean by this is
that the port must not set the values of these variables
absolutely, overriding existing values; instead, it may
append whatever values it needs to the existing values. This
is so that build options that affect all ports can be set
globally.</para>
<para>If the port does not respect these variables,
please add
<literal>NO_PACKAGE=ignores either cc or cxx</literal> to the
<filename>Makefile</filename>.</para>
<para>An example of a <filename>Makefile</filename> respecting
both <varname>CC</varname> and <varname>CXX</varname>
variables follows. Note the <varname>?=</varname>:</para>
<programlisting>CC?= gcc</programlisting>
<programlisting>CXX?= g++</programlisting>
<para>Here is an example which respects neither
<varname>CC</varname> nor <varname>CXX</varname>
variables:</para>
<programlisting>CC= gcc</programlisting>
<programlisting>CXX= g++</programlisting>
<para>Both <varname>CC</varname> and <varname>CXX</varname>
variables can be defined on &os; systems in
<filename>/etc/make.conf</filename>. The first example
defines a value if it was not previously set in
<filename>/etc/make.conf</filename>, preserving any
system-wide definitions. The second example clobbers
anything previously defined.</para>
</sect1>
<sect1 xml:id="dads-cflags">
<title>Respect <varname>CFLAGS</varname></title>
<para>The port must respect the <varname>CFLAGS</varname>
variable. What we mean by this is that the port must not
set the value of this variable absolutely, overriding the
existing value; instead, it may append whatever values it
needs to the existing value. This is so that build options
that affect all ports can be set globally.</para>
<para>If it does not, please add
<literal>NO_PACKAGE=ignores cflags</literal> to the
<filename>Makefile</filename>.</para>
<para>An example of a <filename>Makefile</filename> respecting
the <varname>CFLAGS</varname> variable follows. Note the
<varname>+=</varname>:</para>
<programlisting>CFLAGS+= -Wall -Werror</programlisting>
<para>Here is an example which does not respect the
<varname>CFLAGS</varname> variable:</para>
<programlisting>CFLAGS= -Wall -Werror</programlisting>
<para>The <varname>CFLAGS</varname> variable is defined on
&os; systems in <filename>/etc/make.conf</filename>. The
first example appends additional flags to the
<varname>CFLAGS</varname> variable, preserving any system-wide
definitions. The second example clobbers anything previously
defined.</para>
<para>You should remove optimization flags from the third party
<filename>Makefile</filename>s. System
<varname>CFLAGS</varname> contains system-wide optimization
flags. An example from an unmodified
<filename>Makefile</filename>:</para>
<programlisting>CFLAGS= -O3 -funroll-loops -DHAVE_SOUND</programlisting>
<para>Using system optimization flags, the
<filename>Makefile</filename> would look similar to the
following example:</para>
<programlisting>CFLAGS+= -DHAVE_SOUND</programlisting>
</sect1>
<sect1 xml:id="dads-pthread">
<title>Threading Libraries</title>
<para>The threading library must be linked to the binaries using
a special flag <literal>-pthread</literal> on &os;. If
a port insists on linking <literal>-lpthread</literal>
directly, patch it to use <literal>-pthread</literal>.</para>
<note>
<para>If building the port errors out with
<literal>unrecognized option '-pthread'</literal>, it may be
desirable to use <command>cc</command> as linker by setting
<varname>CONFIGURE_ENV</varname> to
<literal>LD=${CC}</literal>. The
<literal>-pthread</literal> option is not supported by
<command>ld</command> directly.</para>
</note>
</sect1>
<sect1 xml:id="dads-feedback">
<title>Feedback</title>
<para>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.</para>
</sect1>
<sect1 xml:id="dads-readme">
<title><filename>README.html</filename></title>
<para><filename>README.html</filename> is not part of the port,
but generated by <command>make readme</command>. Do not
include this file in patches or commits.</para>
<note>
<para>If <command>make readme</command> fails, make sure that
the default value of <varname>ECHO_MSG</varname> has not
been modified by the port.</para>
</note>
</sect1>
<sect1 xml:id="dads-noinstall">
<title>Marking a Port Not Installable with
<varname>BROKEN</varname>, <varname>FORBIDDEN</varname>, or
<varname>IGNORE</varname></title>
<para>In certain cases users should be prevented from installing
a port. To tell a user that a port should not be installed,
there are several <command>make</command> variables that can
be used in a port's <filename>Makefile</filename>. The value
of the following <command>make</command> variables will be the
reason that is given back to users for why the port refuses to
install itself. Please use the correct
<command>make</command> variable as each make variable conveys
radically different meanings to both users, and to automated
systems that depend on the <filename>Makefile</filename>s,
such as <link linkend="build-cluster">the ports build
cluster</link>, <link linkend="freshports">FreshPorts</link>,
and <link linkend="portsmon">portsmon</link>.</para>
<sect2 xml:id="dads-noinstall-variables">
<title>Variables</title>
<itemizedlist>
<listitem>
<para><varname>BROKEN</varname> is reserved for ports that
currently do not compile, install, or deinstall
correctly. It should be used for ports where the
problem is believed to be temporary.</para>
<para>If instructed, the build cluster will still attempt
to try to build them to see if the underlying problem
has been resolved. (However, in general, the cluster is
run without this.)</para>
<para>For instance, use <varname>BROKEN</varname> when a
port:</para>
<itemizedlist>
<listitem>
<para>does not compile</para>
</listitem>
<listitem>
<para>fails its configuration or installation
process</para>
</listitem>
<listitem>
<para>installs files outside of
<filename>${LOCALBASE}</filename></para>
</listitem>
<listitem>
<para>does not remove all its files cleanly upon
deinstall (however, it may be acceptable, and
desirable, for the port to leave user-modified files
behind)</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para><varname>FORBIDDEN</varname> is used for ports that
contain a security vulnerability or induce grave concern
regarding the security of a &os; system with a given
port installed (e.g., a reputably insecure program or a
program that provides easily exploitable services).
Ports should be marked as <varname>FORBIDDEN</varname>
as soon as a particular piece of software has a
vulnerability and there is no released upgrade. Ideally
ports should be upgraded as soon as possible when a
security vulnerability is discovered so as to reduce the
number of vulnerable &os; hosts (we like being known
for being secure), however sometimes there is a
noticeable time gap between disclosure of a
vulnerability and an updated release of the vulnerable
software. Do not mark a port
<varname>FORBIDDEN</varname> for any reason other than
security.</para>
</listitem>
<listitem>
<para><varname>IGNORE</varname> is reserved for ports that
should not be built for some other reason. It should be
used for ports where the problem is believed to be
structural. The build cluster will not, under any
circumstances, build ports marked as
<varname>IGNORE</varname>. For instance, use
<varname>IGNORE</varname> when a port:</para>
<itemizedlist>
<listitem>
<para>compiles but does not run properly</para>
</listitem>
<listitem>
<para>does not work on the installed version of
&os;</para>
</listitem>
<listitem>
<para>has a distfile which may not be automatically
fetched due to licensing restrictions</para>
</listitem>
<listitem>
<para>does not work with some other currently
installed port (for instance, the port depends on
<package role="port">www/apache20</package> but
<package role="port">www/apache22</package> is
installed)</para>
</listitem>
</itemizedlist>
<note>
<para>If a port would conflict with a currently
installed port (for example, if they install a file in
the same place that performs a different function),
<link linkend="conflicts">use
<varname>CONFLICTS</varname> instead</link>.
<varname>CONFLICTS</varname> will set
<varname>IGNORE</varname> by itself.</para>
</note>
</listitem>
<listitem>
<para>If a port should be marked <varname>IGNORE</varname>
only on certain architectures, there are two other
convenience variables that will automatically set
<varname>IGNORE</varname> for you:
<varname>ONLY_FOR_ARCHS</varname> and
<varname>NOT_FOR_ARCHS</varname>. Examples:</para>
<programlisting>ONLY_FOR_ARCHS= i386 amd64</programlisting>
<programlisting>NOT_FOR_ARCHS= ia64 sparc64</programlisting>
<para>A custom <varname>IGNORE</varname> message can be
set using <varname>ONLY_FOR_ARCHS_REASON</varname> and
<varname>NOT_FOR_ARCHS_REASON</varname>. Per
architecture entries are possible with
<varname>ONLY_FOR_ARCHS_REASON_<replaceable>ARCH</replaceable></varname>
and
<varname>NOT_FOR_ARCHS_REASON_<replaceable>ARCH</replaceable></varname>.</para>
</listitem>
<listitem>
<para>If a port fetches i386 binaries and installs them,
<varname>IA32_BINARY_PORT</varname> should be set. If
this variable is set, it will be checked whether the
<filename>/usr/lib32</filename> directory is available
for IA32 versions of libraries and whether the kernel
has IA32 compatibility compiled in. If one of these two
dependencies is not satisfied, <varname>IGNORE</varname>
will be set automatically.</para>
</listitem>
</itemizedlist>
</sect2>
<sect2 xml:id="dads-noinstall-notes">
<title>Implementation Notes</title>
<para>The strings should not be quoted.
Also, the wording of the string should be somewhat
different due to the way the information is shown to the
user. Examples:</para>
<programlisting>BROKEN= fails to link with base -lcrypto</programlisting>
<programlisting>IGNORE= unsupported on recent versions</programlisting>
<para>resulting in the following output from
<command>make describe</command>:</para>
<programlisting>===&gt; foobar-0.1 is marked as broken: fails to link with base -lcrypto.</programlisting>
<programlisting>===&gt; foobar-0.1 is unsupported on recent versions.</programlisting>
</sect2>
</sect1>
<sect1 xml:id="dads-deprecated">
<title>Marking a Port for Removal with
<varname>DEPRECATED</varname> or
<varname>EXPIRATION_DATE</varname></title>
<para>Do remember that <varname>BROKEN</varname> and
<varname>FORBIDDEN</varname> are to be used as a temporary
resort if a port is not working. Permanently broken ports
should be removed from the tree entirely.</para>
<para>When it makes sense to do so, users can be warned about
a pending port removal with <varname>DEPRECATED</varname>
and <varname>EXPIRATION_DATE</varname>. The former is
simply a string stating why the port is scheduled for removal;
the latter is a string in ISO 8601 format (YYYY-MM-DD). Both
will be shown to the user.</para>
<para>It is possible to set <varname>DEPRECATED</varname>
without an <varname>EXPIRATION_DATE</varname> (for instance,
recommending a newer version of the port), but the converse
does not make any sense.</para>
<para>There is no set policy on how much notice to give.
Current practice seems to be one month for security-related
issues and two months for build issues. This also gives any
interested committers a little time to fix the
problems.</para>
</sect1>
<sect1 xml:id="dads-dot-error">
<title>Avoid Use of the <literal>.error</literal>
Construct</title>
<para>The correct way for a <filename>Makefile</filename> to
signal that the port can not be installed due to some external
factor (for instance, the user has specified an illegal
combination of build options) is to set a non-blank value to
<varname>IGNORE</varname>. This value will be formatted and
shown to the user by <command>make install</command>.</para>
<para>It is a common mistake to use <literal>.error</literal>
for this purpose. The problem with this is that many
automated tools that work with the ports tree will fail in
this situation. The most common occurrence of this is seen
when trying to build <filename>/usr/ports/INDEX</filename>
(see <xref linkend="make-describe"/>). However, even more
trivial commands such as <command>make maintainer</command>
also fail in this scenario. This is not acceptable.</para>
<example xml:id="dot-error-breaks-index">
<title>How to Avoid Using <literal>.error</literal></title>
<para>The first of the
next two <filename>Makefile</filename> snippets will cause
<command>make index</command> to fail, while the second one
will not:</para>
<programlisting>.error "option is not supported"</programlisting>
<programlisting>IGNORE=option is not supported</programlisting>
</example>
</sect1>
<sect1 xml:id="dads-sysctl">
<title>Usage of <filename>sysctl</filename></title>
<para>The usage of <filename>sysctl</filename> is discouraged
except in targets. This is because the evaluation of any
<literal>makevar</literal>s, such as used during
<command>make index</command>, then has to run the command,
further slowing down that process.</para>
<para>Usage of &man.sysctl.8; should always be done with the
<varname>SYSCTL</varname> variable, as it contains the fully
qualified path and can be overridden, if one has such a
special need.</para>
</sect1>
<sect1 xml:id="dads-rerolling-distfiles">
<title>Rerolling Distfiles</title>
<para>Sometimes the authors of software change the content of
released distfiles without changing the file's name. You have
to verify that the changes are official and have been
performed by the author. It has happened in the past that the
distfile was silently altered on the download servers with the
intent to cause harm or compromise end user security.</para>
<para>Put the old distfile aside, download the new one, unpack
them and compare the content with &man.diff.1;. If you see
nothing suspicious, you can update
<filename>distinfo</filename>. Be sure to summarize the
differences in your PR or commit log, so that other people
know that you have taken care to ensure that nothing bad has
happened.</para>
<para>You might also want to contact the authors of the software
and confirm the changes with them.</para>
</sect1>
<sect1 xml:id="dads-avoiding-linuxisms">
<title>Avoiding Linuxisms</title>
<para>Do not use <filename>/proc</filename> if there are any
other ways of getting the information, e.g.,
<function>setprogname(argv[0])</function> in
<function>main()</function> and then &man.getprogname.3; if
you want to <quote>know your name</quote>.</para>
<para>Do not rely on behaviour that is undocumented by
<acronym>POSIX</acronym>.</para>
<para>Do not record timestamps in the critical path of the
application if it also works without. Getting timestamps may
be slow, depending on the accuracy of timestamps in the
<acronym>OS</acronym>. If timestamps are really needed,
determine how precise they have to be and use an
<acronym>API</acronym> which is documented to just deliver the
needed precision.</para>
<para>A number of simple syscalls (for example
&man.gettimeofday.2;, &man.getpid.2;) are much faster on
&linux; than on any other operating system due to caching and
the vsyscall performance optimizations. Do not rely on them
being cheap in performance-critical applications. In general,
try hard to avoid syscalls if possible.</para>
<para>Do not rely on &linux;-specific socket behaviour. In
particular, default socket buffer sizes are different (call
&man.setsockopt.2; with <literal>SO_SNDBUF</literal> and
<literal>SO_RCVBUF</literal>, and while &linux;'s &man.send.2;
blocks when the socket buffer is full, &os;'s will fail and
set <literal>ENOBUFS</literal> in errno.</para>
<para>If relying on non-standard behaviour is required,
encapsulate it properly into a generic <acronym>API</acronym>,
do a check for the behaviour in the configure stage, and stop
if it is missing.</para>
<para>Check the
<link xlink:href="http://www.freebsd.org/cgi/man.cgi">man
pages</link> to see if the function used is a
<acronym>POSIX</acronym> interface (in the
<quote>STANDARDS</quote> section of the man page).</para>
<para>Do not assume that <filename>/bin/sh</filename> is
<application>bash</application>. Ensure that a command line
passed to &man.system.3; will work with a
<acronym>POSIX</acronym> compliant shell.</para>
<para>A list of common <application>bash</application>isms is
available <link
xlink:href="https://wiki.ubuntu.com/DashAsBinSh">here</link>.</para>
<para>Check that headers are included in the
<acronym>POSIX</acronym> or man page recommended way, e.g.,
<filename>sys/types.h</filename> is often forgotten, which is
not as much of a problem for &linux; as it is for &os;.</para>
<para>Compile threaded applications with
<quote>-pthread</quote>, not <quote>-lpthread</quote> or
variations thereof.</para>
</sect1>
<sect1 xml:id="dads-misc">
<title>Miscellanea</title>
<para>The files <filename>pkg-descr</filename> and
<filename>pkg-plist</filename> should each be double-checked.
If you are reviewing a port and feel they can be worded
better, do so.</para>
<para>Do not copy more copies of the GNU General Public License
into our system, please.</para>
<para>Please be careful to note any legal issues! Do not let us
illegally distribute software!</para>
</sect1>
</chapter>

View file

@ -0,0 +1,15 @@
#
# Build the Porters Handbook with just the content from this chapter.
#
# $FreeBSD$
#
CHAPTERS= porting-samplem/chapter.xml
VPATH= ..
MASTERDOC= ${.CURDIR}/../${DOC}.${DOCBOOKSUFFIX}
DOC_PREFIX?= ${.CURDIR}/../../../..
.include "../Makefile"

View file

@ -0,0 +1,103 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!--
The FreeBSD Documentation Project
$FreeBSD$
-->
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="porting-samplem">
<title>A Sample <filename>Makefile</filename></title>
<para>Here is a sample <filename>Makefile</filename> that you can
use to create a new port. Make sure you remove all the extra
comments (ones between brackets)!</para>
<para>It is recommended that you follow this format (ordering of
variables, empty lines between sections, etc.). This format is
designed so that the most important information is easy to
locate. We recommend that you use
<link linkend="porting-portlint">portlint</link> to check the
<filename>Makefile</filename>.</para>
<programlisting>[the header...just to make it easier for us to identify the ports.]
# Created by: Satoshi Asami &lt;asami@FreeBSD.org&gt;
[The optional <emphasis>Created by:</emphasis> line names the person who originally
created the port. Note that the <quote>:</quote> is followed by a space
and not a tab character.
If this line is present, future maintainers should
not change or remove it except at the original author's request.]
# &dollar;FreeBSD&dollar;
[ ^^^^^^^^^ This will be automatically replaced with RCS ID string by SVN
when it is committed to our repository. If upgrading a port, do not alter
this line back to "&dollar;FreeBSD&dollar;". SVN deals with it automatically.]
[section to describe the port itself and the master site - PORTNAME
and PORTVERSION are always first, followed by CATEGORIES,
and then MASTER_SITES, which can be followed by MASTER_SITE_SUBDIR.
PKGNAMEPREFIX and PKGNAMESUFFIX, if needed, will be after that.
Then comes DISTNAME, EXTRACT_SUFX and/or DISTFILES, and then
EXTRACT_ONLY, as necessary.]
PORTNAME= xdvi
PORTVERSION= 18.2
CATEGORIES= print
[do not forget the trailing slash ("/")!
if you are not using MASTER_SITE_* macros]
MASTER_SITES= ${MASTER_SITE_XCONTRIB}
MASTER_SITE_SUBDIR= applications
PKGNAMEPREFIX= ja-
DISTNAME= xdvi-pl18
[set this if the source is not in the standard ".tar.gz" form]
EXTRACT_SUFX= .tar.Z
[section for distributed patches -- can be empty]
PATCH_SITES= ftp://ftp.sra.co.jp/pub/X11/japanese/
PATCHFILES= xdvi-18.patch1.gz xdvi-18.patch2.gz
[maintainer; *mandatory*! This is the person who is volunteering to
handle port updates, build breakages, and to whom a users can direct
questions and bug reports. To keep the quality of the Ports Collection
as high as possible, we no longer accept new ports that are assigned to
"ports@FreeBSD.org".]
MAINTAINER= asami@FreeBSD.org
COMMENT= DVI Previewer for the X Window System
[dependencies -- can be empty]
RUN_DEPENDS= gs:${PORTSDIR}/print/ghostscript
[this section is for other standard bsd.port.mk variables that do not
belong to any of the above]
[If it asks questions during configure, build, install...]
IS_INTERACTIVE= yes
[If it extracts to a directory other than ${DISTNAME}...]
WRKSRC= ${WRKDIR}/xdvi-new
[If the distributed patches were not made relative to ${WRKSRC}, you
may need to tweak this]
PATCH_DIST_STRIP= -p1
[If it requires a "configure" script generated by GNU autoconf to be run]
GNU_CONFIGURE= yes
[If it requires GNU make, not /usr/bin/make, to build...]
USES= gmake
[If it is an X application and requires "xmkmf -a" to be run...]
USES= imake
[et cetera.]
[non-standard variables to be used in the rules below]
MY_FAVORITE_RESPONSE= "yeah, right"
[then the special rules, in the order they are called]
pre-fetch:
i go fetch something, yeah
post-patch:
i need to do something after patch, great
pre-install:
and then some more stuff before installing, wow
[and then the epilogue]
.include &lt;bsd.port.mk&gt;</programlisting>
</chapter>

View file

@ -0,0 +1,15 @@
#
# Build the Porters Handbook with just the content from this chapter.
#
# $FreeBSD$
#
CHAPTERS= porting-why/chapter.xml
VPATH= ..
MASTERDOC= ${.CURDIR}/../${DOC}.${DOCBOOKSUFFIX}
DOC_PREFIX?= ${.CURDIR}/../../../..
.include "../Makefile"

View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!--
The FreeBSD Documentation Project
$FreeBSD$
-->
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="why-port">
<title>Introduction</title>
<para>The &os; Ports Collection is the way almost everyone
installs applications ("ports") on &os;. Like everything
else about &os;, it is primarily a volunteer effort.
It is important to keep this in mind when reading this
document.</para>
<para>In &os;, anyone may submit a new port, or volunteer
to maintain an existing port if it is unmaintained&mdash;you
do not need any special commit privileges to do so.</para>
</chapter>

View file

@ -0,0 +1,15 @@
#
# Build the Porters Handbook with just the content from this chapter.
#
# $FreeBSD$
#
CHAPTERS= quick-porting/chapter.xml
VPATH= ..
MASTERDOC= ${.CURDIR}/../${DOC}.${DOCBOOKSUFFIX}
DOC_PREFIX?= ${.CURDIR}/../../../..
.include "../Makefile"

View file

@ -0,0 +1,405 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!--
The FreeBSD Documentation Project
$FreeBSD$
-->
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="quick-porting">
<title>Quick Porting</title>
<para>This section tells you how to quickly create a new port. In
many cases, it is not sufficient, so you will have to read
further on into the document.</para>
<para>First, get the original tarball and put it into
<varname>DISTDIR</varname>, which defaults to
<filename>/usr/ports/distfiles</filename>.</para>
<note>
<para>The following assumes that the software compiled
out-of-the-box, i.e., there was absolutely no change required
for the port to work on your &os; box. If you needed to
change something, you will have to refer to the next section
too.</para>
</note>
<note>
<para>It is recommended to set the <varname>DEVELOPER</varname>
&man.make.1; variable in <filename>/etc/make.conf</filename>
before getting into porting.</para>
<screen>&prompt.root; <userinput>echo DEVELOPER=yes &gt;&gt; /etc/make.conf</userinput></screen>
<para>This setting enables the <quote>developer mode</quote>
that displays deprecation warnings and activates some further
quality checks on calling <command>make</command>.</para>
</note>
<sect1 xml:id="porting-makefile">
<title>Writing the <filename>Makefile</filename></title>
<para>The minimal <filename>Makefile</filename> would look
something like this:</para>
<programlisting># &dollar;FreeBSD&dollar;
PORTNAME= oneko
PORTVERSION= 1.1b
CATEGORIES= games
MASTER_SITES= ftp://ftp.cs.columbia.edu/archives/X11R5/contrib/
MAINTAINER= youremail@example.com
COMMENT= Cat chasing a mouse all over the screen
.include &lt;bsd.port.mk&gt;</programlisting>
<note>
<para>In some cases, the <filename>Makefile</filename> of an
existing port may contain additional lines in the header,
such as the name of the port and the date it was created.
This additional information has been declared obsolete, and
is being phased out.</para>
</note>
<para>See if you can figure it out. Do not worry about the
contents of the <literal>&dollar;FreeBSD&dollar;</literal>
line, it will be filled in automatically by
<application>Subversion</application> when the port is
imported to our main ports tree. You can find a more detailed
example in the
<link linkend="porting-samplem">sample Makefile</link>
section.</para>
</sect1>
<sect1 xml:id="porting-desc">
<title>Writing the Description Files</title>
<para>There are two description files that are required for
any port, whether they actually package or not. They are
<filename>pkg-descr</filename> and
<filename>pkg-plist</filename>. Their
<filename>pkg-</filename> prefix distinguishes them from other
files.</para>
<sect2>
<title><filename>pkg-descr</filename></title>
<para>This is a longer description of the port. One to a few
paragraphs concisely explaining what the port does is
sufficient.</para>
<note>
<para>This is <emphasis>not</emphasis> a manual or an
in-depth description on how to use or compile the port!
<emphasis>Please be careful if you are copying from the
<filename>README</filename> or manpage</emphasis>; too
often they are not a concise description of the port or
are in an awkward format (e.g., manpages have justified
spacing, which looks particularly bad with monospaced
fonts).</para>
</note>
<para>A well-written <filename>pkg-descr</filename> describes
the port completely enough that users would not have to
consult the documentation or visit the website to understand
what the software does, how it can be useful, or what
particularly nice features it has. Mentioning certain
requirements like a graphical toolkit, heavy dependencies,
runtime environment, or implementation languages help users
decide whether this port will work for them.</para>
<para>Include a URL to the official WWW homepage. Prepend
<emphasis>one</emphasis> of the websites (pick the most
common one) with <literal>WWW:</literal> (followed by single
space) so that automated tools will work correctly. If the
URI is the root of the website or directory, it should be
terminated with a slash.</para>
<note>
<para>If the listed webpage for a port is not available, try
to search the Internet first to see if the official site
moved, was renamed, or is hosted elsewhere.</para>
</note>
<para>The following example shows how your
<filename>pkg-descr</filename> should look:</para>
<programlisting>This is a port of oneko, in which a cat chases a poor mouse all over
the screen.
:
(etc.)
WWW: http://www.oneko.org/</programlisting>
</sect2>
<sect2>
<title><filename>pkg-plist</filename></title>
<para>This file lists all the files installed by the port. It
is also called the <quote>packing list</quote> because the
package is generated by packing the files listed here. The
pathnames are relative to the installation prefix (usually
<filename>/usr/local</filename>.
If the
port creates directories during installation, make sure to
add <literal>@dirrm</literal> lines to remove them when the
package is deleted.</para>
<para>Here is a small example:</para>
<programlisting>bin/oneko
man/man1/oneko.1.gz
lib/X11/app-defaults/Oneko
lib/X11/oneko/cat1.xpm
lib/X11/oneko/cat2.xpm
lib/X11/oneko/mouse.xpm
@dirrm lib/X11/oneko</programlisting>
<para>Refer to the &man.pkg-create.8; manual page for details
on the packing list.</para>
<note>
<para>It is recommended that you keep all the filenames in
this file sorted alphabetically. It will make verifying
the changes when you upgrade the port much easier.</para>
</note>
<note>
<para>Creating a packing list manually can be a very tedious
task. If the port installs a large numbers of files,
<link linkend="plist-autoplist">creating the packing list
automatically</link> might save time.</para>
</note>
<para>There is only one case when
<filename>pkg-plist</filename> can be omitted from a port.
If the port installs just a handful of files, and perhaps
directories, the files and directories may be listed in the
variables <varname>PLIST_FILES</varname> and
<varname>PLIST_DIRS</varname>, respectively, within the
port's <filename>Makefile</filename>. For instance, we
could get along without <filename>pkg-plist</filename> in
the above <filename>oneko</filename> port by adding the
following lines to the <filename>Makefile</filename>:</para>
<programlisting>PLIST_FILES= bin/oneko \
man/man1/oneko.1.gz \
lib/X11/app-defaults/Oneko \
lib/X11/oneko/cat1.xpm \
lib/X11/oneko/cat2.xpm \
lib/X11/oneko/mouse.xpm
PLIST_DIRS= lib/X11/oneko</programlisting>
<para>Of course, <varname>PLIST_DIRS</varname> should be left
unset if a port installs no directories of its own.</para>
<note>
<para>Several ports can share a common directory. In that
case, <varname>PLIST_DIRS</varname> should be replaced by
<varname>PLIST_DIRSTRY</varname> so that the directory is
removed only if empty, otherwise it is silently ignored.
<varname>PLIST_DIRS</varname> and
<varname>PLIST_DIRSTRY</varname> are equivalent to using
<literal>@dirrm</literal> and <literal>@dirrmtry</literal>
in <filename>pkg-plist</filename>, as described in
<xref linkend="plist-dir-cleaning"/>.</para>
</note>
<para>The price for this way of listing port's files and
directories is that you cannot use command sequences
described in &man.pkg-create.8;. Therefore, it is suitable
only for simple ports and makes them even simpler. At the
same time, it has the advantage of reducing the number of
files in the ports collection. Please consider using this
technique before you resort to
<filename>pkg-plist</filename>.</para>
<para>Later we will see how <filename>pkg-plist</filename>
and <varname>PLIST_FILES</varname> can be used to fulfill
<link linkend="plist">more sophisticated
tasks</link>.</para>
</sect2>
</sect1>
<sect1 xml:id="porting-checksum">
<title>Creating the Checksum File</title>
<para>Just type <command>make makesum</command>. The ports make
rules will automatically generate the file
<filename>distinfo</filename>.</para>
<para>If a file fetched has its checksum changed regularly and
you are certain the source is trusted (i.e., it comes from
manufacturer CDs or documentation generated daily), you should
specify these files in the <varname>IGNOREFILES</varname>
variable. Then the checksum is not calculated for that file
when you run <command>make makesum</command>, but set to
<literal>IGNORE</literal>.</para>
</sect1>
<sect1 xml:id="porting-testing">
<title>Testing the Port</title>
<para>You should make sure that the port rules do exactly what
you want them to do, including packaging up the port. These
are the important points you need to verify.</para>
<itemizedlist>
<listitem>
<para><filename>pkg-plist</filename> does not contain
anything not installed by the port.</para>
</listitem>
<listitem>
<para><filename>pkg-plist</filename> contains everything
that is installed by the port.</para>
</listitem>
<listitem>
<para>The port can be installed using the
<buildtarget>install</buildtarget> target. This verifies
that the install script works correctly.</para>
</listitem>
<listitem>
<para>The port can be deinstalled properly using the
<buildtarget>deinstall</buildtarget> target. This
verifies that the deinstall script works correctly.</para>
</listitem>
<listitem>
<para>Make sure that <command>make package</command> can be
run as a normal user (that is, not as
<systemitem class="username">root</systemitem>). If that
fails, <literal>NEED_ROOT=yes</literal> must be added to
the port <filename>Makefile</filename>.</para>
</listitem>
</itemizedlist>
<procedure>
<title>Recommended Test Ordering</title>
<step>
<para><command>make stage</command></para>
</step>
<step>
<para><command>make check-orphans</command></para>
</step>
<step>
<para><command>make package</command></para>
</step>
<step>
<para><command>make install</command></para>
</step>
<step>
<para><command>make deinstall</command></para>
</step>
<step>
<para><command>pkg add package-filename</command></para>
</step>
<step>
<para><command>make package</command> (as user)</para>
</step>
</procedure>
<para>Make certain no warnings are shown in any of
the stages.</para>
<para>Thorough automated testing can be done with
<package role="port">ports-mgmt/tinderbox</package> or
<package role="port">ports-mgmt/poudriere</package> from the
Ports Collection. These applications maintain
<literal>jails</literal> where all of the steps shown above
can be tested without affecting the state of the host
system.</para>
</sect1>
<sect1 xml:id="porting-portlint">
<title>Checking Your Port with
<command>portlint</command></title>
<para>Please use <command>portlint</command> to see if your port
conforms to our guidelines. The
<package role="port">ports-mgmt/portlint</package>
program is part of the ports collection. In particular, you
may want to check if the
<link linkend="porting-samplem">Makefile</link> is in the
right shape and the
<link linkend="porting-pkgname">package</link> is named
appropriately.</para>
</sect1>
<sect1 xml:id="porting-submitting">
<title>Submitting the New Port</title>
<para>Before submitting the new port, read
the <link linkend="porting-dads">DOs and DON'Ts</link>
section.</para>
<para>Once happy with your port, the only thing remaining is to
put it in the main &os; ports tree and make everybody else
happy about it too. We do not need the
<filename>work</filename> directory or the
<filename>pkgname.tgz</filename> package, so delete them
now.</para>
<para>Next, build the &man.shar.1; file. Assuming the port is
called <literal>oneko</literal>, <command>cd</command> to the
directory above where the <literal>oneko</literal> directory
is located, and then type:
<command>shar `find oneko` &gt; oneko.shar</command></para>
<para>Include <filename>oneko.shar</filename> in a bug
report and send it with &man.send-pr.1;. See
<link
xlink:href="&url.articles.contributing;/contrib-how.html#CONTRIB-GENERAL">Bug
Reports and General Commentary</link> for more information
about &man.send-pr.1;.</para>
<para>Classify the bug report as Category
<literal>ports</literal> and Class
<literal>change-request</literal>. Do
<emphasis>not</emphasis> mark the report
<literal>confidential</literal>! Add a short description of
the program to the Description field of the PR (perhaps a
short version of the <varname>COMMENT</varname>), and add the
<filename>.shar</filename> file to the Fix field.</para>
<note>
<para>Giving a good description in the synopsis of the problem
report makes the work of port committers a lot easier. We
prefer something like <quote>New port:
&lt;category&gt;/&lt;portname&gt; &lt;short description of
the port&gt;</quote> for new ports. Using this
scheme makes it easier and faster to begin the work of
committing the new port.</para>
</note>
<para>One more time, <emphasis>do not include the original
source distfile, the <filename>work</filename> directory, or
the package you built with
<command>make package</command></emphasis>; and, do use
&man.shar.1; for new ports, not &man.diff.1;.</para>
<para>After submitting the port, please be patient. The time
needed to include a new port in &os; can vary from a few days
to a few months. The list of pending port
<acronym>PR</acronym>s can be viewed at <link
xlink:href="http://www.FreeBSD.org/cgi/query-pr-summary.cgi?category=ports"></link>.</para>
<para>After looking at the new port, we will reply if necessary,
and put it in the tree. Your name will also be added to the
list of <link
xlink:href="&url.articles.contributors;/contrib-additional.html">Additional
&os; Contributors</link> and other files.</para>
</sect1>
</chapter>

View file

@ -0,0 +1,15 @@
#
# Build the Porters Handbook with just the content from this chapter.
#
# $FreeBSD$
#
CHAPTERS= security/chapter.xml
VPATH= ..
MASTERDOC= ${.CURDIR}/../${DOC}.${DOCBOOKSUFFIX}
DOC_PREFIX?= ${.CURDIR}/../../../..
.include "../Makefile"

View file

@ -0,0 +1,519 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!--
The FreeBSD Documentation Project
$FreeBSD$
-->
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="security">
<title>Security</title>
<sect1 xml:id="security-intro">
<title>Why Security is So Important</title>
<para>Bugs are occasionally introduced to the software.
Arguably, the most dangerous of them are those opening
security vulnerabilities. From the technical viewpoint, such
vulnerabilities are to be closed by exterminating the bugs
that caused them. However, the policies for handling mere
bugs and security vulnerabilities are very different.</para>
<para>A typical small bug affects only those users who have
enabled some combination of options triggering the bug. The
developer will eventually release a patch followed by a new
version of the software, free of the bug, but the majority of
users will not take the trouble of upgrading immediately
because the bug has never vexed them. A critical bug that may
cause data loss represents a graver issue. Nevertheless,
prudent users know that a lot of possible accidents, besides
software bugs, are likely to lead to data loss, and so they
make backups of important data; in addition, a critical bug
will be discovered really soon.</para>
<para>A security vulnerability is all different. First, it may
remain unnoticed for years because often it does not cause
software malfunction. Second, a malicious party can use it to
gain unauthorized access to a vulnerable system, to destroy or
alter sensitive data; and in the worst case the user will not
even notice the harm caused. Third, exposing a vulnerable
system often assists attackers to break into other systems
that could not be compromised otherwise. Therefore closing a
vulnerability alone is not enough: the audience should be
notified of it in most clear and comprehensive manner, which
will allow to evaluate the danger and take appropriate
actions.</para>
</sect1>
<sect1 xml:id="security-fix">
<title>Fixing Security Vulnerabilities</title>
<para>While on the subject of ports and packages, a security
vulnerability may initially appear in the original
distribution or in the port files. In the former case, the
original software developer is likely to release a patch or a
new version instantly, and you will only need to update the
port promptly with respect to the author's fix. If the fix is
delayed for some reason, you should either
<link linkend="dads-noinstall">mark the port as
<varname>FORBIDDEN</varname></link> or introduce a patch file
of your own to the port. In the case of a vulnerable port,
just fix the port as soon as possible. In either case,
<link linkend="port-upgrading">the standard procedure for
submitting your change</link> should be followed unless you
have rights to commit it directly to the ports tree.</para>
<important>
<para>Being a ports committer is not enough to commit to
an arbitrary port. Remember that ports usually have
maintainers, whom you should respect.</para>
</important>
<para>Please make sure that the port's revision is bumped
as soon as the vulnerability has been closed.
That is how the users who upgrade installed packages
on a regular basis will see they need to run an update.
Besides, a new package will be built and distributed
over FTP and WWW mirrors, replacing the vulnerable one.
<varname>PORTREVISION</varname> should be bumped unless
<varname>PORTVERSION</varname> has changed in the course
of correcting the vulnerability. That is you should
bump <varname>PORTREVISION</varname> if you have added a
patch file to the port, but you should not if you have updated
the port to the latest software version and thus already
touched <varname>PORTVERSION</varname>. Please refer to the
<link linkend="makefile-naming-revepoch">corresponding
section</link> for more information.</para>
</sect1>
<sect1 xml:id="security-notify">
<title>Keeping the Community Informed</title>
<sect2 xml:id="security-notify-vuxml-db">
<title>The VuXML Database</title>
<para>A very important and urgent step to take as early after
a security vulnerability is discovered as possible is to
notify the community of port users about the jeopardy. Such
notification serves two purposes. First, should the danger
be really severe it will be wise to apply an instant
workaround. E.g., stop the affected network service or even
deinstall the port completely until the vulnerability is
closed. Second, a lot of users tend to upgrade installed
packages only occasionally. They will know from the
notification that they <emphasis>must</emphasis> update the
package without delay as soon as a corrected version is
available.</para>
<para>Given the huge number of ports in the tree, a security
advisory cannot be issued on each incident without creating
a flood and losing the attention of the audience when it
comes to really serious matters. Therefore security
vulnerabilities found in ports are recorded in
<link xlink:href="http://vuxml.freebsd.org/">the &os;
VuXML database</link>. The Security Officer Team members
also monitor it for issues requiring their
intervention.</para>
<para>If you have committer rights you can update the VuXML
database by yourself. So you will both help the Security
Officer Team and deliver the crucial information to the
community earlier. However, if you are not a committer, or
you believe you have found an exceptionally severe
vulnerability please do not hesitate to contact the Security
Officer Team directly as described on the <link
xlink:href="http://www.freebsd.org/security/#how">&os;
Security Information</link> page.</para>
<para>The VuXML database is an <acronym>XML</acronym>
document. Its source file <filename>vuln.xml</filename> is
kept right inside the port
<package role="port">security/vuxml</package>. Therefore
the file's full pathname will be
<filename>PORTSDIR/security/vuxml/vuln.xml</filename>. Each
time you discover a security vulnerability in a port, please
add an entry for it to that file. Until you are familiar
with VuXML, the best thing you can do is to find an existing
entry fitting your case, then copy it and use it as a
template.</para>
</sect2>
<sect2 xml:id="security-notify-vuxml-intro">
<title>A Short Introduction to VuXML</title>
<para>The full-blown <acronym>XML</acronym> format is complex,
and far beyond the scope of this book. However, to gain
basic insight on the structure of a VuXML entry you need
only the notion of tags. XML tag names are enclosed in
angle brackets. Each opening &lt;tag&gt; must have a
matching closing &lt;/tag&gt;. Tags may be nested. If
nesting, the inner tags must be closed before the outer
ones. There is a hierarchy of tags, i.e., more complex
rules of nesting them. This is similar to HTML. The major
difference is that XML is e<emphasis>X</emphasis>tensible,
i.e., based on defining custom tags. Due to its intrinsic
structure XML puts otherwise amorphous data into shape.
VuXML is particularly tailored to mark up descriptions of
security vulnerabilities.</para>
<para>Now consider a realistic VuXML entry:</para>
<programlisting>&lt;vuln vid="f4bc80f4-da62-11d8-90ea-0004ac98a7b9"&gt; <co xml:id="co-vx-vid"/>
&lt;topic&gt;Several vulnerabilities found in Foo&lt;/topic&gt; <co xml:id="co-vx-top"/>
&lt;affects&gt;
&lt;package&gt;
&lt;name&gt;foo&lt;/name&gt; <co xml:id="co-vx-nam"/>
&lt;name&gt;foo-devel&lt;/name&gt;
&lt;name&gt;ja-foo&lt;/name&gt;
&lt;range&gt;&lt;ge&gt;1.6&lt;/ge&gt;&lt;lt&gt;1.9&lt;/lt&gt;&lt;/range&gt; <co xml:id="co-vx-rng"/>
&lt;range&gt;&lt;ge&gt;2.*&lt;/ge&gt;&lt;lt&gt;2.4_1&lt;/lt&gt;&lt;/range&gt;
&lt;range&gt;&lt;eq&gt;3.0b1&lt;/eq&gt;&lt;/range&gt;
&lt;/package&gt;
&lt;package&gt;
&lt;name&gt;openfoo&lt;/name&gt; <co xml:id="co-vx-nm2"/>
&lt;range&gt;&lt;lt&gt;1.10_7&lt;/lt&gt;&lt;/range&gt; <co xml:id="co-vx-epo"/>
&lt;range&gt;&lt;ge&gt;1.2,1&lt;/ge&gt;&lt;lt&gt;1.3_1,1&lt;/lt&gt;&lt;/range&gt;
&lt;/package&gt;
&lt;/affects&gt;
&lt;description&gt;
&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;
&lt;p&gt;J. Random Hacker reports:&lt;/p&gt; <co xml:id="co-vx-bdy"/>
&lt;blockquote
cite="http://j.r.hacker.com/advisories/1"&gt;
&lt;p&gt;Several issues in the Foo software may be exploited
via carefully crafted QUUX requests. These requests will
permit the injection of Bar code, mumble theft, and the
readability of the Foo administrator account.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/body&gt;
&lt;/description&gt;
&lt;references&gt; <co xml:id="co-vx-ref"/>
&lt;freebsdsa&gt;SA-10:75.foo&lt;/freebsdsa&gt; <co xml:id="co-vx-fsa"/>
&lt;freebsdpr&gt;ports/987654&lt;/freebsdpr&gt; <co xml:id="co-vx-fpr"/>
&lt;cvename&gt;CAN-2010-0201&lt;/cvename&gt; <co xml:id="co-vx-cve"/>
&lt;cvename&gt;CAN-2010-0466&lt;/cvename&gt;
&lt;bid&gt;96298&lt;/bid&gt; <co xml:id="co-vx-bid"/>
&lt;certsa&gt;CA-2010-99&lt;/certsa&gt; <co xml:id="co-vx-cts"/>
&lt;certvu&gt;740169&lt;/certvu&gt; <co xml:id="co-vx-ctv"/>
&lt;uscertsa&gt;SA10-99A&lt;/uscertsa&gt; <co xml:id="co-vx-ucs"/>
&lt;uscertta&gt;SA10-99A&lt;/uscertta&gt; <co xml:id="co-vx-uct"/>
&lt;mlist msgid="201075606@hacker.com"&gt;http://marc.theaimsgroup.com/?l=bugtraq&amp;amp;m=203886607825605&lt;/mlist&gt; <co xml:id="co-vx-mls"/>
&lt;url&gt;http://j.r.hacker.com/advisories/1&lt;/url&gt; <co xml:id="co-vx-url"/>
&lt;/references&gt;
&lt;dates&gt;
&lt;discovery&gt;2010-05-25&lt;/discovery&gt; <co xml:id="co-vx-dsc"/>
&lt;entry&gt;2010-07-13&lt;/entry&gt; <co xml:id="co-vx-ent"/>
&lt;modified&gt;2010-09-17&lt;/modified&gt; <co xml:id="co-vx-mod"/>
&lt;/dates&gt;
&lt;/vuln&gt;</programlisting>
<para>The tag names are supposed to be self-explanatory so we
shall take a closer look only at fields you will need to
fill in by yourself:</para>
<calloutlist>
<callout arearefs="co-vx-vid">
<para>This is the top-level tag of a VuXML entry. It has
a mandatory attribute, <literal>vid</literal>,
specifying a universally unique identifier (UUID) for
this entry (in quotes). You should generate a UUID for
each new VuXML entry (and do not forget to substitute it
for the template UUID unless you are writing the entry
from scratch). You can use &man.uuidgen.1; to generate
a VuXML UUID.</para>
</callout>
<callout arearefs="co-vx-top">
<para>This is a one-line description of the issue
found.</para>
</callout>
<callout arearefs="co-vx-nam">
<para>The names of packages affected are listed there.
Multiple names can be given since several packages may
be based on a single master port or software product.
This may include stable and development branches,
localized versions, and slave ports featuring different
choices of important build-time configuration
options.</para>
<important>
<para>It is your responsibility to find all such related
packages when writing a VuXML entry. Keep in mind
that <literal>make search name=foo</literal> is your
friend. The primary points to look for are as
follows:</para>
<itemizedlist>
<listitem>
<para>the <filename>foo-devel</filename> variant
for a <filename>foo</filename> port;</para>
</listitem>
<listitem>
<para>other variants with a suffix like
<literal>-a4</literal> (for print-related
packages), <literal>-without-gui</literal> (for
packages with X support disabled), or
similar;</para>
</listitem>
<listitem>
<para><literal>jp-</literal>,
<literal>ru-</literal>, <literal>zh-</literal>,
and other possible localized variants in the
corresponding national categories of the ports
collection.</para>
</listitem>
</itemizedlist>
</important>
</callout>
<callout arearefs="co-vx-rng">
<para>Affected versions of the package(s) are specified
there as one or more ranges using a combination of
<literal>&lt;lt&gt;</literal>,
<literal>&lt;le&gt;</literal>,
<literal>&lt;eq&gt;</literal>,
<literal>&lt;ge&gt;</literal>, and
<literal>&lt;gt&gt;</literal> elements. The version
ranges given should not overlap.</para>
<para>In a range specification, <literal>*</literal>
(asterisk) denotes the smallest version number. In
particular, <literal>2.*</literal> is less than
<literal>2.a</literal>. Therefore an asterisk may be
used for a range to match all possible
<literal>alpha</literal>, <literal>beta</literal>, and
<literal>RC</literal> versions. For instance,
<literal>&lt;ge&gt;2.*&lt;/ge&gt;&lt;lt&gt;3.*&lt;/lt&gt;</literal>
will selectively match every <literal>2.x</literal>
version while
<literal>&lt;ge&gt;2.0&lt;/ge&gt;&lt;lt&gt;3.0&lt;/lt&gt;</literal>
will not since the latter misses
<literal>2.r3</literal> and matches
<literal>3.b</literal>.</para>
<para>The above example specifies that affected are
versions from <literal>1.6</literal> to
<literal>1.9</literal> inclusive, versions
<literal>2.x</literal> before <literal>2.4_1</literal>,
and version <literal>3.0b1</literal>.</para>
</callout>
<callout arearefs="co-vx-nm2">
<para>Several related package groups (essentially, ports)
can be listed in the <literal>&lt;affected&gt;</literal>
section. This can be used if several software products
(say FooBar, FreeBar and OpenBar) grow from the same
code base and still share its bugs and vulnerabilities.
Note the difference from listing multiple names within a
single &lt;package&gt; section.</para>
</callout>
<callout arearefs="co-vx-epo">
<para>The version ranges should allow for
<varname>PORTEPOCH</varname> and
<varname>PORTREVISION</varname> if applicable. Please
remember that according to the collation rules, a
version with a non-zero <varname>PORTEPOCH</varname> is
greater than any version without
<varname>PORTEPOCH</varname>, e.g.,
<literal>3.0,1</literal> is greater than
<literal>3.1</literal> or even than
<literal>8.9</literal>.</para>
</callout>
<callout arearefs="co-vx-bdy">
<para>This is a summary of the issue. XHTML is used in
this field. At least enclosing
<literal>&lt;p&gt;</literal> and
<literal>&lt;/p&gt;</literal> should appear. More
complex mark-up may be used, but only for the sake of
accuracy and clarity: No eye candy please.</para>
</callout>
<callout arearefs="co-vx-ref">
<para>This section contains references to relevant
documents. As many references as apply are
encouraged.</para>
</callout>
<callout arearefs="co-vx-fsa">
<para>This is a <link
xlink:href="http://www.freebsd.org/security/#adv">&os;
security advisory</link>.</para>
</callout>
<callout arearefs="co-vx-fpr">
<para>This is a <link
xlink:href="http://www.freebsd.org/support.html#gnats">&os;
problem report</link>.</para>
</callout>
<callout arearefs="co-vx-cve">
<para>This is a
<link xlink:href="http://www.cve.mitre.org/">MITRE
CVE</link> identifier.</para>
</callout>
<callout arearefs="co-vx-bid">
<para>This is a <link
xlink:href="http://www.securityfocus.com/bid">SecurityFocus
Bug ID</link>.</para>
</callout>
<callout arearefs="co-vx-cts">
<para>This is a
<link xlink:href="http://www.cert.org/">US-CERT</link>
security advisory.</para>
</callout>
<callout arearefs="co-vx-ctv">
<para>This is a
<link xlink:href="http://www.cert.org/">US-CERT</link>
vulnerability note.</para>
</callout>
<callout arearefs="co-vx-ucs">
<para>This is a
<link xlink:href="http://www.cert.org/">US-CERT</link>
Cyber Security Alert.</para>
</callout>
<callout arearefs="co-vx-uct">
<para>This is a
<link xlink:href="http://www.cert.org/">US-CERT</link>
Technical Cyber Security Alert.</para>
</callout>
<callout arearefs="co-vx-mls">
<para>This is a URL to an archived posting in a mailing
list. The attribute <literal>msgid</literal> is
optional and may specify the message ID of the
posting.</para>
</callout>
<callout arearefs="co-vx-url">
<para>This is a generic URL. It should be used only if
none of the other reference categories apply.</para>
</callout>
<callout arearefs="co-vx-dsc">
<para>This is the date when the issue was disclosed
(<replaceable>YYYY-MM-DD</replaceable>).</para>
</callout>
<callout arearefs="co-vx-ent">
<para>This is the date when the entry was added
(<replaceable>YYYY-MM-DD</replaceable>).</para>
</callout>
<callout arearefs="co-vx-mod">
<para>This is the date when any information in the entry
was last modified
(<replaceable>YYYY-MM-DD</replaceable>). New entries
must not include this field. It should be added upon
editing an existing entry.</para>
</callout>
</calloutlist>
</sect2>
<sect2 xml:id="security-notify-vuxml-testing">
<title>Testing Your Changes to the VuXML Database</title>
<para>Assume you just wrote or filled in an entry for a
vulnerability in the package <literal>clamav</literal> that
has been fixed in version <literal>0.65_7</literal>.</para>
<para>As a prerequisite, you need to
<emphasis>install</emphasis> fresh versions of the ports
<package role="port">ports-mgmt/portaudit</package>,
<package role="port">ports-mgmt/portaudit-db</package>,
and
<package role="port">security/vuxml</package>.</para>
<note>
<para>To run <command>packaudit</command> you must have
permission to write to its
<filename>DATABASEDIR</filename>,
typically <filename>/var/db/portaudit</filename>.</para>
<para>To use a different directory set the
<filename>DATABASEDIR</filename>
environment variable to a different location.</para>
<para>If you are working in a directory other than
<filename>${PORTSDIR}/security/vuxml</filename> set the
<filename>VUXMLDIR</filename>
environment variable to the directory where
<filename>vuln.xml</filename> is located.</para>
</note>
<para>First, check whether there already is an entry for this
vulnerability. If there were such an entry, it would match
the previous version of the package,
<literal>0.65_6</literal>:</para>
<screen>&prompt.user; <userinput>packaudit</userinput>
&prompt.user; <userinput>portaudit clamav-0.65_6</userinput></screen>
<para>If there is none found, you have the green light to add
a new entry for this vulnerability.</para>
<screen>&prompt.user; <userinput>cd ${PORTSDIR}/security/vuxml</userinput>
&prompt.user; <userinput>make newentry</userinput></screen>
<para>When you are done verify its syntax and
formatting.</para>
<screen>&prompt.user; <userinput>make validate</userinput></screen>
<note>
<para>You will need at least one of the following packages
installed:
<package role="port">textproc/libxml2</package>,
<package role="port">textproc/jade</package>.</para>
</note>
<para>Now rebuild the <command>portaudit</command> database
from the VuXML file:</para>
<screen>&prompt.user; <userinput>packaudit</userinput></screen>
<para>To verify that the <literal>&lt;affected&gt;</literal>
section of your entry will match correct package(s), issue
the following command:</para>
<screen>&prompt.user; <userinput>portaudit -f /usr/ports/INDEX -r uuid</userinput></screen>
<note>
<para>Please refer to &man.portaudit.1; for better
understanding of the command syntax.</para>
</note>
<para>Make sure that your entry produces no spurious matches
in the output.</para>
<para>Now check whether the right package versions are matched
by your entry:</para>
<screen>&prompt.user; <userinput>portaudit clamav-0.65_6 clamav-0.65_7</userinput>
Affected package: clamav-0.65_6 (matched by clamav&lt;0.65_7)
Type of problem: clamav remote denial-of-service.
Reference: &lt;http://www.freebsd.org/ports/portaudit/74a9541d-5d6c-11d8-80e3-0020ed76ef5a.html&gt;
1 problem(s) found.</screen>
<para>The former version should match while the latter one
should not.</para>
<para>Finally, verify whether the web page generated from the
VuXML database looks like expected:</para>
<screen>&prompt.user; <userinput>mkdir -p ~/public_html/portaudit</userinput>
&prompt.user; <userinput>packaudit</userinput>
&prompt.user; <userinput>lynx ~/public_html/portaudit/74a9541d-5d6c-11d8-80e3-0020ed76ef5a.html</userinput></screen>
</sect2>
</sect1>
</chapter>

View file

@ -0,0 +1,15 @@
#
# Build the Porters Handbook with just the content from this chapter.
#
# $FreeBSD$
#
CHAPTERS= slow-porting/chapter.xml
VPATH= ..
MASTERDOC= ${.CURDIR}/../${DOC}.${DOCBOOKSUFFIX}
DOC_PREFIX?= ${.CURDIR}/../../../..
.include "../Makefile"

View file

@ -0,0 +1,430 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!--
The FreeBSD Documentation Project
$FreeBSD$
-->
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="slow-porting">
<title>Slow Porting</title>
<para>Okay, so it was not that simple, and the port required some
modifications to get it to work. In this section, we will
explain, step by step, how to modify it to get it to work with
the ports paradigm.</para>
<sect1 xml:id="slow-work">
<title>How Things Work</title>
<para>First, this is the sequence of events which occurs when
the user first types <command>make</command> in your port's
directory. You may find that having
<filename>bsd.port.mk</filename> in another window while you
read this really helps to understand it.</para>
<para>But do not worry if you do not really understand what
<filename>bsd.port.mk</filename> is doing, not many people
do... <!-- smiley --><emphasis>:-)</emphasis></para>
<procedure>
<step>
<para>The <buildtarget>fetch</buildtarget> target is run.
The <buildtarget>fetch</buildtarget> target is responsible
for making sure that the tarball exists locally in
<varname>DISTDIR</varname>. If
<buildtarget>fetch</buildtarget> cannot find the required
files in <varname>DISTDIR</varname> it will look up the
URL <varname>MASTER_SITES</varname>, which is set in the
Makefile, as well as our FTP mirrors where we put
distfiles as backup. It will then attempt to fetch the
named distribution file with <varname>FETCH</varname>,
assuming that the requesting site has direct access to the
Internet. If that succeeds, it will save the file in
<varname>DISTDIR</varname> for future use and
proceed.</para>
</step>
<step>
<para>The <buildtarget>extract</buildtarget> target is run.
It looks for your port's distribution file (typically a
<command>gzip</command>ped tarball) in
<varname>DISTDIR</varname> and unpacks it into a temporary
subdirectory specified by <varname>WRKDIR</varname>
(defaults to <filename>work</filename>).</para>
</step>
<step>
<para>The <buildtarget>patch</buildtarget> target is run.
First, any patches defined in
<varname>PATCHFILES</varname> are applied. Second, if any
patch files named
<filename>patch-*</filename>
are found in <varname>PATCHDIR</varname> (defaults to the
<filename>files</filename> subdirectory), they are applied
at this time in alphabetical order.</para>
</step>
<step>
<para>The <buildtarget>configure</buildtarget> target is
run. This can do any one of many different things.</para>
<orderedlist>
<listitem>
<para>If it exists,
<filename>scripts/configure</filename> is run.</para>
</listitem>
<listitem>
<para>If <varname>HAS_CONFIGURE</varname> or
<varname>GNU_CONFIGURE</varname> is set,
<filename>WRKSRC/configure</filename>
is run.</para>
</listitem>
</orderedlist>
</step>
<step>
<para>The <buildtarget>build</buildtarget> target is run.
This is responsible for descending into the port's private
working directory (<varname>WRKSRC</varname>) and building
it.</para>
</step>
<step>
<para>The <buildtarget>stage</buildtarget> target is run.
This puts the final set of built files into a temporary
directory (<varname>STAGEDIR</varname>, see
<xref linkend="staging"/>). The hierarchy of this
directory mirrors that of the system on which the package
will be installed.</para>
</step>
<step>
<para>The <buildtarget>install</buildtarget> target is run.
This copies the files listed in the port's pkg-plist to
the host system.</para>
</step>
</procedure>
<para>The above are the default actions. In addition, you can
define targets
<buildtarget>pre-<replaceable>something</replaceable></buildtarget>
or
<buildtarget>post-<replaceable>something</replaceable></buildtarget>,
or put scripts with those names, in the
<filename>scripts</filename> subdirectory, and they will be
run before or after the default actions are done.</para>
<para>For example, if you have a
<buildtarget>post-extract</buildtarget> target defined in your
<filename>Makefile</filename>, and a file
<filename>pre-build</filename> in the
<filename>scripts</filename> subdirectory, the
<buildtarget>post-extract</buildtarget> target will be called
after the regular extraction actions, and the
<filename>pre-build</filename> script will be executed before
the default build rules are done. It is recommended that you
use <filename>Makefile</filename> targets if the actions are
simple enough, because it will be easier for someone to figure
out what kind of non-default action the port requires.</para>
<para>The default actions are done by the
<filename>bsd.port.mk</filename> targets
<buildtarget>do-<replaceable>something</replaceable></buildtarget>.
For example, the commands to extract a port are in the target
<buildtarget>do-extract</buildtarget>. If you are not happy
with the default target, you can fix it by redefining the
<buildtarget>do-<replaceable>something</replaceable></buildtarget>
target in your <filename>Makefile</filename>.</para>
<note>
<para>The <quote>main</quote> targets (e.g.,
<buildtarget>extract</buildtarget>,
<buildtarget>configure</buildtarget>, etc.) do nothing more
than make sure all the stages up to that one are completed
and call the real targets or scripts, and they are not
intended to be changed. If you want to fix the extraction,
fix <buildtarget>do-extract</buildtarget>, but never ever
change the way <buildtarget>extract</buildtarget>
operates! Additionally, the target
<buildtarget>post-deinstall</buildtarget> is invalid and
is not run by the ports infrastructure.</para>
</note>
<para>Now that you understand what goes on when the user types
<command>make install</command>, let
us go through the recommended steps to create the perfect
port.</para>
</sect1>
<sect1 xml:id="slow-sources">
<title>Getting the Original Sources</title>
<para>Get the original sources (normally) as a compressed
tarball
(<filename>foo.tar.gz</filename> or
<filename>foo.tar.bz2</filename>)
and copy it into <varname>DISTDIR</varname>. Always use
<emphasis>mainstream</emphasis> sources when and where you
can.</para>
<para>You will need to set the variable
<varname>MASTER_SITES</varname> to reflect where the original
tarball resides. You will find convenient shorthand
definitions for most mainstream sites in
<filename>bsd.sites.mk</filename>. Please use these
sites&mdash;and the associated definitions&mdash;if at all
possible, to help avoid the problem of having the same
information repeated over again many times in the source base.
As these sites tend to change over time, this becomes a
maintenance nightmare for everyone involved.</para>
<para>If you cannot find a FTP/HTTP site that is well-connected
to the net, or can only find sites that have irritatingly
non-standard formats, you might want to put a copy on a
reliable FTP or HTTP server that you control (e.g., your home
page).</para>
<para>If you cannot find somewhere convenient and reliable to
put the distfile we can <quote>house</quote> it ourselves on
<systemitem>ftp.FreeBSD.org</systemitem>; however, this is the
least-preferred solution. The distfile must be placed into
<filename>~/public_distfiles/</filename> of someone's
<systemitem>freefall</systemitem> account. Ask the person who
commits your port to do this. This person will also set
<varname>MASTER_SITES</varname> to
<varname>MASTER_SITE_LOCAL</varname> and
<varname>MASTER_SITE_SUBDIR</varname> to their
<systemitem>freefall</systemitem> username.</para>
<para>If your port's distfile changes all the time without any
kind of version update by the author, consider putting the
distfile on your home page and listing it as the first
<varname>MASTER_SITES</varname>. If you can, try to talk the
port author out of doing this; it really does help to
establish some kind of source code control. Hosting your own
version will prevent users from getting
<errorname>checksum mismatch</errorname> errors, and also
reduce the workload of maintainers of our FTP site. Also, if
there is only one master site for the port, it is recommended
that you house a backup at your site and list it as the second
<varname>MASTER_SITES</varname>.</para>
<para>If your port requires some additional `patches' that are
available on the Internet, fetch them too and put them in
<varname>DISTDIR</varname>. Do not worry if they come from a
site other than where you got the main source tarball, we have
a way to handle these situations (see the description of
<link linkend="porting-patchfiles">PATCHFILES</link>
below).</para>
</sect1>
<sect1 xml:id="slow-modifying">
<title>Modifying the Port</title>
<para>Unpack a copy of the tarball in a private directory and
make whatever changes are necessary to get the port to compile
properly under the current version of &os;. Keep
<emphasis>careful track</emphasis> of everything you do, as
you will be automating the process shortly. Everything,
including the deletion, addition, or modification of files
should be doable using an automated script or patch file when
your port is finished.</para>
<para>If your port requires significant user
interaction/customization to compile or install, you should
take a look at one of Larry Wall's classic
<application>Configure</application> scripts and perhaps do
something similar yourself. The goal of the new ports
collection is to make each port as
<quote>plug-and-play</quote> as possible for the end-user
while using a minimum of disk space.</para>
<note>
<para>Unless explicitly stated, patch files, scripts, and
other files you have created and contributed to the &os;
ports collection are assumed to be covered by the standard
BSD copyright conditions.</para>
</note>
</sect1>
<sect1 xml:id="slow-patch">
<title>Patching</title>
<para>In the preparation of the port, files that have been added
or changed can be recorded with &man.diff.1; for later
feeding to &man.patch.1;. Doing this with a typical file
involves saving a copy of the original file before making any
changes.</para>
<screen>&prompt.user; <userinput>cp <replaceable>file</replaceable> <replaceable>file</replaceable>.orig</userinput></screen>
<para>Patches are saved into files named
<filename>patch-*</filename> where
<replaceable>*</replaceable> indicates the pathname of the
file that is patched, such as
<filename>patch-Imakefile</filename> or
<filename>patch-src-config.h</filename>.</para>
<para>After the file has been modified, &man.diff.1; is used to
record the differences between the original and the modified
version. <option>-u</option> causes &man.diff.1; to produce
<quote>unified</quote> diffs, the preferred form.</para>
<screen>&prompt.user; <userinput>diff -u <replaceable>file</replaceable>.orig <replaceable>file</replaceable> &gt; patch-<replaceable>pathname-file</replaceable></userinput></screen>
<para>When generating patches for new, added files,
<option>-N</option> is added to tell &man.diff.1; to treat the
non-existent original file as if it existed but was
empty:</para>
<screen>&prompt.user; <userinput>diff -u -N <replaceable>newfile</replaceable>.orig <replaceable>newfile</replaceable> &gt; patch-<replaceable>pathname-newfile</replaceable></userinput></screen>
<para>Patch files are stored in <varname>PATCHDIR</varname>
(usually <filename class="directory">files/</filename>, from
where they will be automatically applied. All patches must be
relative to <varname>WRKSRC</varname> (generally the directory
the port's tarball unpacks itself into, that being where the
build is done). To make fixes and upgrades easier, avoid
having more than one patch fix the same file (that is,
<filename>patch-file</filename> and
<filename>patch-file2</filename> both changing
<filename>WRKSRC/foobar.c</filename>). Note that if the path
of a patched file contains an underscore
(<literal>_</literal>) character, the patch needs to have two
underscores instead in its name. For example, to patch a file
named <filename>src/freeglut_joystick.c</filename>, the
corresponding patch should be named
<filename>patch-src-freeglut__joystick.c</filename>.</para>
<para>Please only use characters
<literal>[-+._a-zA-Z0-9]</literal> for naming patches. Do not
use any other characters besides them. Do not name patches
like <filename>patch-aa</filename> or
<filename>patch-ab</filename>, always mention the path and
file name in patch names.</para>
<para>There is an alternate, easier method for creating patches
to existing files. The first steps are the same, make a copy
of the unmodified file with an <filename>.orig</filename>
extension, then make modifications. Then use
<command>make makepatch</command> to write updated patch files
to the <filename>files</filename> directory of the
port.</para>
<para>Do not put RCS strings in patches.
<application>Subversion</application> 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
(<literal>&dollar;</literal>) signs, and typically start with
<literal>&dollar;Id</literal> or
<literal>&dollar;RCS</literal>.</para>
<para>Using the recurse (<option>-r</option>) option to
&man.diff.1; to generate patches is fine, but please
look at the resulting patches to make sure there is no
unnecessary junk in there. In particular, diffs between two
backup files, <filename>Makefile</filename>s when the port
uses <command>Imake</command> or GNU
<command>configure</command>, etc., are unnecessary and should
be deleted. If it was necessary to edit
<filename>configure.in</filename> and run
<command>autoconf</command> to regenerate
<command>configure</command>, do not take the diffs of
<command>configure</command> (it often grows to a few thousand
lines!). Instead, define
<literal>USE_AUTOTOOLS=autoconf:261</literal> and take the
diffs of <filename>configure.in</filename>.</para>
<para>Try to minimize the amount of non-functional whitespace
changes in patches. It is common in the Open Source world for
projects to share large amounts of a code base, but obey
different style and indenting rules. When taking a working
piece of functionality from one project to fix similar areas
in another, please be careful: the resulting line patch may be
full of non-functional changes. It not only increases the
size of the <application>Subversion</application> repository
but makes it hard to find out what exactly caused the problem
and what was changed at all.</para>
<para>If a file must be deleted, do it in the
<buildtarget>post-extract</buildtarget> target rather than as
part of the patch.</para>
<para>Simple replacements can be performed directly from the
port <filename>Makefile</filename> using the in-place mode of
&man.sed.1;. This is useful when changes use the value of a
variable:</para>
<programlisting>post-patch:
@${REINPLACE_CMD} -e 's|for Linux|for FreeBSD|g' ${WRKSRC}/README</programlisting>
<para>Quite often, software being ported uses the CR/LF
convention in source files. This may cause problems with
further patching, compiler warnings, or script execution (like
<literal>/bin/sh^M not found</literal>.) To quickly convert
all files from CR/LF to just LF, add this entry to the port
<filename>Makefile</filename>:</para>
<programlisting>USES= dos2unix</programlisting>
<para>A list of specific files to convert can
be given:</para>
<programlisting>USES= dos2unix
DOS2UNIX_FILES= util.c util.h</programlisting>
<para>Use <varname>DOS2UNIX_REGEX</varname> to convert a group
of files across subdirectories. Its argument is a
&man.find.1;-compatible regular expression. More on the
format is in &man.re.format.7;. This option is useful for
converting all files of a given extension. For example,
convert all source code files, leaving binary files
intact:</para>
<programlisting>USES= dos2unix
DOS2UNIX_REGEX= .*\.([ch]|cpp)</programlisting>
<para>A similar option is <varname>DOS2UNIX_GLOB</varname>,
which invokes <command>find</command> for each element listed
in it.</para>
<programlisting>USES= dos2unix
DOS2UNIX_GLOB= *.c *.cpp *.h</programlisting>
</sect1>
<sect1 xml:id="slow-configure">
<title>Configuring</title>
<para>Include any additional customization commands in your
<filename>configure</filename> script and save it in the
<filename>scripts</filename> subdirectory. As mentioned
above, you can also do this with <filename>Makefile</filename>
targets and/or scripts with the name
<filename>pre-configure</filename> or
<filename>post-configure</filename>.</para>
</sect1>
<sect1 xml:id="slow-user-input">
<title>Handling User Input</title>
<para>If your port requires user input to build, configure, or
install, you must set <varname>IS_INTERACTIVE</varname> in
your <filename>Makefile</filename>. This will allow
<quote>overnight builds</quote> to skip your port if the user
sets the variable <envar>BATCH</envar> in his environment (and
if the user sets the variable <envar>INTERACTIVE</envar>, then
<emphasis>only</emphasis> those ports requiring interaction
are built). This will save a lot of wasted time on the set of
machines that continually build ports (see below).</para>
<para>It is also recommended that if there are reasonable
default answers to the questions, you check the
<varname>PACKAGE_BUILDING</varname> variable and turn off the
interactive script when it is set. This will allow us to
build the packages for CDROMs and FTP.</para>
</sect1>
</chapter>

View file

@ -0,0 +1,15 @@
#
# Build the Porters Handbook with just the content from this chapter.
#
# $FreeBSD$
#
CHAPTERS= specials/chapter.xml
VPATH= ..
MASTERDOC= ${.CURDIR}/../${DOC}.${DOCBOOKSUFFIX}
DOC_PREFIX?= ${.CURDIR}/../../../..
.include "../Makefile"

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,15 @@
#
# Build the Porters Handbook with just the content from this chapter.
#
# $FreeBSD$
#
CHAPTERS= testing/chapter.xml
VPATH= ..
MASTERDOC= ${.CURDIR}/../${DOC}.${DOCBOOKSUFFIX}
DOC_PREFIX?= ${.CURDIR}/../../../..
.include "../Makefile"

View file

@ -0,0 +1,201 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!--
The FreeBSD Documentation Project
$FreeBSD$
-->
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="testing">
<title>Testing the Port</title>
<sect1 xml:id="make-describe">
<title>Running <command>make describe</command></title>
<para>Several of the &os; port maintenance tools, such as
&man.portupgrade.1;, rely on a database called
<filename>/usr/ports/INDEX</filename> which keeps track of
such items as port dependencies. <filename>INDEX</filename>
is created by the top-level
<filename>ports/Makefile</filename> via
<command>make index</command>, which descends into each port
subdirectory and executes <command>make describe</command>
there. Thus, if <command>make describe</command> fails in any
port, no one can generate <filename>INDEX</filename>, and many
people will quickly become unhappy.</para>
<note>
<para>It is important to be able to generate this file no
matter what options are present in
<filename>make.conf</filename>, so please avoid doing things
such as using <literal>.error</literal> statements when (for
instance) a dependency is not satisfied. (See
<xref linkend="dads-dot-error"/>.)</para>
</note>
<para>If <command>make describe</command> produces a string
rather than an error message, you are probably safe. See
<filename>bsd.port.mk</filename> for the meaning of the
string produced.</para>
<para>Also note that running a recent version of
<command>portlint</command> (as specified in the next section)
will cause <command>make describe</command> to be run
automatically.</para>
</sect1>
<sect1 xml:id="testing-portlint">
<title>Portlint</title>
<para>Do check your work with <link
linkend="porting-portlint"><command>portlint</command></link>
before you submit or commit it. <command>portlint</command>
warns you about many common errors, both functional and
stylistic. For a new (or repocopied) port,
<command>portlint -A</command> is the most thorough; for an
existing port, <command>portlint -C</command> is
sufficient.</para>
<para>Since <command>portlint</command> uses heuristics to
try to figure out errors, it can produce false positive
warnings. In addition, occasionally something that is
flagged as a problem really cannot be done in any other
way due to limitations in the ports framework. When in
doubt, the best thing to do is ask on &a.ports;.</para>
</sect1>
<sect1 xml:id="testing-porttools">
<title>Port Tools</title>
<para>The
<package role="port">ports-mgmt/porttools</package>
program is part of the Ports Collection.</para>
<para><command>port</command> is the front-end script, which can
help you simplify the testing job. Whenever you want to test
a new port or update an existing one, you can use
<command>port test</command> to test your port, including the
<link
linkend="testing-portlint"><command>portlint</command></link>
checking. This command also detects and lists any files that
are not listed in <filename>pkg-plist</filename>. See the
following example:</para>
<screen>&prompt.root; <userinput>port test /usr/ports/net/csup</userinput></screen>
</sect1>
<sect1 xml:id="porting-prefix">
<title><varname>PREFIX</varname> and
<varname>DESTDIR</varname></title>
<para><varname>PREFIX</varname> determines where the port will
be installed. It defaults to <filename>/usr/local</filename>,
but can be set by the user to a custom path like
<filename>/opt</filename>. Your port must respect the value
of this variable.</para>
<para><varname>DESTDIR</varname>, if set by the user, determines
the complete alternative environment, usually a jail or an
installed system mounted somewhere other than
<filename>/</filename>. A port will actually install into
<filename>DESTDIR/PREFIX</filename>,
and register with the package database in
<filename>DESTDIR/var/db/pkg</filename>.
As <varname>DESTDIR</varname> is handled automatically by the
ports infrastructure with &man.chroot.8;, you do not need any
modifications or any extra care to write
<varname>DESTDIR</varname>-compliant ports.</para>
<para>The value of <varname>PREFIX</varname> will be set to
<varname>LOCALBASE</varname> (defaulting to
<filename>/usr/local</filename>). If
<varname>USE_LINUX_PREFIX</varname> is set,
<varname>PREFIX</varname> will be <varname>LINUXBASE</varname>
(defaulting to <filename>/compat/linux</filename>).</para>
<para>Avoiding hard-coded <filename>/usr/local</filename> paths
in the source makes the port much more flexible and able to
cater to the needs of other sites. Often, this can be
accomplished by simply replacing occurrences of
<filename>/usr/local</filename> in the port's various
<filename>Makefile</filename>s with
<literal>&dollar;{PREFIX}</literal>. This variable is
automatically passed down to every stage of the build and
install processes.</para>
<para>Make sure your application is not installing things in
<filename>/usr/local</filename> instead of
<varname>PREFIX</varname>. A quick test for such hard-coded
paths is:</para>
<screen>&prompt.root; <userinput>make clean; make package PREFIX=/var/tmp/`make -V PORTNAME`</userinput></screen>
<para>If anything is installed outside of
<varname>PREFIX</varname>, the package creation process will
complain that it cannot find the files.</para>
<para>In addition, it is worth checking the same with the
stage directory support (see
<xref linkend="staging"/>):</para>
<screen>&prompt.root; <userinput>make stage &amp;&amp; make check-orphans &amp;&amp; make package</userinput></screen>
<para>These tests will not find hard-coded paths inside the
port's files, nor will it verify that
<varname>LOCALBASE</varname> is being used to correctly refer
to files from other ports. The temporarily-installed port in
<filename>/var/tmp/`make -V PORTNAME`</filename> should be
tested for proper operation to make sure there
are no problems with paths.</para>
<para><varname>PREFIX</varname> should not be set explicitly
in a port's <filename>Makefile</filename>. Users installing
the port may have set <varname>PREFIX</varname> to a custom
location, and the port should respect that setting.</para>
<para>Refer to programs and files from other ports with the
variables mentioned above, not explicit pathnames. For
instance, if your port requires a macro
<literal>PAGER</literal> to have the full pathname of
<command>less</command>, do not use a literal path of
<filename>/usr/local/bin/less</filename>. Instead, use
<literal>&dollar;{LOCALBASE}</literal>:</para>
<programlisting>-DPAGER=\"&dollar;{LOCALBASE}/bin/less\"</programlisting>
<para>The path with <varname>LOCALBASE</varname> is more likely
to still work if the system administrator has moved the whole
<filename>/usr/local</filename> tree somewhere else.</para>
</sect1>
<sect1 xml:id="testing-tinderbox">
<title>Tinderbox</title>
<para>If you are an avid ports contributor, you might want to
take a look at <application>Tinderbox</application>. It is a
powerful system for building and testing ports.
You can
install <application>Tinderbox</application> using
<package role="port">ports-mgmt/tinderbox</package> port.
Be sure to read supplied documentation since the configuration
is not trivial.</para>
<para>Visit the
<link xlink:href="http://tinderbox.marcuscom.com/">Tinderbox
website</link> for more details.</para>
</sect1>
<sect1 xml:id="testing-poudriere">
<title>Poudriere</title>
<para>As a ports contributor, consider installing
<application>poudriere</application>. It is a powerful
system for building and testing ports.
<application>Poudriere</application> can be installed with
<package role="port">ports-mgmt/poudriere</package>.</para>
<para>Visit the <link
xlink:href="http://fossil.etoilebsd.net/poudriere">Poudriere
website</link> for more details.</para>
</sect1>
</chapter>

View file

@ -0,0 +1,15 @@
#
# Build the Porters Handbook with just the content from this chapter.
#
# $FreeBSD$
#
CHAPTERS= upgrading/chapter.xml
VPATH= ..
MASTERDOC= ${.CURDIR}/../${DOC}.${DOCBOOKSUFFIX}
DOC_PREFIX?= ${.CURDIR}/../../../..
.include "../Makefile"

View file

@ -0,0 +1,297 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!--
The FreeBSD Documentation Project
$FreeBSD$
-->
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="port-upgrading">
<title>Upgrading a Port</title>
<para>When you notice that a port is out of date compared to the
latest version from the original authors, you should first
ensure that you have the latest port. You can find them in the
<filename>ports/ports-current</filename> directory of the &os;
FTP mirror sites. However, if you are working with more than a
few ports, you will probably find it easier to use
<application>Subversion</application> or &man.portsnap.8;
to keep your whole ports collection up-to-date, as described in
the <link
xlink:href="&url.books.handbook;/ports-using.html">Handbook</link>.
This will have the added benefit of tracking all the port's
dependencies.</para>
<para>The next step is to see if there is an update already
pending. To do this, you have two options. There is a
searchable interface to the <link
xlink:href="http://www.FreeBSD.org/cgi/query-pr-summary.cgi?query">FreeBSD
Problem Report (PR) database</link> (also known as
<literal>GNATS</literal>). Select <literal>ports</literal> in
the dropdown, and enter the name of the port.</para>
<para>However, sometimes people forget to put the name of the port
into the Synopsis field in an unambiguous fashion. In that
case, you can try the
<link linkend="portsmon">&os; Ports Monitoring System</link>
(also known as <literal>portsmon</literal>). This system
attempts to classify port PRs by portname. To search for PRs
about a particular port, use the <link
xlink:href="http://portsmon.FreeBSD.org/portoverview.py">Overview
of One Port</link>.</para>
<para>If there is no pending PR, the next step is to send an email
to the port's maintainer, as shown by
<command>make maintainer</command>. That person may already be
working on an upgrade, or have a reason to not upgrade the port
right now (because of, for example, stability problems of the
new version); you would not want to duplicate their work. Note
that unmaintained ports are listed with a maintainer of
<literal>ports@FreeBSD.org</literal>, which is just the general
ports mailing list, so sending mail there probably will not help
in this case.</para>
<para>If the maintainer asks you to do the upgrade or there is
no maintainer, then you have a chance to help out &os; by
preparing the update yourself! Please do this by using the
&man.diff.1; command in the base system.</para>
<para>To create a suitable <command>diff</command> for a single
patch, copy the file that needs patching to
<replaceable>something.orig</replaceable>, save your changes to
<replaceable>something</replaceable> and then create your
patch:</para>
<informalexample>
<screen>&prompt.user; <userinput>diff -u something.orig something &gt; something.diff</userinput></screen>
</informalexample>
<para>Otherwise, you should either use the
<command>svn diff</command> method (<xref linkend="svn-diff"/>)
or copy the contents of the port to an entire different
directory and use the result of the recursive &man.diff.1;
output of the new and old ports directories (e.g., if your
modified port directory is called <filename>superedit</filename>
and the original is in our tree as
<filename>superedit.bak</filename>, then save the result of
<command>diff -ruN superedit.bak superedit</command>). Either
unified or context diff is fine, but port committers generally
prefer unified diffs. Note the use of the <literal>-N</literal>
option&mdash;this is the accepted way to force diff to properly
deal with the case of new files being added or old files being
deleted. Before sending us the diff, please examine the output
to make sure all the changes make sense. (In particular, make
sure you first clean out the work directories with
<command>make clean</command>).</para>
<para>To simplify common operations with patch files, you can use
<filename>/usr/ports/Tools/scripts/patchtool.py</filename>.
Before using it, please read
<filename>/usr/ports/Tools/scripts/README.patchtool</filename>.</para>
<para>If the port is unmaintained, and you are actively using
it yourself, please consider volunteering to become its
maintainer. &os; has over 4000 ports without maintainers, and
this is an area where more volunteers are always needed. (For a
detailed description of the responsibilities of maintainers,
refer to the section in the <link
xlink:href="&url.books.developers-handbook;/policies.html#POLICIES-MAINTAINER">Developer's
Handbook</link>.)</para>
<para>The best way to send us the diff is by including it via
&man.send-pr.1; (category <literal>ports</literal>). If you are
maintaining the port, be sure to put <literal>[maintainer
update]</literal> at the beginning of your synopsis line and set
the <quote>Class</quote> of your PR to
<literal>maintainer-update</literal>. Otherwise, the
<quote>Class</quote> of your PR should be
<literal>change-request</literal>. Please mention any added or
deleted files in the message, as they have to be explicitly
specified to &man.svn.1; when doing a commit. If the diff is
more than about 20KB, please compress and uuencode it;
otherwise, just include it in the PR as is.</para>
<para>Before using &man.send-pr.1;, review the <link
xlink:href="&url.articles.problem-reports;/pr-writing.html">
Writing the problem report</link> section in the Problem
Reports article. It contains far more information about how to
write useful problem reports.</para>
<important>
<para>If the upgrade is motivated by security concerns or a
serious fault in the currently committed port, please notify
the &a.portmgr; to request immediate rebuilding and
redistribution of the port's package. Unsuspecting users
of <command>pkg</command> will otherwise continue to install
the old version via <command>pkg install</command> for several
weeks.</para>
</important>
<note>
<para>Once again, please use &man.diff.1; and not &man.shar.1;
to send updates to existing ports! This helps ports
committers understand exactly what is being changed.</para>
</note>
<para>Now that you have done all that, read about
how to keep up-to-date in <xref linkend="keeping-up"/>.</para>
<sect1 xml:id="svn-diff">
<title>Using <application>Subversion</application> to Make
Patches</title>
<para>When possible, please submit a &man.svn.1; diff. They
are easier to handle than diffs between
<quote>new and old</quote> directories. It is easier
to see what has changed, and to update the diff if
something was modified in the Ports Collection since you
began work on it, or if the
committer asks for something to be fixed.</para>
<screen>&prompt.user; <userinput>cd ~/my_wrkdir</userinput> <co xml:id="my-wrkdir"/>
&prompt.user; <userinput>svn co https://svn0.us-west.FreeBSD.org/ports/head/dns/pdnsd</userinput> <co xml:id="svn-FreeBSD-org"/>
&prompt.user; <userinput>cd ~/my_wrkdir/pdnsd</userinput></screen>
<calloutlist>
<callout arearefs="my-wrkdir">
<para>This can be anywhere you want, of course; building
ports is not limited to within
<filename>/usr/ports/</filename>.</para>
</callout>
<callout arearefs="svn-FreeBSD-org">
<para><link
xlink:href="https://svn0.us-west.FreeBSD.org/">svn0.us-west.FreeBSD.org</link>
is a public <application>Subversion</application> server.
Select the closest mirror and verify the mirror server
certificate from the list of <link
xlink:href="&url.books.handbook;/svn-mirrors.html">Subversion
mirror sites</link>.</para>
</callout>
</calloutlist>
<para>While in the working directory, make any changes that you
would usually make to the port. If you add or remove a file,
use <command>svn</command> to track these changes:</para>
<screen>&prompt.user; <userinput>svn add new_file</userinput>
&prompt.user; <userinput>svn remove deleted_file</userinput></screen>
<para>Make sure that you check the port using the checklist in
<xref linkend="porting-testing"/> and
<xref linkend="porting-portlint"/>.</para>
<screen>&prompt.user; <userinput>svn status</userinput>
&prompt.user; <userinput>svn update</userinput> <co xml:id="svn-update"/></screen>
<calloutlist>
<callout arearefs="svn-update">
<para>This will try to merge the differences between your
patch and current repository version; watch the output
carefully. The letter in front of each file name
indicates what was done with it. See
<xref linkend="table-svn-up"/> for a complete list.</para>
</callout>
</calloutlist>
<table pgwide="1" frame="none" xml:id="table-svn-up">
<title><application>Subversion</application> Update File
Prefixes</title>
<tgroup cols="2">
<tbody>
<row>
<entry>U</entry>
<entry>The file was updated without problems.</entry>
</row>
<row>
<entry>G</entry>
<entry>The file was updated without problems (you will
only see this when working against a remote
repository).</entry>
</row>
<row>
<entry>M</entry>
<entry>The file had been modified, and was merged
without conflicts.</entry>
</row>
<row>
<entry>C</entry>
<entry>The file had been modified, and was merged with
conflicts.</entry>
</row>
</tbody>
</tgroup>
</table>
<para>If <literal>C</literal> is displayed as a result of
<command>svn update</command>, it means something changed in
the <application>Subversion</application> repository and
&man.svn.1; was not able to merge the local changes with those
from the repository. It is always a good idea to inspect the
changes anyway, since &man.svn.1; does not know anything about
how a port should be, so it might (and probably will) merge
things that do not make sense.</para>
<para>The last step is to make a unified &man.diff.1;
of the changes:</para>
<screen>&prompt.user; <userinput>svn diff &gt; ../`basename ${PWD}`.diff</userinput></screen>
<note>
<para>Any files that have been removed should be explicitly
mentioned in the PR, because file removal may not be obvious
to the committer.</para>
</note>
<para>Send your patch following the guidelines in
<xref linkend="port-upgrading"/>.</para>
</sect1>
<sect1 xml:id="moved-and-updating-files">
<title>The Files <filename>UPDATING</filename> and
<filename>MOVED</filename></title>
<para>If upgrading the port requires special steps like
changing configuration files or running a specific program,
you should document this in the file
<filename>/usr/ports/UPDATING</filename>. The format of
an entry in this file is as follows:</para>
<programlisting>YYYYMMDD:
AFFECTS: users of portcategory/portname
AUTHOR: Your name &lt;Your email address&gt;
Special instructions</programlisting>
<para>If you are including exact portmaster or portupgrading
instructions, please make sure to get the shell escaping
right.</para>
<para>The <filename>/usr/ports/MOVED</filename> file is used to
list moved or removed ports. Each line in the file is made
up of the name of the port, where the port was moved to, when,
and why. If the port was removed, the section detailing where
it was moved to can be left blank. Each section must be
separated by the <literal>|</literal> (pipe) character, like
so:</para>
<programlisting>old name|new name (blank for deleted)|date of move|reason</programlisting>
<para>The date should be entered in the form
<literal>YYYY-MM-DD</literal>. New entries should be added to
the end of the file to keep it in chronological order.</para>
<para>If a port was removed but has since been restored,
delete the line in this file that states that it was
removed.</para>
<para>The changes can be validated with
<command>Tools/scripts/MOVEDlint.awk</command>.</para>
</sect1>
</chapter>