---
title: Chapter 9. pkg-*
prev: books/porters-handbook/plist
next: books/porters-handbook/testing
description: Tricks about the pkg-* files
tags: ["pkg", "pkg-message", "UCL", "pkg-install", "pkg-deinstall"]
showBookMenu: true
weight: 9
params:
  path: "/books/porters-handbook/pkg-files/"
---

[[pkg-files]]
= pkg-*
:doctype: book
:toc: macro
:toclevels: 1
:icons: font
:sectnums:
:sectnumlevels: 6
:sectnumoffset: 9
:partnums:
:source-highlighter: rouge
:experimental:
:images-path: books/porters-handbook/

ifdef::env-beastie[]
ifdef::backend-html5[]
:imagesdir: ../../../../images/{images-path}
endif::[]
ifndef::book[]
include::shared/authors.adoc[]
include::shared/mirrors.adoc[]
include::shared/releases.adoc[]
include::shared/attributes/attributes-{{% lang %}}.adoc[]
include::shared/{{% lang %}}/teams.adoc[]
include::shared/{{% lang %}}/mailing-lists.adoc[]
include::shared/{{% lang %}}/urls.adoc[]
toc::[]
endif::[]
ifdef::backend-pdf,backend-epub3[]
include::../../../../../shared/asciidoctor.adoc[]
endif::[]
endif::[]

ifndef::env-beastie[]
toc::[]
include::../../../../../shared/asciidoctor.adoc[]
endif::[]

There are some tricks we have not mentioned yet about the [.filename]#pkg-*# files that come in handy sometimes.

[[porting-message]]
== pkg-message

To display a message when the package is installed, place the message in [.filename]#pkg-message#.
This capability is often useful to display additional installation steps to be taken after a `pkg install` or `pkg upgrade`.

[IMPORTANT]
====
* [.filename]#pkg-message# must contain only information that is _vital_ to setup and operation on FreeBSD, and that is unique to the port in question.
* Setup information should only be shown on initial install. Upgrade instructions should be shown only when upgrading from the relevant version.
* Do not surround the messages with either whitespace or lines of symbols (like `----------`, `**********`, or `==========`). Leave the formatting to man:pkg[8].
* Committers have blanket approval to constrain existing messages to install or upgrade ranges using the UCL format specifications.

====

pkg-message supports two formats:

raw::
A regular plain text file.
Its message is only displayed on install.

UCL::
If the file starts with "`[`" then it is considered to be a UCL file.
The UCL format is described on https://github.com/vstakhov/libucl[libucl's GitHub page].

[NOTE]
====
Do not add an entry for [.filename]#pkg-message# in [.filename]#pkg-plist#.
====

[[porting-message-ucl]]
=== UCL in pkg-message

The format is the following.
It should be an array of objects.
The objects themselves can have these keywords:

`message`::
The actual message to be displayed.
This keyword is mandatory.

`type`::
When the message should be displayed.

`maximum_version`::
Only if `type` is `upgrade`.
Display if upgrading from a version strictly lower than the version specified.

`minimum_version`::
Only if `type` is `upgrade`.
Display if upgrading from a version stictly greater than the version specified.

The `maximum_version` and `minimum_version` keywords can be combined.

The `type` keyword can have three values:

`install`::
The message should only be displayed when the package is installed.

`remove`::
The message should only be displayed when the package is removed.

`upgrade`::
the message should only be displayed during an upgrade of the package..

[IMPORTANT]
====
To preserve the compatibility with non UCL [.filename]#pkg-message# files,
the first line of a UCL [.filename]#pkg-message# _MUST be_ a single "`[`", and the last line _MUST be_ a single "`]`".
====

[[porting-message-ucl-short-ex]]
.UCL Short Strings
[example]
====

The message is delimited by double quotes `"`, this is used for simple single line strings:

[.programlisting]
....
[
{ type: install
  message: "Simple message"
}
]
....

====

[[porting-message-ucl-multiline-ex]]
.UCL Multiline Strings
[example]
====

Multiline strings use the standard here document notation.
The multiline delimiter _must_ start just after `<<` symbols without any whitespace and it _must_ consist of capital letters only.
To finish a multiline string, add the delimiter string on a line of its own without any whitespace.
The message from <<porting-message-ucl-short-ex>> can be written as:

[.programlisting]
....
[
{ type: install
  message: <<EOM
Simple message
EOM
}
]
....

====

[[porting-message-ucl-ex2]]
.Display a Message on Install/Deinstall
[example]
====

When a message only needs to be displayed on installation or uninstallation, set the type:

[.programlisting]
....
[
{
  type: remove
  message: "package being removed."
}
{ type: install, message: "package being installed."}
]
....

====

[[porting-message-ucl-ex3]]
.Display a Message on Upgrade
[example]
====

When a port is upgraded, the message displayed can be even more tailored to the port's needs.

