# Portfile details

This Chapter describes in detail how each part of a portfile is works and is used.

## General syntax

A Portfile is a TCL script, so the syntax used must be valid TCL or the Portfile will not work. The basic syntax of the Portfile has been designed so most tasks are performed using key value(s) combinations. Many people don't realise it is TCL until they want to do something more advanced and realise all that power is there.

All key value pairs in a Portfile are single lines so line breaks must be escaped with a back slash ('\').

Variables syntax is ${foo} for the foo variant.

### Special characters

As the Portfile is a TCL script certain charachters are "special". These have a special meaning in TCL and if you dont want that special meaning, they must be escaped. In general a character is escaped using the back slash ('\'). The main characters you need to be careful with are

- $
- {
- }
- [
- ]

### Required keys

There is a small set of required key/value pairs without which a Portfile cannot be correct.

The required keys are

- PortSystem
- name
- version
- platforms
- maintainers
- categories
- description
- master_sites
- checksums
- homepage
- long_description

Each of these keys is described in the following pages of the guide.

## Useful preset variables

prefix

  Installation prefix, set in the systemwide configuration file ${prefix}/etc/macports/macports.conf. Can be overridden on a per port basis. For example XFree86 needs to install in the /usr tree, or aqua applications are installed in /Applications/MacPorts

binpath

  Default PATH to use in finding executables. Read only.

libpath

  Path to the MacPorts TCL libraries. Read only.

portpath

  Path to the directory containing the downloaded Portfiles. Read Only.

filesdir

  Path to port files relative to ${portpath}. Read Only.

workdir

  Path to work directory relative to ${portpath}. Read Only

workpath

  Full path to work directory. Read only.

worksrcpath

  Full path to extracted source code. Equivalent to ${workpath}/${worksrcdir}.

destroot

  Full path into which software will be destrooted. Equivalent to ${workpath}/destroot. Read only.

distpath

  Location to store downloaded distfiles. Read Only

os_arch

  Identifies hardware type (ie, "powerpc"). Read Only

os_version

  Version number of operating system (ie "6.0"). Read Only.

## Initialization phase

The first part of a Portfile deals with initialisation. Most of the keys (or options) in the initialisation phase are required for all Portfiles.

PortSystem

  Determines which version of the portsystem the Portfile is compatible with. MacPorts supports versioning of the PortSystem so if new, backwards incompatible changes are introduced older Portfiles can continue to use the older version of the system. The PortSystem line wraps the loading of TCL libraries appropriate for that version of MacPorts. If you don't load the libraries, nothing else in the Portfile will work. Thus, the PortSystem should be the top line in the Portfile.

  Currently MacPorts only has version 1.0 so you should put: `PortSystem 1.0` in your Portfile.

name

  The name of the Port. By default this is used to build the url from which the Port is fetched. The name should be lowercase.

  `name foo`

version

  The version of the Port. By default this is used to build the url from which the Port is fetched.

  `version 1.23.45`

platforms

  The platforms on which the port has been tested.

  `platforms darwin freebsd`

categories

  The type of Port. The first category should be the same as the directory in which the Portfile is stored and therefore should be chosen with care. A Port may have more that one category but is not required to.

  `categories foo bar`

description

  One sentence describing what the port is, use long_description for more detail. If you use long_description you must still use description.

  `description foo performs the transformation of bar into xml`

long_description

  Description of what the port is/does. Long lines can be broken with escaped newlines.

      long_description foo
      					performs the transformation of bar into xml \
      This allows users to rapidly transform documentation into multiple \
      formats.

maintainers

  List the email address or addresses of the Portfile maintainer(s)

  `maintainers joeblogs@somerandom.domain.com`

revision

  Local revision number of portfile. Increment for port revisions. The default for this is 0. It should be incremented for revisions that change the installed port.

  This key should only be used if the Portfile for the same port version has changed significantly. It should not be used if the port ${version} has changed. Most of the time, this key is not needed at all.

  `revision 1.1`

extract.suffix

  By default the value of ${extract.suffix} is .tar.gz. Specifying extract.suffix is optional, only use it if the suffix is not 'tar.gz.'.

  `extract.suffix .tgz`

distname

  By default distname is ${name}-${version}. Specifying distname is optional, only use it if the file that contains the port is not ${name}-${version} (without the extract.suffix).

  `distname ${name}_${version}`

distfiles

  Defaults to ${distname}.${extract.suffix}. Specifying distfiles is optional, only use it if the file that contains the port is not ${distname}.${extract.suffix} or more than one file needs to be retirieved.

  `distfiles stable.${extract.suffix} installer.sh`

  Some ports require multiple items to be fetched from different sites, this can be achieved using tags. The tags are then used to identify which of the master_sites to fetch the file from.see master_sites below for more information. As with long_description, long lines should be broken up with escaped newlines.

  `distfiles stable.${extract.suffix}:source installer.sh:install`

use_zip

  Specifying use_zip is optional, only use it if the file downloads are zipped rather than tarred and gzipped. use_zip sets ${extract.suffix} to .zip and extract.cmd to unzip, extract.pre_args to -q and extract.post_args to "-d $portpath/$workdir".

  `use_zip yes`

use_bzip2

  Specifying use_bzip2 is optional, only use it if the file downloads are tarred and bzipped rather than gzipped. use_bzip2 sets ${extract.suffix} to .tar.bz2 and extract.cmd to bzip2.

  `use_bzip2 yes`

## Fetch phase

master_sites

  A whitespace delimited list of urls from which the source of the port can be retrieved. The URL should not include the name of the file being retrieved.

  If you have multiple sites you should break up long lines with escapend newlines.

      master_sites   http://www.somesite.org/files/ \
                     http://www.somemirror.org/somesite_org/files/

  Always put the trailing forward slash at the end of a url, and remember to not include the filename itself.

  If you need to retrieve files from different sites you can label the urls with tags.

      master_sites   http://www.somesite.org/files/:source \
                     http://www.someothersite.org/somesite_extras/:extras

master_sites.mirror_subdir

  Subdirectory to add to mirror sites taken from a mirror sites list. Please see the section below on Mirror Site Lists for more details.

patch_sites

  List sites from which to download patchfiles from, syntax is the same as master_sites. See the Patch phase below for more information.

      patch_sites    ftp://ftp.patchcityrepo.com/pub/magic/patches

patch_sites.mirror_subdir

  Subdirectory to add to mirror sites taken from a mirror sites list. Please see the section below on Mirror Site Lists for more details.

### Mirror Site Lists

Mirror site lists are, as one might guess, predefined lists of mirror sites for use in `master_sites` or `patch_sites`. The basic usage of mirror site lists in a `Portfile` is:

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

Where '`sourceforge`' is the name of the mirror list which specifies SourceForge mirrors. `master_sites.mirror_subdir` is used to specify the subdirectory of all sites in in any mirror lists in which the file is found. The above example is equivalent to:

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

There are two potential problems when using mirror site lists as described above. First, if you are using multiple mirror site lists, such as `sourceforge` and `gnu`, the subdirectory might not always be the same. Second, if you have multiple distfiles and are using distfile tags to specify which site in `master_sites` to download which file from.

Fortunately MacPorts also provides a much more powerful and flexible syntax for mirror site lists.

    distfiles                   file_one.tar.gz:tagone file_two.tar.gz:tagtwo file_three.tar.gz
    master_sites                sourceforge::tagone gnu:directory:tagtwo \
                                http://distfiles.opendarwin.org/
    master_sites.mirror_subdir  ${name}

At first glance, this example is probably quite confusing. Basically, the advanced syntax is `list:subdirectory:tag`. The above example shows the many ways this can be used. The above example will:

- Look for `file_one.tar.gz` in:

      http://us.dl.sourceforge.net/${name}/
      http://eu.dl.sourceforge.net/${name}/
      ftp://us.dl.sourceforge.net/pub/sourceforge/${name}/
      ...

- Look for `file_two.tar.gz` in:

      ftp://ftp.gnu.org/gnu/directory/${name}/
      ftp://gatekeeper.dec.com/pub/GNU/directory/${name}/
      ftp://ftp.uu.net/archive/systems/gnu/directory/${name}/
      ...

- Look for `file_three.tar.gz` in:

      http://distfiles.opendarwin.org/

There are a few important points to remember when using this syntax. The subdirectory specified with the list (`gnu:directory`) is appended to all of the mirror sites in that list before the `master_sites.mirror_subdir`, and `master_sites.mirror_subdir` is always appended to the end of the mirror site. When using tags, you are not required to specify a subdirectory (`sourceforge::tagone`). `master_sites.mirror_subdir` is also not required when specifying a subdirectory with the list.

The original example could also be have been written using this syntax without the need of `master_sites.mirror_subdir` like this:

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

The mirror site lists functionality also works exactly the same for `patch_sites` and `patch_sites.mirror_subdir`.

Below is a list of the mirror site lists that can be used.

- `afterstep`

- `apache`

- `freebsd`

- `gnome`

- `gnu`

- `isc`

- `kde`

- `openbsd`

- `perl_cpan`

- `postgresql`

- `ruby`

- `sourceforge`

- `sunsite`

- `tcltk`

- `xcontrib`

- `xfree`

## Integrity checking phase

Each file downloaded is integrity checked using a checksum. This is used to help prevent trojaned sources being downloaded. If you do not include the checksums line, the file will be downloaded and the checksum reported as a conenience to the Portfile author.

checksums

  Currently only the md5 checksum is supported. Specify the filename, the checksum type and the checksum.

  `${distname}-${extract.sufx} md5 65b89365a65dcad71d4402b48 \ foo.tar.gz md5 65b89365a65dcad71d4402b44`

  If you only have one file being fetched the filename can be omitted.

  `md5 65b89365a65dcad71d4402b48`

## Extract phase

extract.only

  List of files to extract into ${workpath}, defaults to ${distfiles}. Useful when some files are not compressed. Only use extract.only if the default does not do the right thing.

  `extract.only foo.tar.gz bar.tar.gz`

extract.cmd

  Command to perform extraction. Defaults to gzip.

  `extract.cmd gunzip`

extract.pre_args

  Arguments added to extract command before a file name. Defaults to -dc.

  `extract.pre_args -cd`

extract.args

  Arguments to extract.cmd, Read Only. The value is ${distpath}/${distfile}

extract.post_args>

  Arguments added to extract command after a file name. Defaults to "| tar -xf".

  `extract.post_args | tar -xf`

## Patch phase

patchfiles

  List of patch files to apply to source. Patch files can be supplied in a port in a directory named files (based on the value of ${filepath}) within the port directory or fetched from ${patchsites}. Each patchfile supplied by the Portfile author should patch a single file. The standard convention is to name the patch file 'patch-<filename>.diff, with one diff file per file altered in the source. If the filename is ambiguous because there are multiple files with that name in the distribution, supply the path components to uniquely identify the file being patched. Diffs should be created from the top level of `worksrcdir`, the working source directory where the port was extracted, with a command similar to the following:

  `diff -u -b -w path/to/filename.orig path/to/filename > ../../files/patch-filename.diff`

  If, for example the original file is `path/to/filename.orig` and the file that was changed is `path/to/filename`.

  Patches downloaded from patchsites must have checksumes.

  To specify patchfiles in a portfile:

  `patchfiles patch-Makefile.in patch-source.c`

## Configuration phase

### Automake and autoconf

use_automake

  If set to yes, use automake

  `use_automake yes`

automake.env

  Environmental variables to pass to automake

  `CFLAGS="-I'${prefix}/include'"`

automake.args

  Arguments to pass to automake.

  `automake.args --foreign`

automake.dir

  Directory in which to run ${automake.cmd}. Defaults to ${worksrcpath}

  `automake.dir`

use_autoconf

  If set to yes, run autoconf.

  `use_autoconf yes`

autoconf.env

  Environmental variables to pass to autoconf

  `autoconf.env CFLAGS=-I'${prefix}/include/gtk12'`

autoconf.args

  Arguments to pass to autoconf.

  `autoconf.args -l src/aclocaldir`

autoconf.dir

  Directory in which to run ${autoconf.cmd}.

  `autoconf.dir src`

### configure

configure.env

  Set environment variables for configure.

  `configure.env CFLAGS="-I'${prefix}/include'"`

configure.pre_args

  Arguments added to configure command before ${configure.args}. Defaults to --prefix=${prefix}.

  `configure.pre_args --prefix="${prefix}/apache2"`

configure.args

  Arguments to pass to configure.

  `configure.args --etcdir="${prefix}/etc"`

## Build phase

build.cmd

  Make command to run relative to ${worksrcdir}. Defaults to make.

  `build.cmd pbxbuild`

build.type

  Defines which 'make' is required, either 'gnu' or 'bsd' Sets build.cmd to either 'gnumake' or 'bsdmake' accordingly

  `build.type gnu`

build.pre_args

  Arguments to pass to ${build.cmd} before ${build.args}. Read only. Set to ${build.target.current}

build.args

  Arguments to pass to ${build.cmd}

  `build.args -DNOWARN`

build.target

  Target to pass to make for building everything. Defaults to all.

  `build.target.all all-src`

## Destroot phase

destroot.cmd

  Install command to run relative to ${worksrcdir}. Defaults to ${build.cmd}.

  `destroot.cmd pbxbuild`

destroot.type

  Defines which 'make' is required, either 'gnu' or 'bsd' Sets install.cmd to either 'gnumake' or 'bsdmake' accordingly

  `destroot.type gnu`

destroot.pre_args

  Arguments to pass to ${destroot.cmd} before ${destroot.args}. Read only. Set to ${destroot.target}

destroot.args

  Arguments to pass to ${destroot.cmd}

  `destroot.args -DNOWARN`

destroot.target

  Install target to pass to ${destroot.cmd}.

  `destroot.target install-src`

destroot.destdir

  Arguments passed to ${destroot.cmd} in order to install correctly into the destroot.

  All ports must install via the 'destroot' so that the MacPorts infrastructure can register each file and directory a port installs. Most autoconf based build systems will behave correctly and respect DESTDIR, however some will not. Most of those that do not respect DESTDIR will install correctly if you use 'prefix', as in the example below. If your port doesn't respect either of these, you'll have to figure out what to do yourself. Some ports use another term, others require you to patch the Makefile (or other build related script).

  `destroot.destdir prefix=${destroot}${prefix}`

## Test phase

test.run

  Enable running test suites bundled with a port

  `test.run yes`

test.cmd

  Test command to run relative to ${worksrcdir}

  `test.cmd checks.sh`

test.target

  Test target to pass to ${test.cmd}

  `test.target checks`

test.dir

  Directory in which to run ${test.cmd}

  `test.dir ${worksrcpath}/checks`

## Install phase

These keys have all been deprecated. You should use the destroot keys in their place.

## StartupItems

To create StartupItems for your port, use these directives. It is considered good style to use the startupitem commands instead of creating a rc.s-tyle script.

startupitem.create

  This triggers the creation of a StartupItem, defaults to `no`.

startupitem.name

  sets the name for the StartupItem, defaults to `${portname}`

startupitem.init

  commands that will get executes on initialization of StartupItem, e. g. assign common variables. Default is empty.

  Common usage would be to define the location of the pidfile, like `PIDFILE=${prefix}/var/run/food.pid`.

startupitem.start

  command to call to start the daemon etc.; defaults to `${prefix}/etc/rc.d/${portname}.sh start`

  The common unix daemon would just have something like `${prefix}/sbin/food`

startupitem.stop

  command to call to stop the daemon etc.; defaults to `${prefix}/etc/rc.d/${portname}.sh stop`

  The common schema on this command is to call `kill` on the daemons pid. If you have a pid-file, you would use something like `kill \$(cat ${prefix}/var/run/food.pid)`.

startupitem.restart

  command to call to restart the daemon etc.; defaults to `StopService; StartService` (execute stop, start on self).

startupitem.requires

  The required services to run this daemon, defaults to `"Disk" "NFS"`.

## Dependencies

### Principles

### Dependency tests

depends_fetch

depends_extract

depends_lib

depends_build

depends_run

## TCL primitives

MacPorts provides several useful TCL primitives for use within Portfiles.

### adduser

Add a user to the system.

Usage: `adduser name`

Where `name` is the username to add. You can also override the defaults for any of the following user settings:

`adduser name password={\*} uid=[nextuid] gid=[nextgid] realname=${name} home=/dev/null shell=/dev/null`

### addgroup

Add a group to the system.

Usage: `addgroup name`

Where `name` is the name of the group to add. You can also override the defaults for any of the following group settings:

`addgroup name gid=[nextgid] users=""`

### file

Manipulate file names and attributes.

Usage: `file option name ?arg arg ...?`

Please see the Tcl documentation at The Tcl/Tk Developer's Site. for more on the options and arguments for file.

### reinplace

Provides "sed in place" functionality.

Usage: `reinplace sed_patern file`

Where `sed_patern` is a sed patern, and `file` is the name of the file to run sed on.

### system

Execute a system command.

Usage: `system "command"`

## Other

### Pre and post phase steps

Pre-*

Post-*

### Overriding a phase