As of 2015, all ports should already have been staged, but you can check for any stragglers on portsmon.
The stage directory support means that a port does not install directly into the destination directories, but instead into a separate directory (automake packages call this DESTDIR) from which the package is then built - in many cases, this does not require root privileges. If enabled for a port, the package is first built, installed into the STAGEDIR, packaged, and then installed from the package. If disabled, the traditional approach is used, which means to install directly into the destination and build the package from there.
List of information to know to be able to convert a port.
NO_STAGE=yes line.${STAGEDIR} before everything that is a destination${PREFIX}, ${ETCDIR}, ${DATADIR}, ${EXAMPLESDIR}, ${MANPREFIX}, ${DOCSDIR}, etc.@exec entries in pkg-plist, or by the pkg-install script. Duplicating these in both places is no longer needed as the package installation will run them.pkg-message, it will be shown automatically when the package installs.post-install: target (in particular because pkgng doesn't work like pkg_install in that area and pkgng ignores the @exec mkdir, and directly packs the directory even if empty).${CHMOD} ... and ${CHOWN}... and ${INSTALL_PROGRAM} -m mode -o user -g group with corresponding pkg-plist entries: @mode mode, @owner user, @group group. @mode, @owner root, @group wheel keywords afterwards.@dirrm(try) directory. For pkg_tools compatibility add: @exec install -d -o user -g group -m mode %D/directory.USES+=uidfix to the port's Makefile helps you. It will override the default user IDs for the ports-framework-based installation commands to the user running them, and the packaging from the stage should then see to proper owner/group settings. See above for how to change them..if blocks can be made unconditional, except in cases when installed files are big enough to cause significant I/O overhead.${STAGEDIR} to the target path only (and generally try to avoid using absolute paths in source). Example:${LN} -sf libfoo.so.42 ${STAGEDIR}${PREFIX}/lib/libfoo.so
}}} /!\ Note that source of `${PREFIX}/lib/libfoo.so.42`, while seemingly okay, could be in fact incorrect, since absolute path can potentially point to a wrong location, e.g. when remote filesystem (with installed package) is mounted via NFS under non-root mount point. Relative paths are less fragile (and often much shorter).
== @exec, @unexec ordering in pkg-plist ==
* If there are `@exec` and `@unexec` that deal with installed files, for instance, copying a sample file to a configuration in @exec and removing it - if unaltered - from @unexec, the @unexec must be '''before''' and the @exec must be '''after''' the affected file. Example: {{{
@comment ### THIS IS WRONG ###
@exec if [ ! -f %D/etc/dnsmasq.conf ]; then cp -p %D/%F %B/dnsmasq.conf; fi
@unexec if cmp -s %D/etc/dnsmasq.conf %D/etc/dnsmasq.conf.example ; then rm -f %D/etc/dnsmasq.conf ; fi
etc/dnsmasq.conf.example}}} must be converted to: {{{
@unexec if cmp -s %D/etc/dnsmasq.conf %D/etc/dnsmasq.conf.example ; then rm -f %D/etc/dnsmasq.conf ; fi
etc/dnsmasq.conf.example
@exec if [ ! -f %D/etc/dnsmasq.conf ]; then cp -p %D/%F %B/dnsmasq.conf; fi}}}
== PORTDOCS PORTEXAMPLES ==
* To support PORTDOCS and PORTEXAMPLES, most of the time, there is no more need for hacks. Just add the right %%PORTDOCS%% or %%PORTEXAMPLES%% as prefix in your pkg-plist, then the given files from the stagedir will or will not become part of the package according to DOCS and EXAMPLES port options.
== MAN*/MANLANG/MLINKS now useless ==
* manpage compression/uncompression is now automatically handled by the framework if you use stagedir.
* When converting remove the `MAN*`, `MANLANG` and `MLINKS` and add the man pages as any normal files in pkg-plist.
* Conversion script: {{{
{ for section in $(jot 9); do for file in $(make -V MAN${section}); do echo man/man${section}/${file}.gz; done; done; MLINKS=$(make -V MLINKS); set -- ${MLINKS}; while :; do [ $# -eq 0 ] && break; file=$2; section=${file##*.}; echo man/man${section}/${file}.gz; shift 2; done; }|sort
make -V __MANPAGES -V _MLINKS | tr ' ' '\n' | sed -e 's=/usr/local/==g' | sort -u
make -V __MANPAGES | tr ' ' '\n' | sort
The above command should help preparing plist now that you are staged.
Make sure you tested make package as a normal user (not root). If that fails, add NEED_ROOT=yes in the port's Makefile.
If this happens when the upstream software you are packaging claims DESTDIR support, it is broken (Mailman up to 2.1.16, for instance).
Barring upstream fixes, you can work around the problem, and recompile scripts like this, for instance, from a post-build: target. Assuming your Python scripts are supposed to reside in ${PYTHONPREFIX_SITELIBDIR} after installation:
(cd ${STAGEDIR}${PREFIX} \
&& ${PYTHON_CMD} ${PYTHON_LIBDIR}/compileall.py \
-d ${PYTHONPREFIX_SITELIBDIR} -f ${PYTHONPREFIX_SITELIBDIR:S;${PREFIX}/;;})
This runs a compilation on a path relative to the stage directory (based on the cd ${STAGEDIR}${PREFIX} part), and prefixes the ${PYTHONPREFIX_SITELIBDIR} to the file name recorded in the byte-compiled output file (through the -d ${PYTHONPREFIX_SITELIBDIR}). -f is required to force recompilation, and the :S;${PREFIX}/;; is to strip the prefix from the PYTHONPREFIX_SITELIBDIR variable to make it a path relative to ${PREFIX}.
grep -r work/stage `make -V WRKSRC`
For p5-ports which previously use MAN3 you can use macro PERL5_MAN3 inside pkg-plist.
For example:
lib/perl5/5.14/man/man3/AnyEvent::I3.3.gz can be replaced with %%PERL5_MAN3%%/AnyEvent::I3.3.gz
Beware: pkg_install is buggy when handling “@cwd”, if your ports have “@cwd” in the plist it needs to be changed to the actual directory. Using
@cwd %%PREFIX%% will not work as it is already in PLIST_SUB as PREFIX=%D.
A workaround is to use @cwd %%RESETPREFIX%% in pkg-plist.
Please add NO_MTREE=yes on meta ports. Otherwise, they would needlessly extract the mtree to the stage dir, and be counted as orphans.
Ports that install kernel modules (usually in /boot/modules) can add USES=kmod to Makefile to have most items taken care of.
Makefile.in created with old automake runs ranlib twice, when building the library and when installin (on our case, staging), and because of that you can see errors like these:
Making install in lib /bin/sh ../mkinstalldirs .../work/stage/usr/local/lib install -m 444 libft.a .../work/stage/usr/local/lib/libft.a /usr/local/bin/ranlib .../work/stage/usr/local/lib/libft.a /usr/local/bin/ranlib: unable to copy file '.../work/stage/usr/local/lib/libft.a'; reason: Permission denied
A workaround to get it fixed is to add a REINPLACE_CMD on post-patch: target to remove RANLIB from installation, like this:
@${REINPLACE_CMD} -e '/echo.*RANLIB/,+1d' \
${WRKSRC}/lib/Makefile.in