[.programlisting]
....
[
{
  type: upgrade
  message: "Package is being upgraded."
}
{
  type: upgrade
  maximum_version: "1.0"
  message: "Upgrading from before 1.0 need to do this."
}
{
  type: upgrade
  minimum_version: "1.0"
  message: "Upgrading from after 1.0 should do that."
}
{
  type: upgrade
  maximum_version: "3.0"
  minimum_version: "1.0"
  message: "Upgrading from > 1.0 and < 3.0 remove that file."
}
]
....

[IMPORTANT]
****
When displaying a message on upgrade, it is important to limit when it is being shown to the user.
Most of the time it is by using `maximum_version` to limit its usage to upgrades from before a certain version when something specific needs to be done.
****

====

[[pkg-install]]
== pkg-install

If the port needs to execute commands when the binary package is installed with `pkg add` or `pkg install`, use [.filename]#pkg-install#.
This script will automatically be added to the package.
It will be run twice by `pkg`, the first time as `${SH} pkg-install ${PKGNAME} PRE-INSTALL` before the package is installed, and the second time as `${SH} pkg-install ${PKGNAME} POST-INSTALL` after it has been installed.
`$2` can be tested to determine which mode the script is being run in.
The `PKG_PREFIX` environmental variable will be set to the package installation directory.

[IMPORTANT]
====
This script is here to help you set up the package so that it is as ready to use as possible.
It _must not_ be abused to start services, stop services, or run any other commands that will modify the currently running system.
====

[[pkg-deinstall]]
== pkg-deinstall

This script executes when a package is removed.

This script will be run twice by `pkg delete`.
The first time as `${SH} pkg-deinstall ${PKGNAME} DEINSTALL` before the port is de-installed and the second time as `${SH} pkg-deinstall ${PKGNAME} POST-DEINSTALL` after the port has been de-installed.
`$2` can be tested to determine which mode the script is being run in.
The `PKG_PREFIX` environmental variable will be set to the package installation directory

[IMPORTANT]
====
This script is here to help you set up the package so that it is as ready to use as possible.
It _must not_ be abused to start services, stop services, or run any other commands that will modify the currently running system.
====

[[pkg-names]]
== Changing the Names of pkg-*

All the names of [.filename]#pkg-\*# are defined using variables that can be changed in the [.filename]#Makefile# if needed.
This is especially useful when sharing the same [.filename]#pkg-*# files among several ports or when it is necessary to write to one of these files.
See crossref:porting-dads[porting-wrkdir,writing to places other than `WRKDIR`] for why it is a bad idea to write directly into the directory containing the [.filename]#pkg-*# files.

Here is a list of variable names and their default values.
(`PKGDIR` defaults to `${MASTERDIR}`.)

[.informaltable]
[cols="1,1", frame="none", options="header"]
|===
| Variable
| Default value

|`DESCR`
|`${PKGDIR}/pkg-descr`

|`PLIST`
|`${PKGDIR}/pkg-plist`

|`PKGINSTALL`
|`${PKGDIR}/pkg-install`

|`PKGDEINSTALL`
|`${PKGDIR}/pkg-deinstall`

|`PKGMESSAGE`
|`${PKGDIR}/pkg-message`
|===

[[using-sub-files]]
== Making Use of `SUB_FILES` and `SUB_LIST`

`SUB_FILES` and `SUB_LIST` are useful for dynamic values in port files, such as the installation `PREFIX` in [.filename]#pkg-message#.

`SUB_FILES` specifies a list of files to be automatically modified.
Each [.filename]#file# in the `SUB_FILES` list must have a corresponding [.filename]#file.in# present in `FILESDIR`.
A modified version will be created as [.filename]#${WRKDIR}/file#.
Files defined as a value of `USE_RC_SUBR` are automatically added to `SUB_FILES`.
For the files [.filename]#pkg-message#, [.filename]#pkg-install#, and [.filename]#pkg-deinstall#, the corresponding Makefile variable is automatically set to point to the processed version.

`SUB_LIST` is a list of `VAR=VALUE` pairs.
For each pair, `%%VAR%%` will be replaced with `VALUE` in each file listed in `SUB_FILES`.
Several common pairs are automatically defined: `PREFIX`, `LOCALBASE`, `DATADIR`, `DOCSDIR`, `EXAMPLESDIR`, `WWWDIR`, and `ETCDIR`.
Any line beginning with `@comment` followed by a space, will be deleted from resulting files after a variable substitution.

This example replaces `%%ARCH%%` with the system architecture in a [.filename]#pkg-message#:

[.programlisting]
....
SUB_FILES=	pkg-message
SUB_LIST=	ARCH=${ARCH}
....

Note that for this example, [.filename]#pkg-message.in# must exist in `FILESDIR`.

Example of a good [.filename]#pkg-message.in#:

[.programlisting]
....
Now it is time to configure this package.
Copy %%PREFIX%%/shared/examples/putsy/%%ARCH%%.conf into your home directory
as .putsy.conf and edit it.
....
