Index: head/en_US.ISO8859-1/books/porters-handbook/plist/chapter.xml =================================================================== --- head/en_US.ISO8859-1/books/porters-handbook/plist/chapter.xml (revision 45655) +++ head/en_US.ISO8859-1/books/porters-handbook/plist/chapter.xml (revision 45656) @@ -1,743 +1,804 @@ Advanced <filename>pkg-plist</filename> Practices Changing <filename>pkg-plist</filename> Based on Make Variables Some ports, particularly the p5- ports, need to change their pkg-plist depending on what options they are configured with (or version of perl, in the case of p5- ports). To make this easy, any instances in pkg-plist of %%OSREL%%, %%PERL_VER%%, and %%PERL_VERSION%% will be substituted appropriately. The value of %%OSREL%% is the numeric revision of the operating system (for example, 4.9). %%PERL_VERSION%% and %%PERL_VER%% is the full version number of perl (for example, 5.8.9). Several other %%VARS%% related to port's documentation files are described in the relevant section. To make other substitutions, set PLIST_SUB with a list of VAR=VALUE pairs and instances of %%VAR%% will be substituted with VALUE in pkg-plist. For instance, if a port installs many files in a version-specific subdirectory, use a placeholder for the version so that pkg-plist does not have to be regenerated every time the port is updated. For example: OCTAVE_VERSION= ${PORTREVISION} PLIST_SUB= OCTAVE_VERSION=${OCTAVE_VERSION} in the Makefile and use %%OCTAVE_VERSION%% wherever the version shows up in pkg-plist. When the port is upgraded, it will not be necessary to edit dozens (or in some cases, hundreds) of lines in pkg-plist. If files are installed conditionally on the options set in the port, the usual way of handling it is prefixing pkg-plist lines with a %%OPT%% for lines needed when the option is enabled, or %%NO_OPT%% when the option is disabled, and adding OPTIONS_SUB=yes to the Makefile. See for more information. For instance, if there are files that are only installed when the X11 option is enabled, and Makefile has: OPTIONS_DEFINE= X11 OPTIONS_SUB= yes In pkg-plist, put %%X11%% in front of the lines only being installed when the option is enabled, like this : %%X11%%bin/foo-gui This substitution will be done between the pre-install and do-install targets, by reading from PLIST and writing to TMPPLIST (default: WRKDIR/.PLIST.mktmp). So if the port builds PLIST on the fly, do so in or before pre-install. Also, if the port needs to edit the resulting file, do so in post-install to a file named TMPPLIST. Another way of modifying a port's packing list is based on setting the variables PLIST_FILES, PLIST_DIRS, and PLIST_DIRSTRY. The value of each variable is regarded as a list of pathnames to write to TMPPLIST along with PLIST contents. Names listed in PLIST_FILES, PLIST_DIRS, and PLIST_DIRSTRY are subject to %%VAR%% substitution as described above. Except for that, names from PLIST_FILES will appear in the final packing list unchanged, while @dirrm and @dirrmtry will be prepended to names from PLIST_DIRS and PLIST_DIRSTRY, respectively. To take effect, PLIST_FILES, PLIST_DIRS, and PLIST_DIRSTRY must be set before TMPPLIST is written, that is, in pre-install or earlier. From time to time, using OPTIONS_SUB is not enough. In those cases, adding a specific TAG to PLIST_SUB inside the Makefile with a special value of @comment, makes package tools to ignore the line. For instance, if some files are only installed when the X11 option is on and the architecture is i386: .include <bsd.port.pre.mk> .if ${PORT_OPTIONS:MX11} && ${ARCH} == "i386" PLIST_SUB+= X11I386="" .else PLIST_SUB+= X11I386="@comment " .endif Empty Directories Cleaning Up Empty Directories When being de-installed, A port has to remove empty directories it created. This is usually accomplished by adding @dirrm lines for all directories that are specifically created by the port. Subdirectories must be deleted before deleting parent directories. : 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 However, sometimes @dirrm will give errors because other ports share the same directory. Use @dirrmtry to remove only empty directories without warning. @dirrmtry share/doc/gimp This will neither print any error messages nor cause pkg delete (see &man.pkg-delete.8;) to exit abnormally even if ${PREFIX}/share/doc/gimp is not empty due to other ports installing some files in there. Creating Empty Directories Empty directories created during port installation need special attention. They must be present when the package is created. If they are not created by the port code, create them in the Makefile: post-stage: @${MKDIR} ${STAGEDIR}${PREFIX}/some/directory Add the directory to pkg-plist like any other. For example, if the directory has files created when the port is used: @dirrmtry some/directory Configuration Files If the port installs configuration files to PREFIX/etc (or elsewhere) do not list them in pkg-plist. That will cause pkg delete to remove files that have been carefully edited by the user, and a re-installation will wipe them out. Instead, install sample files with a filename.sample extension. The @sample macro automates this, see for what it does exactly. For each sample file, add a line to pkg-plist: @sample etc/orbit.conf.sample If there is a very good reason not to install a working configuration file by default, only list the sample filename in pkg-plist, without the @sample part, and add a message pointing out that the user must copy and edit the file before the software will work. When a port installs its configuration in a subdirectory of ${PREFIX}/etc, use ETCDIR, which defaults to ${PREFIX}/etc/${PORTNAME}, it can be overridden in the ports Makefile if there is a convention for the port to use some other directory. The %%ETCDIR%% macro will be used in its stead in pkg-plist. The sample configuration files should always have the .sample suffix. If for some historical reason using the standard suffix is not possible, use this construct: @unexec if cmp -s %D/etc/orbit.conf-dist %D/etc/orbit.conf; then rm -f %D/etc/orbit.conf; fi etc/orbit.conf-dist @exec if [ ! -f %D/etc/orbit.conf ] ; then cp -p %D/%F %B/orbit.conf; fi 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 @unexec 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 @exec line comes after the sample configuration file name. To debug any issues, temporarily remove the -s flag to &man.cmp.1; for more output. See &man.pkg-create.8; for more information on %D and related substitution markers. Dynamic Versus Static Package List A static package list is a package list which is available in the Ports Collection either as pkg-plist (with or without variable substitution), or embedded into the Makefile via PLIST_FILES, PLIST_DIRS, and PLIST_DIRSTRY. Even if the contents are auto-generated by a tool or a target in the Makefile before the inclusion into the Ports Collection by a committer (for example, using make makeplist>), this is still considered a static list, since it is possible to examine it without having to download or compile the distfile. A dynamic package list 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 make clean. 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. For example, ports which generate docs with Javadoc. Automated Package List Creation First, make sure the port is almost complete, with only pkg-plist missing. Running make makeplist will show an example for pkg-plist. The output of makeplist must be double checked for correctness as it tries to automatically guess a few things, and can get it wrong. User configuration files should be installed as filename.sample, as it is described in . info/dir must not be listed and appropriate install-info lines must be added as noted in the info files section. Any libraries installed by the port must be listed as specified in the shared libraries section. Expanding Package List with Keywords + All keywords can also take optional arguments in + parentheses. The arguments are owner, group, and mode. This + argument is used on the file or directory referenced. + To change the owner, group, and mode of a configuration file, + use: + + @sample(games,games,640) etc/config.sample + + The arguments are optional. If only the group and mode + need to be changed, use: + + @sample(,games,660) etc/config.sample + <literal>@fc</literal> <replaceable>directory</replaceable> Add a @dirrmtry entry for the directory passed as an argument, and run fc-cache -s on that directory after installation and deinstallation. <literal>@fcfontsdir</literal> <replaceable>directory</replaceable> Add a @dirrmtry entry for the directory passed as an argument, and run fc-cache -s, mkfontscale and mkfontdir on that directory after installation and deinstallation. Additionally, on deinstallation, it removes the fonts.scale and fonts.dir cache files if they are empty. <literal>@fontsdir</literal> <replaceable>directory</replaceable> Add a @dirrmtry entry for the directory passed as an argument, and run mkfontscale and mkfontdir on that directory after installation and deinstallation. Additionally, on deinstallation, it removes the fonts.scale and fonts.dir cache files if they are empty. <literal>@info</literal> <replaceable>file</replaceable> Add the file passed as argument to the plist, and updates the info document index on installation and deinstallation. Additionally, it removes the index if empty on deinstallation. <literal>@sample</literal> <replaceable>file</replaceable> Add the file passed as argument to the plist. On installation, check for a real file with just the base name (the name without the .sample extension). If the real file is not found, copy the sample file to the base file name. On deinstallation, remove the configuration file if it has not been modified. See for more information. <literal>@shell</literal> <replaceable>file</replaceable> Add the file passed as argument to the plist. On installation, add the full path to file to /etc/shells, while making sure it is not added twice. On deinstallation, remove it from /etc/shells. Base Keywords - There are a few historic keywords that are hardcoded, and + There are a few keywords that are hardcoded, and documented in &man.pkg-create.8;. For the sake of completeness, they are also documented here. + + <literal>@</literal> + [<replaceable>file</replaceable>] + + The empty keyword is a placeholder to use when the + file's owner, group, or mode need to be changed. For + example, to set the group of the file to + games and add the setgid bit, add: + + @(,games,2755) sbin/daemon + + <literal>@cwd</literal> [<replaceable>directory</replaceable>] Set the internal directory pointer to point to directory. All subsequent filenames are assumed relative to this directory. <literal>@exec</literal> <replaceable>command</replaceable> Execute command as part of the unpacking process. If command contains any of these sequences somewhere in it, they are expanded inline. For these examples, assume that @cwd is set to /usr/local and the last extracted file was bin/emacs. %F Expand to the last filename extracted (as specified). In the example case bin/emacs. %D Expand to the current directory prefix, as set with @cwd. In the example case /usr/local. %B Expand to the basename of the fully qualified filename, that is, the current directory prefix plus the last filespec, minus the trailing filename. In the example case, that would be /usr/local/bin. %f Expand to the filename part of the fully qualified name, or the converse of %B. In the example case, emacs. <literal>@unexec</literal> <replaceable>command</replaceable> Execute command as part of the deinstallation process. Expansion of special % sequences is the same as for @exec. This command is not executed during the package add, as @exec is, but rather when the package is deleted. This is useful for deleting links and other ancillary files that were created as a result of adding the package, but not directly known to the package's table of contents (and hence not automatically removable). <literal>@mode</literal> <replaceable>mode</replaceable> Set default permission for all subsequently extracted files to mode. Format is the same as that used by &man.chmod.1;. Use without an arg to set back to default permissions (mode of the file while being packed). + + + This must be a numeric mode, like + 644, 4755, or + 600. It cannnot be a relative mode + like u+s. + <literal>@owner</literal> <replaceable>user</replaceable> Set default ownership for all subsequent files to user. Use without an argument to set back to default ownership (root). <literal>@group</literal> <replaceable>group</replaceable> Set default group ownership for all subsequent files to group. Use without an arg to set back to default group ownership (wheel). <literal>@comment</literal> <replaceable>string</replaceable> This line is ignored when packing. + + <literal>@dir</literal> + <replaceable>directory</replaceable> + + Declare directory name. By default, directories created + under PREFIX by a package installation + are automatically removed. Use this when an empty directory + under PREFIX needs to be created, or when + the directory needs to have non default owner, group, or + mode. Directories outside of PREFIX need + to be registered. For example, + /var/db/${PORTNAME} needs to have a + @dir entry whereas + ${PREFIX}/share/${PORTNAME} does not if + it contains files or uses the default owner, group, and + mode. + + <literal>@dirrm</literal> - <replaceable>directory</replaceable> + directory (Deprecated) Declare directory name to be deleted at deinstall time. - By default, directories created by a package installation - are not deleted when the package is deinstalled. This - provides an explicit directory cleanup method. These - directives must appear at the end of the package list. If - the directory is not empty a warning is printed, and the - directory is not removed. + By default, directories created under + PREFIX by a package installation are + deleted when the package is deinstalled. <literal>@dirrmtry</literal> - <replaceable>directory</replaceable> + directory (Deprecated) Declare directory name to be removed, as for @dirrm, but does not issue a warning if the directory cannot be removed. Creating New Keywords Package list files can be extended by keywords that are defined in the ${PORTSDIR}/Keywords directory. - The settings for each keyword lives in a - YAML file named - keyword.yaml. + The settings for each keyword are stored in a + UCL file named + keyword.ucl. The file must contain at least one of the next sections: attributes Changes the owner, group, or mode used by the keyword. Contains an associative array where the possible keys are owner, group, and mode. The values are, respectively, a user name, a group name, and a file mode. For example: attributes: { owner: "games", group: "games", mode: 0555 } action Defines what happens to the keyword's parameter. Contains an array where the possible values are: setprefix Set the prefix for the next plist entries. + dir + + + Register a directory to be created on + install and removed on deinstall. + + + + dirrm Register a directory to be deleted on - deinstall. + deinstall. Deprecated. dirrmtry Register a directory to try and deleted on - deinstall. + deinstall. Deprecated. file Register a file. setmode Set the mode for the next plist entries. setowner Set the owner for the next plist entries. setgroup Set the group for the next plist entries. comment Does not do anything, equivalent to not entering an action section. ignore_next Ignore the next entry in the plist. pre-install post-install pre-deinstall post-deinstall pre-upgrade post-upgrade These keywords contains a &man.sh.1; script to be executed before or after installation, deinstallation, or upgrade of the package. In addition to the usual @exec %foo placeholders described in , there is a new one, %@, which represents the argument of the keyword. Example of a <literal>@dirrmtryecho</literal> Keyword This keyword does two things, it adds a @dirrmtry directory line to the packing list, and echoes the fact that the directory is removed when deinstalling the package. actions: [dirrmtry] -post-deinstall: | - echo "Directory %D/%@ removed." +post-deinstall: <<EOD + echo "Directory %D/%@ removed." +EOD Real Life Example, How the <literal>@sample</literal> - Could be Implemented + is Implemented This keyword does three things, it adds the filename passed as an argument to @sample to the packing list, it adds to the post-install script instructions to copy the sample to the actual configuration file if it does not already exist, and it adds to the post-deinstall instructions to remove the configuration file if it has not been modified. actions: [file] -post-install: | +post-install: <<EOD case "%@" in /*) sample_file="%@" ;; *) sample_file="%D/%@" ;; esac target_file="${sample_file%.sample}" if ! [ -f "${target_file}" ]; then /bin/cp -p "${sample_file}" "${target_file}" fi -pre-deinstall: | +EOD +pre-deinstall: <<EOD case "%@" in /*) sample_file="%@" ;; *) sample_file="%D/%@" ;; esac target_file="${sample_file%.sample}" if cmp -s "${target_file}" "${sample_file}"; then rm -f "${target_file}" - fi + else + echo "You may need to manually remove ${target_file} if it's no longer needed." + fi +EOD