portfile
introduction
maintainer

# Quick Start

## Getting Started With MacPorts

This document will provide a short guide to the basics of a MacPorts `Portfile`. A `Portfile` is actually a Tcl script run by the `port` system. Despite this, the `Portfile` syntax is very straightforward.

In order to work with MacPorts, you will need to download and install it on your system. The Obtaining and Installing MacPorts sections of this guide describes the process in detail.

In order for these commands to work, you're going to need permission to write to certain areas of your MacPorts tree. You need to be able to write to `${prefix}/var/macports/build` and `${prefix}/var/macports/distfiles`. You could run all of these commands as a superuser (prefix the commands with `sudo`), but you might accidentally install a broken package that way, or otherwise damage up your MacPorts installation. Another option is to change the owner of just those directories to your user, so you can write to those directories but not your whole `${prefix}` tree. To do this, run `chown username ${prefix}/var/macports/build` and `chown -R username ${prefix}/var/macports/distfiles`.

Since you're interested in writing a `Portfile`, you should invoke the `port` with the `-d` (debugging option) switch. This will display useful messages that are usually suppressed while running MacPorts.

## Basic Topics and Examples

### Fetching the Sources

The first step is to choose a piece of software to port. For this example, we'll be porting ircII, a popular Internet relay chat client.

We can start with a simple `Portfile` describing the basic attributes of ircII, such as its name, version, and the site where we can download the sources.

Create a working directory named `ircII` and inside it create a file named `Portfile` with the following contents:

#### ircII `Portfile`

    # $Id: $
    PortSystem        1.0
    name              ircii
    version           20020912
    categories        irc
    maintainers       kevin@opendarwin.org
    description       an IRC and ICB client
    long_description  The ircII program is a full screen, termcap based \
                      interface to Internet Relay Chat. It gives full access \
                      to all of the normal IRC functions, plus a variety of \
                      additional options.
    homepage          http://www.eterna.com.au/ircii/
    master_sites      ftp://ircftp.au.eterna.com.au/pub/ircII/

A `Portfile` consists of key/value pairs. This example uses the following keys:

`# $Id: $`

  Every `Portfile` starts with `#$Id: $`. This is a RCS `Id` tag (commented out with the '#' character so that MacPorts is not confused by the tag).

`PortSystem`

  Following the RCS `Id` tag comes the `PortSystem` version declaration. Currently the only valid version declaration is `PortSystem 1.0`.

`name` and `version`

  The `name` and `version` keys describe the name and version of the software.

`categories`

  The `categories` key is a list of the logical categories to which the software belongs; this is used for organizational purposes. The first entry in `categories` should match the directory in which the port's directory resides in the ports tree.

`maintainers`

  The `maintainers` key should contain the email address of the person or persons maintaining the port.

`description` and `long_description`

  `description` provides a short (one line) description of the port, while `long_description` holds a more detailed description of the software.

`homepage`

  To refer to the main web site of the software, the `homepage` key is used.

`master_sites`

  The `master_sites` key should contain a list of sites where the distribution sources may be downloaded by the port system.

MacPorts uses the terms 'keys' and 'options' interchangeably since most keys are used as options of a particular task in the porting process.

At this point, the `Portfile` is complete enough to download ircII. By default, MacPorts will append the `version` to `name` and assume sources are in a gzipped tar archive with the `.tar.gz` suffix.

From your working directory, execute the following command:

`port -d -v checksum`

