Portfile DevelopmentThis chapter covers a brief introduction to Portfiles, how to create a
local Portfile repository for development, and creating Portfiles.Portfile IntroductionA MacPorts Portfile is a TCL script that usually
contains only the simple keyword/value combinations and Tcl extensions as
described in the Portfile Reference
chapter, though it may also contain arbitrary TCL code. Every port has a
corresponding Portfile, but Portfiles do not completely define a port's
installation behavior since MacPorts base has default port installation
characteristics coded within it. Therefore Portfiles need only specify
required options, though some ports may require non-default
options.A common way for Portfiles to augment or override MacPorts base
default installation phase characteristics is by using
Portfile phase declaration(s). If you use Portfile
phase declaration(s), you should know how to identify the "global" section
of a Portfile. Any statements not contained within a phase declaration, no
matter where they are located in a Portfile, are said to be in the global
section of the Portfile; therefore the global section need not be
contiguous. Likewise, to remove statements from the global section they
must be placed within a phase declaration.The main phases you need to be aware of when making a Portfile are
these:FetchExtractPatchConfigureBuildDestrootThe default installation phase behavior performed by the MacPorts
base works fine for applications that use the standard
configure, make, and make
install steps, which conform to phases configure, build, and
destroot respectively. For applications that do not conform to this
standard behavior, any installation phase may be augmented using pre- and/or post- phases,
or even overridden or
eliminated. See
Example Portfiles
below.For a detailed description of all port phases, see the Portfile Reference chapter.Local Portfile RepositoriesTo create and test Portfiles that are not yet committed to
subversion, you may create a local Portfile repository as shown. Replace
the hypothetical user julesverne with your username
in the example below.Open the sources.conf file in a text
editor.%%cd ${prefix}/etc/macports/%%pico sources.confInsert a URL pointing to your local repository location before
the rsync URL as shown.file:///Users/julesverne/ports
rsync://rsync.macports.org/release/ports
The file URL should always appear before the rsync URL so that
local Portfiles can be tested that are duplicated in the MacPorts
tree, because the port command will always
operate on the first Portfile it encounters.Place the Portfiles you create inside a directory whose name
matches the port, which should in turn be placed inside a directory
that reflect the port's primary category (the first category entry in
the Portfile).%%cd /Users/julesverne%%mkdir -p ports/games/bestevergame%%cd ports/games/bestevergame%%touch PortfileAfter a Portfile is created (see below), use the MacPorts
portindex command in the local repository's
directory to install it into the
Portindex.%% cd /Users/julesverne/ports
%% portindexCreating software index in /Users/julesverne/ports
Adding port games/bestevergame
Total number of ports parsed: 1
Ports successfully parsed: 1
Ports failed: 0Once the local port is added to the Portindex,
it becomes available for searching or installation as with any other
Portfile in the MacPorts tree as shown.%%port search besteverbestevergame games/bestevergame 1.1 The Best Ever GameCreating a PortfileHere we list the individual Portfile components for an application
that conforms to the the standard configure,
make, and make install steps of most
open source application installs.Subversion ID tag lineThe first line of a new Portfile must be set as shown. When a
port is committed to subversion, ID tags are expanded to include the
last person to commit and the commit time.# $Id$PortSystem lineThis statement is required for all ports.PortSystem 1.0Port namename rrdtoolPort versionversion 1.2.23Port categoriesA port may belong to more than one category, but the first
(primary) category should match the directory name in the ports tree
where the Portfile is to reside.categories netPort maintainersA port's maintainer is a person or persons who take
responsibility for keeping the port up-to-date, and the maintainer
keyword lists maintainer email addresses(s). To hide these addresses
from spambots, see the more full explanation of the maintainer keyword
in the Global
Keywords section of the Portfile
Reference chapter.maintainers julesverne@example.orgThe address nomaintainer@macports.org, or in
hidden form nomaintainer, designates a port that may
be modified by any committer.Port descriptiondescription Round Robin DatabasePort long_descriptionlong_description RRDtool is a system to store and display time-series dataA port's application homepagehomepage http://people.ee.ethz.ch/~oetiker/webtools/rrdtool/Platform statementplatforms darwinA port's download URLsmaster_sites http://oss.oetiker.ch/rrdtool/pub/ \
ftp://ftp.pucpr.br/rrdtool/Port checksumsThe checksums specified in a Portfile are checked with the
fetched tarball for security. For the best security, use md5, sha1,
and rmd160 checksum types.checksums md5 dafa161bc9c61e57636a6085c87c1fe8 \
sha1 5da610e1c8bc01b80abc21ab9e98e004363b429c \
rmd160 0c1147242adf476f5e93f4d59b553ee3ea378b23To find the correct checksums for a port's distribution file,
follow this example:%%md5 rrdtool-1.2.23.tar.gz%%openssl sha1 rrdtool-1.2.23.tar.gz%%openssl rmd160 rrdtool-1.2.23.tar.gzMD5 ( ... rrdtool-1.2.23.tar.gz) = dafa161bc9c61e57636a6085c87c1fe8
SHA1( ... rrdtool-1.2.23.tar.gz)= 5da610e1c8bc01b80abc21ab9e98e004363b429c
RIPEMD160( ... rrdtool-1.2.23.tar.gz)= 0c1147242adf476f5e93f4d59b553ee3ea378b23Port dependenciesA port's dependencies are ports that must be installed before
another port is installed.depends_lib port:perl5.8 \
port:tcl \
port:zlibPort configure arguments (optional)configure.args --prefix=${prefix} \
--enable-perl-site-install \
--mandir=${prefix}/share/manExample PortfilesIn this section we begin by taking a look at a complete simple
Portfile; then we see how to augment default phases by
defining pre- and post- phases, how to override default phases,
and finally how to eliminate port
phases.A Basic Portfile# Id$
PortSystem 1.0
name rrdtool
version 1.2.23
categories net
maintainers julesverne
description Round Robin Database
long_description RRDtool is a system to store and display time-series data
homepage http://people.ee.ethz.ch/~oetiker/webtools/rrdtool/
platforms darwin
master_sites http://oss.oetiker.ch/rrdtool/pub/ \
ftp://ftp.pucpr.br/rrdtool/
checksums md5 dafa161bc9c61e57636a6085c87c1fe8 \
sha1 5da610e1c8bc01b80abc21ab9e98e004363b429c \
rmd160 0c1147242adf476f5e93f4d59b553ee3ea378b23
depends_lib port:perl5.8 \
port:tcl \
port:zlib
configure.args --prefix=${prefix} \
--enable-perl-site-install \
--mandir=${prefix}/share/manAugment Phases Using pre- / post-To augment a port's installation phase, and not override it, you
may use pre- and post- installation phases as shown in this
example.post-destroot {
# Install example files not installed by the Makefile
file mkdir ${destroot}${prefix}/share/doc/${name}/examples
file copy ${worksrcpath}/examples/ \
${destroot}${prefix}/share/doc/${name}/examples
}Overriding PhasesTo override the automatic MacPorts installation phase processing,
define your own installation phases as shown in this example.destroot {
xinstall -m 755 -d ${destroot}${prefix}/bin
xinstall -m 755 ${worksrcpath}/cdpr ${destroot}${prefix}/bin
}Eliminating PhasesTo eliminate a default phase, simply define a phase with no
contents as shown.build {}Because many software packages do not use
, a keyword is provided to eliminate the
phase. See the chapter Portfile Reference for full
information.Creating a StartupItemStartupitems may be placed in the global section of a
Portfile.startupitem.create yes
startupitem.name nmicmpd
startupitem.executable "${prefix}/bin/nmicmpd"Startupitems keywords may also be used within a variant definition
to make their installation conditional.variant server {
startupitem.create yes
startupitem.start "${prefix}/share/${name}/vm-pop3d.init start"
startupitem.stop "${prefix}/share/${name}/vm-pop3d.init stop"
}Port VariantsVariants are a way for port authors to provide options that may be
invoked at install time. They are declared in the global section of a
Portfile using the "variant" keyword and may provide a description.Variants to Modify OptionsThe most common use for a variant is to add or remove
dependencies, configure arguments, and build arguments from the global
Portfile section. Here is an example of a port providing four variants
that add additional configure arguments to a port.variant pop { configure.args-append --enable-pop }
variant imap { configure.args-append --enable-imap }
variant ssl { configure.args-append --with-ssl }
variant debug { configure.args-append --enable-debug }In the example variant declaration, the configure argument
--without-x is removed and a numner of others are
appended.variant x11 description {Builds port as an X11 program with Lucid widgets} {
configure.args-delete --without-x
configure.args-append --with-x-toolkit=lucid \
--without-carbon \
--with-xpm \
--with-jpeg \
--with-tiff \
--with-gif \
--with-png
depends_lib-append lib:libX11:XFree86 \
lib:libXpm:XFree86 \
port:jpeg \
port:tiff \
port:libungif \
port:libpng
}Variant Actions in a PhaseIf a variant requires options in addition to those provided by
keywords using -append and/or -delete, in other words, any actions that
would normally take place within a port installation phase, do not try
to do this within the variant declaration. Rather, modify the behavior
of any affected phases when the variant is invoked using the
variant_isset keyword.post-destroot {
xinstall -m 755 -d ${destroot}${prefix}/etc/
xinstall ${worksrcpath}/examples/foo.conf \
${destroot}${prefix}/etc/
if {[variant_isset] carbon]} {
delete ${destroot}${prefix}/bin/emacs
delete ${destroot}${prefix}/bin/emacs-${version}
}
}Default VariantsVariants are used to specify actions that lie outside the core
functions of an application or port, but there may be some cases where
you wish to specify these non-core functions by default. For this
purpose you may use the keyword default_variants.default_variants +foo +barThe default_variant keyword may only be used in the global
Portfile section.Patch FilesPatch files are files created with the Unix command
diff that are applied using the command
patch to modify text files to fix bugs or extend
functionality.Creating Portfile PatchesIf you wish to contribute modifications or fixes to a Portfile,
you should do so in the form of a patch.Make a copy of the Portfile you wish to modify; both files
must be in the same directory, though it may be any
directory.%%cp Portfile Portfile.origEdit the file to make it as you want it to be after it is
fetched.Now use the Unix command diff -u to create
a "unified" diff patch file. Put the name of the port in the
patchfile, for example, Portfile-rrdtool.diff.%%diff -u Portfile.orig Portfile > Portfile-rrdtool.diffA patch file that is a "unified" diff file is the easiest to
interpret by humans and this type should always be used for ports.
The Portfile patch below will change the version and checksums when
applied.--- Portfile.orig 2007-07-25 18:52:12.000000000 -0700
+++ Portfile 2007-07-25 18:53:35.000000000 -0700
@@ -2,7 +2,7 @@
PortSystem 1.0
name nefu
-version 1.4.0
+version 1.3.0
categories net
maintainers nomaintainer@macports.org
description A network monitoring daemon.
@@ -13,9 +13,9 @@
homepage http://rsug.itd.umich.edu/software/${name}
master_sites ${homepage}/files/
-checksums md5 f0953b21cdb5eb327e40d4b215110b71
+checksums md5 01532e67a596bfff6a54aa36face26ae
extract.suffix .tgz
platforms darwin
Now you may attach the patch file to a MacPorts Trac ticket for
the port author to evaluate.Creating Source Code PatchesNecessary or useful patches to application source code should be
sent to the application developer (not the port author) so the
modifications may be included in the next version, and the port patch
eventually removed.Locate the file you wish to patch in its original location
within the unpacked source directory and make a duplicate of
it.%%cd foo-1.34/src%%cp Makefile.in Makefile.in.origEdit the file to make it as you want it to be after it is
fetched.Now use the Unix command diff -u to create
a "unified" diff patch file.%%cd foo-1.34%%diff -u Makefile.in.orig Makefile.in > patch-Makefile.inYou must execute the diff command in the
top-level of the unpacked source code. Otherwise the
patch command will look for the file to be
patched in the wrong place and fail.A patch file that is a "unified" diff file is the easiest to
interpret by humans and this type should always be used for ports.
See the example below where a patch adds DESTDIR
support to a Makefile.in file.--- Makefile.in.orig 2007-06-01 16:30:47.000000000 -0700
+++ Makefile.in 2007-06-20 10:10:59.000000000 -0700
@@ -131,23 +131,23 @@
$(INSTALL_DATA)/gdata $(INSTALL_DATA)/perl
install-lib:
- -mkdir -p $(INSTALL_LIB)
+ -mkdir -p $(DESTDIR)$(INSTALL_LIB)
$(PERL) tools/install_lib -s src -l $(INSTALL_LIB) $(LIBS)
- cp $(TEXT) $(INSTALL_LIB)/
+ cp $(TEXT) $(DESTDIR)$(INSTALL_LIB)/Now you may place the patch
patch-Makefile.in in the path ${portpath}/files
of a local repository (or commit it to subversion) and use it in a
port using the patchfiles keyword.patchfiles patch-Makefile.inYou should make a patch file for each file to be patched,
though if you obtain a patch from another source that patches
multiple files it is permissible to use it that way. Patch
filenames should generally be of the form
"patch-<directory>-<filename>", as shown in this
example: patch-src-Makefile.in.Manually Applying PatchesThough MacPorts applies patch files automatically, you may want to
know how to apply patch files manually if you want to test patch files
you have created or you wish to apply uncommitted Portfile
patches.Change to the directory containing the file to be patched. In
this example, we'll apply a Portfile patch to the postfix
port.%%cd ${prefix}/var/macports/sources/rsync.macports.org/release/ports/mail/postfixNow apply the patch that is on the current user's desktop. The
patchfile knows the filename of the file to be patched.%%patch -p0 < ~/Desktop/Portfile-postfix.diffpatching file PortfilePortfile Best PracticesThis section contains practical guidelines for creating Portfiles
that install smoothly and provide consistency between ports. The following
sections are on the TODO list.Don't Overwrite Config FilesTODO:Install Docs and ExamplesTODO:Provide User MessagesTODO:Use VariablesTODO: Set variables so changing paths may be done in one place;
use them anytime it makes updates simpler: distname
${name}-src-${version}