The `port` command (when used without an explicit port name operates on the `Portfile` in the current working directory. You should see the following output:

``

    DEBUG: Executing com.apple.main (ircii)
    DEBUG: Executing com.apple.fetch (ircii)
    --->  ircii-20020912.tar.gz doesn't seem to exist in /opt/local/var/db/mports/distfiles
    --->  Attempting to fetch ircii-20020912.tar.gz from ftp://ircftp.au.eterna.com.au/pub/ircII/
    DEBUG: Executing com.apple.checksum (ircii)
    Error: No checksums statement in Portfile.  File checksums are:
    ircii-20020912.tar.gz md5 2ae68c015698f58763a113e9bc6852cc
    Error: Target error: com.apple.checksum returned: No checksums statement in Portfile.

### Verifying the Downloaded File

Notice that MacPorts first checks for a local copy of `ircii-20020912.tar.gz` and doesn't find it, so it then downloads from the remove site. The port doesn't finish because of an error: `No checksums statement in Portfile.` Portfiles must contain an md5 checksum of all distribution files--this allows MacPorts to verify the accuracy and authenticity of the sources. For convenience, an md5 checksum of the downloaded files is printed when the `checksums` argument is not specified. Go back and add the following to your `Portfile`:

    checksums    md5 2ae68c015698f58763a113e9bc6852cc

If you have more than one file being fetched you should specify the checksum for each in the form:

    checksums    foo md5 ... \
                 bar md5 ...

### Extracting the Sources into a Working Directory

Now that we have a checksum and can verify our sources, we can proceed to extracting the sources into our working directory. Execute the following:

`port -d -v extract`

Which should display the following output:

``

    DEBUG: Skipping completed com.apple.main (ircii)
    DEBUG: Skipping completed com.apple.fetch (ircii)
    DEBUG: Executing com.apple.checksum (ircii)
    --->  Checksum OK for ircii-20020912.tar.gz
    DEBUG: Executing com.apple.extract (ircii)
    --->  Extracting for ircii-20020912
    --->  Extracting ircii-20020912.tar.gz ... DEBUG: Assembled command: 'cd
    /Users/kevin/opendarwin/proj/macports/mports/irc/ircii/work && gzip -dc /opt/local/var/db/mports/distfiles/ircii-20020912.tar.gz | tar -xf -'
    Done

### Running a `configure` Script

Now that the sources have been extracted into a `work` directory in the Portfile directory, we can configure the sources to compile with the desired options. By default MacPorts assumes the software you're porting uses an autoconf `configure` script and will pass the `--prefix=${prefix}` argument to `configure`, specifying that the software should be installed in the directory tree used by MacPorts.

ircII's standard set of options is fine for a base install on Darwin, so we won't add anything to the `configure` phase and instead just move on to the build phase. Please look at the later chapters in this Guide for more information about the Configuration phase.

### Building the Sources

To build, type the following:

`port -d build`

By default, the build phase executes the system's `make`(1) utility. (This can be changed with the `build.type` option which accepts an argument of `bsd`, `gnu`, or `pbx`. Alternatively, the `build.cmd` option may be used to specify an arbitrary build command.) The above step has started compiling the sources, when it finishes we'll be ready to install the software.

### Installing the Finished Product on the System

The former method of including a `contents` list has been made obsolete by the `destroot` mechanism. With `destroot` the software is installed into a directory tree below in the `work` directory. While some software (like ircII) does not require any special tweaks to be installed into the destroot, others (like ncftp) need the `install.destroot` option in order to correctly install into the `destroot`.

    destroot.destdir     mandir=${destroot}${prefix}/man prefix=${destroot}${prefix}

Take a look at some of our ports to see more examples on how to use the `destroot.destdir` option.

Now we have a complete `Portfile`. Run the installation step to add your port to your own registry.

`sudo port -d -v install`

Which should finish with the output:

``

    --->  Adding ircii to registry, this may take a moment...

## Advanced Topics

### Overriding Targets

It's possible to override the functionality of any build target with Tcl code. A common example is the following which might be useful for a script without a configure script. `configure` script:

    configure    {}

In the `Portfile`, this will replace the functionality of the `configure` target, thus skipping that step. It is also possible to execute Tcl code immediately before or after any of the standard targets. This can be accomplished using pre--<target> or post-<target> in the following manner:

    post-configure {
        reinplace "s|change.this.to.a.server|irc.openprojects.net|g" \
                  "${worksrcpath}/config.h"
    }

This example replaces the occurrence of `change.this.to.a.server` with `irc.freenode.net` in the `config.h` file that was generated during the preceding `configure` phase. Note this is a somewhat contrived example, since the same could have been accomplished by specifying `--with-default-server=irc.freenode.net` in `configure.args`, but the approach is generally useful when such configure arguments aren't present.

### Portfile Variants

Since Darwin 6.0 has ipv6, it would be possible to configure with the `--with-ipv6` option. This can be done by adding the following option to the `Portfile`:

    configure.args      --disable-ipv6

    variant ipv6 {
        configure.args-append  --enable-ipv6
    }

Now the default build will not include ipv6 support, but if the ipv6 variant is requested, ircII will have it. Options by themselves should be thought of as an assignment operator. Since variants may be used in combination with one another, it's good practice to only append to options instead of overwriting them. All options may be suffixed with `-append` or `-delete` to append or delete one term from the list. You can specify building with the ipv6 variant in the following way:

`port build +ipv6`

### Mirror Site Lists

It is possible to use predefined lists of mirror sites in your `Portfile`, such as SourceForge or GNU mirrors. The straight-forward usage is:

    master_sites                sourceforge http://distfiles.opendarwin.org/
    master_sites.mirror_subdir  ${name}

In this example, `sourceforge` is the name of the mirror site list (See Chapter 3, 'Fetch Phase' for a list of all available mirror site lists), `http://distfiles.opendarwin.org/` is a normal `master_sites` URL, and `${name}` (the value of the `name` keyword in the `Portfile`) is the subdirectory to append to any mirror site lists specified.

This will search all of the mirror sites for SourceForge and then http://distfiles.opendarwin.org, appending `${name}` to the end of each SoureForge mirror site in the list. This example will try to fetch from:

    http://us.dl.sourceforge.net/${name}/
    ftp://us.dl.sourceforge.net/pub/sourceforge/${name}/
    ...
    http://distfiles.opendarwin.org/

Note that the value of `master_sites.mirror_subdir` is not appended to `http://distfiles.opendarwin.org/`, this URL is treated normally. In this example `master_sites.mirror_subdir` is a required key.

You can also use the mirror site lists in `patch_sites` and use `patch_sites.mirror_subdir` to specify the subdirectory. For more information and advanced usage of mirror site lists (i.e. distfile tags, multiple lists with different subdirectories), please see Chapter 3, 'Fetch Phase'.

### Additional Options

There are additional options that are commonly used in `Portfile`s. The following are commonly used options that may be useful:

`distfiles`

  `distfile` is the name and version combined with the `extract.suffix` (by default `${name}-${version}.tar.gz`) by default, and is used by MacPorts to fetch the distribution file. If the name of the file on the server is not the same as `${name}-${version}.tar.gz` you can use this option to override the default `distfile` name.

`depends_lib`

  `depends_lib` is used if the port needs other libraries or binaries to be installed in order to `configure` and run. It takes three terms, separated by colons. The first term is `bin` or `lib`. This defines the search path the port system will look for the dependency in. If `bin` is specified, `$PATH` is searched for the dependency. If `lib` is specified, the library path is searched instead. The second term is a regular expression that is used to search the search path for the dependency. Usually the name of the library is good enough. The port system will append `.dylib` to the reg-ex so only dynamic libraries will be matched. The third term is the name of the port that can provide the dependency if it is not satisfied by something already installed on the system.

`patchfiles`

  `patchfiles` is a list of patches to be applied to the port (needed for the software to compile/run or install correctly). Patches are usually provided in a `files/` directory in the same directory as the `Portfile`.

Please take a look at the other chapters in this Guide for more detailed information about these and other options.

## Common Mistakes

### Don't quote or wrap items in '{}'.

Frequently people submit ports with the description or configure arguments quoted, or wrapped in curly brackets. In general this is not correct.

## Testing `Portfiles`: Tips and Hints

### Debugging and Verbose Messages

You should use the `-d` and `-v` switches to `port` to enable debugging and verbose messages, respectively.

### Use a Local Portfile Repository

Enable a second local source (`Portfile`) repository for your uncommitted ports. Edit your `sources.conf` file and add:`file:///User/foo/mports-dev` (or wherever your local mport tree is). Place all your `Portfiles` inside their corresponding portdirs (reflecting the name of the port), which should in turn be placed inside directories that reflect their primary category (the first one listed for their

    categories

entry).

Create an index file from the local source repository root. This will also perform a simple syntax check on the Portfiles contained therein.

`portindex`

### Testing Destroot

First run port install without root privileges, this is a good way to check that the port installs into the destroot and not directly into the main prefix directory, or elsewhere in the system. This should succeed up to the point macports attempts to copy the port from the destroot into the macports prefix. Once you are confident the port is correctly destrooted install the port into the macports prefix using root privileges.

`sudo port install foo`

Ensure the Port installs into the destroot and does not install anything onto the system directly, most software that uses autoconf should behave correctly automatically as macports sets DESTDIR by default. If files are directly installed to the system they will not be registered and packaging will fail.

### Test Uninstall

Uninstall the port

`sudo port uninstall foo`

### Try the Port on a Clean Machine

Make sure the port builds, installs and uninstalls on a "clean machine". A clean machine should have a clean install of the OS, to avoid missing dependencies. Using a chrooted version of the OS to install and test ports makes this much easier, see the chroot HOWTO for more details on how to set up the chroot.

### Clean the Working Directory after an Error

Clean the working source directory for a port. This will allow a clean reinstall if an error was encountered earlier in the build process.

`port clean foo`

## Where can I ask for advice?

Either on the macports-dev@lists.macosforge.org mailing list, or on the #macports channel on irc.freenode.net. Don't be afraid to ask questions! You should also look at the later sections of the guideand the `portfile`(7) and `portstyle`(7) manpages for more information.

## How do I submit my Ports

See the submission chapter for all the information on how to submit a port properly.

## More Example `Portfile`s

### Expat `Portfile`

    # &dollar;Id: Portfile,v 1.14 2003/07/30 14:35:39 fkr Exp &dollar;

    PortSystem      1.0

    name            libxslt
    version         1.0.21
    homepage        http://www.xmlsoft.org/
    description     gnome xslt library and xsltproc
    categories      textproc
    platforms       darwin
    maintainers     mike+libxslt@gene-hacker.net
    master_sites    ftp://xmlsoft.org/ \
                    ftp://ftp.gnome.org/pub/GNOME/sources/libxslt/1.0/

    checksums       md5 9cc0491e2584788748eb7069ea1d5277
    depends_lib     lib:libxml2:libxml2
    patchfiles      patch-aclocal.m4 patch-configure patch-ltmain.sh

    long_description Gnome library for applying XSL stylesheet transformations to \
     xml files, comes with several useful binaries.

### Neon `Portfile`

    # &dollar;Id: Portfile,v 1.14 2003/07/30 14:35:39 fkr Exp &dollar;

    PortSystem 1.0
    name            neon
    version         0.23.4

    categories      www
    maintainers     rooneg@electricjellyfish.net
    description     An HTTP and WebDAV client library with a C interface

    master_sites    http://www.webdav.org/neon/
    checksums       md5 56b380a7352c68d425b1d3d3d610f994

    depends_lib     lib:libexpat.0.4:expat
    configure.env   LDFLAGS='-L"${prefix}/lib"' CPPFLAGS='-I"${prefix}/include"'

    configure.args  --with-ssl \
                    --with-force-ssl \
                    --enable-xml \
                    --enable-shared \
                    --with-expat

For more examples, you can browse the directory tree of MacPorts' `mports` directory and have a look at the `Portfile`s of your favorite ports.

For more information about some options used in these `Portfile` examples that were not covered in this chapter, please take a look at the following chapters of this Guide.