FreeBSD Handbook : Installing Applications: The Ports collection : Making a port yourself : Special Considerations
Previous: Configuring the Makefile
Next: The pkg Subdirectory

4.7.4. Special Considerations

There are some more things you have to take into account when you create a port. This section explains the most common of those.

4.7.4.1. ldconfig

If your port installs a shared library, add a post-install target to your Makefile that runs `${LDCONFIG} -m' on the directory where the new library is installed (usually ${PREFIX}/lib) to register it into the shared library cache.

Also, add a matching `@exec /sbin/ldconfig -m'/`@unexec /sbin/ldconfig -R' pair to your pkg/PLIST file so that a user who installed the package can start using the shared library immediately and deinstallation will not cause the system to still believe the library is there. These lines should immediately follow the line for the shared library itself, as in:

lib/libtcl80.so.1
@exec /sbin/ldconfig -m %D/lib
@unexec /sbin/ldconfig -R

Never, ever, ever add a line that says `ldconfig' without any arguments to your Makefile or pkg/PLIST. This will reset the shared library cache to the contents of /usr/lib only, and will royally screw up the user's machine ("Help, xinit does not run anymore after I install this port!"). Anybody who does this will be shot and cut into 65,536 pieces by a rusty knife and have his liver chopped out by a bunch of crows and will eternally rot to death in the deepest bowels of hell (not necessarily in that order)....

4.7.4.2. ELF support

Since FreeBSD moved to ELF with the 3.0-RELEASE, we need to convert many ports that build shared libraries to support ELF. Complicating this task is that a 3.0 system can run as both ELF and a.out, and we wish to unoffically support the 2.2 as long as possible. Below are the guidelines on how to convert a.out only ports to support both a.out and ELF compilation.

Some part of this list is only applicable during the conversion, but will be left here for awhile for reference in case you have come across some old port you wish to upgrade.

Moving a.out libraries out of the way

A.out libraries should be moved out of /usr/local/lib and similar to an `aout' subdirectory. (If you don't move them out of the way, ELF ports will happily overwrite a.out libraries.) The `move-aout-libs' target in the 3.0-CURRENT src/Makefile (called from `aout-to-elf') will do this for you. It will only move a.out libs so it is safe to call it on a system with both ELF and a.out libs in the standard directories.

Format

The ports tree will build packages in the format the machine is in. This means a.out for 2.2 and a.out or ELF for 3.0 depending on what `objformat` returns. Also, once users move a.out libraries to a subdirectory, building a.out libraries will be unsupported. (I.e., it may still work if you know what you are doing, but you are on your own.)

Note: if a port only works for a.out, set BROKEN_ELF to a string describing the reason why. Such ports will be skipped during a build on an ELF system.

PORTOBJFORMAT

bsd.port.mk will set PORTOBJFORMAT to `aout' or `elf' and export it in the environments CONFIGURE_ENV, SCRIPTS_ENV and MAKE_ENV. (It's always going to be `aout' in 2.2-STABLE). It is also passed to PLIST_SUB as `PORTOBJFORMAT=${PORTOBJFORMAT}'. (See comment on ldconfig lines below.)

The variable is set using this line:

PORTOBJFORMAT!= test -x /usr/bin/objformat && /usr/bin/objformat || echo aout
in bsd.port.mk.

Ports' make processes should use this variable to decide what to do. However, if the port's configure script already automatically detects an ELF system, it is not necessary to refer to PORTOBJFORMAT.

Building shared libraries

The following are differences in handling shared libraries for a.out and ELF.

Shared library versions

An ELF shared library should be called "libfoo.so.M" where M is the single version number, and an a.out library should be called "libfoo.so.M.N" where M is the major version and N is the the minor version number. Do not mix those; never install an ELF shared library called "libfoo.so.N.M" or an a.out shared library (or symlink) called "libfoo.so.N".

Linker command lines

Assuming `cc -shared' is used rather than `ld' directly, the only difference is that you need to add `-Wl,-soname,libfoo.so.M' on the command line for ELF.

You need to install a symlink libfoo.so -> libfoo.so.N to make ELF linkers happy. Since it should be listed in PLIST too, and it won't hurt in the a.out case (some ports even require the link for dynamic loading), you should just make this link regardless of the setting of PORTOBJFORMAT.

LIB_DEPENDS

All port Makefiles are edited to remove minor numbers from LIB_DEPENDS, and also to have the regexp support removed. (E.g., `foo\\.1\\.\\(33|40\\)' -> `foo.2'.) They will be matched using `grep -wF'.

PLIST

PLIST should contain the short (ELF) shlib names if the a.out minor number is zero, and the long (a.out) names otherwise. bsd.port.mk will automatically add `.0' to the end of short shlib lines if PORTOBJFORMAT equals aout, and will delete the minor number from long shlib names if PORTOBJFORMAT equals elf.

In cases where you really need to install shlibs with two versions on an ELF system or those with one version on an a.out system (for instance, ports that install compatibility libraries for other operating systems), define the variable NO_FILTER_SHLIBS. This will turn off the editing of PLIST mentioned in the previous paragraph.

ldconfig

The ldconfig line in Makefiles should read:

${SETENV} OBJFORMAT=${PORTOBJFORMAT} ${LDCONFIG} -m ....
and in PLIST:
@exec /usr/bin/env OBJFORMAT=%%PORTOBJFORMAT%% /sbin/ldconfig -m ...
@unexec /usr/bin/env OBJFORMAT=%%PORTOBJFORMAT%% /sbin/ldconfig -R
This is to ensure that the correct ldconfig will be called depending on the format of the package, not the default format of the system.

4.7.4.3. MASTERDIR

If your port needs to build slightly different versions of packages by having a variable (for instance, resolution or paper size) take different values, create one subdirectory per package to make it easier for users to see what to do, but try to share as many files as possible between ports. Typically you only need a very short Makefile in all but one of the directories if you use variables cleverly. In the sole Makefiles, you can use ${MASTERDIR} to specify the directory where the rest of the files are. Also, use a variable as part of PKGNAME so the packages will have different names.

This will be best demonstrated by an example. This is part of japanese/xdvi300/Makefile:

 :
PKGNAME=	ja-xdvi${RESOLUTION}-17
 :
# default
RESOLUTION?=    300
.if ${RESOLUTION} != 118 && ${RESOLUTION} != 240 && \
	${RESOLUTION} != 300 && ${RESOLUTION} != 400
	@${ECHO} "Error: invalid value for RESOLUTION: \"${RESOLUTION}\"" 
	@${ECHO} "Possible values are: 118, 240, 300 (default) and 400." 
	@${FALSE}
.endif
japanese/xdvi300 also has all the regular patches, package files, etc. If you type `make' there, it will take the default value for the resolution (300) and build the port normally.

As for other resolutions, this is the entire xdvi118/Makefile (minus the comments):

RESOLUTION=     118
MASTERDIR=      ${.CURDIR}/../xdvi300

.include "${MASTERDIR}/Makefile"
(xdvi240/Makefile and xdvi400/Makefile are similar). The ${MASTERDIR} definition tells bsd.port.mk that the regular set of subdirectories like ${PATCHDIR} and ${PKGDIR} are to be found under xdvi300. The RESOLUTION=118 line will override the RESOLUTION?=300 line in xdvi300/Makefile and the port will be built with resolution set to 118.

4.7.4.4. Shared library versions

First, please read our policy on shared library versioning to understand what to do with shared library versions in general. Do not blindly assume software authors know what they are doing; many of them do not. It is very important that these details are carefully considered, as we have quite a unique situation where we are trying to have dozens of potentially incompatible software pairs co-exist. Careless port imports have caused great trouble regarding shared libraries in the past (ever wondered why the port jpeg-6b has a shared library version of `9.0'?). If in doubt, send a message to the FreeBSD ports mailing list <freebsd-ports@FreeBSD.ORG>. Most of the time, your job ends by determining the right shared library version and making appropriate patches to implement it.

However, if there is a port which is a different version of the same software already in the tree, the situation is much more complex. In short, the FreeBSD implementation does not allow the user to specify to the linker which version of shared library to link against (the linker will always pick the highest numbered version). This means, if there is a libfoo.so.3.2 and libfoo.so.4.0 in the system, there is no way to tell the linker to link a particular application to libfoo.so.3.2. It is essentially completely overshadowed in terms of compilation-time linkage. In this case, the only solution is to rename the `base' part of the shared library. For instance, change libfoo.so.4.0 to libfoo4.so.1.0 so both version 3.2 and 4.0 can be linked from other ports.

4.7.4.5. Manpages

The MAN[1-9LN] variables will automatically add any manpages to pkg/PLIST (this means you must not list manpages in the PLIST -- see generating PLIST for more). It also makes the install stage automatically compress or uncompress manpages depending on the setting of NOMANCOMPRESS in /etc/make.conf.

To specify whether the manpages are compressed upon installation, use the MANCOMPRESSED variable. This variable can take three values, `yes', `no' and `maybe'. `yes' means manpages are already installed compressed, `no' means they are not, and `maybe' means the software already respects the value of NOMANCOMPRESS so bsd.port.mk does not have to do anything special.

MANCOMPRESSED is automatically set to `yes' if USE_IMAKE is set and NO_INSTALL_MANPAGES is not set, and to `no' otherwise. You don't have to explicitly define it unless the default is not suitable for your port.

If your port anchors its man tree somewhere other than PREFIX, you can use the MANPREFIX to set it. Also, if only manpages in certain sections go in a non-standard place, such as some Perl modules ports, you can set individual man paths using MANsectPREFIX (where sect is one of 1-9, L or N).

If your manpages go to language-specific subdirectories, set the name of the languages to MANLANG. The value of this variable defaults to "" (i.e., English only).

Here is an example that puts it all together.

MAN1=          foo.1
MAN3=          bar.3
MAN4=          baz.4
MANLANG=       "" ja
MAN3PREFIX=	${PREFIX}/share/foobar
MANCOMPRESSED= yes
states that six files
${PREFIX}/man/man1/foo.1.gz
${PREFIX}/man/ja/man1/foo.1.gz
${PREFIX}/share/foobar/man/man3/bar.3.gz
${PREFIX}/share/foobar/man/ja/man3/bar.3.gz
${PREFIX}/man/man4/baz.4.gz
${PREFIX}/man/ja/man4/baz.4.gz
are installed by this port.

4.7.4.6. Ports that require Motif

There are many programs that require a Motif library (available from several commercial vendors, while there is a free clone reported to be able to run many applications in x11-toolkits/lesstif) to compile. Since it is a popular toolkit and their licenses usually permit redistribution of statically linked binaries, we have made special provisions for handling ports that require Motif in a way that we can easily compile binaries linked either dynamically (for people who are compiling from the port) or statically (for people who distribute packages).

REQUIRES_MOTIF

If your port requires Motif, define this variable in the Makefile. This will prevent people who don't own a copy of Motif from even attempting to build it.

${MOTIFLIB}

This variable will be set by bsd.port.mk to be the appropriate reference to the Motif library. Please patch the source to use this wherever the Motif library is referenced in the Makefile or Imakefile.

There are two common cases:

  1. If the port refers to the Motif library as `-lXm' in its Makefile or Imakefile, simply substitute `${MOTIFLIB}' for it.
  2. If the port uses `XmClientLibs' in its Imakefile, change it to `${MOTIFLIB} ${XTOOLLIB} ${XLIB}'.

Note that ${MOTIFLIB} (usually) expands to `-L/usr/X11R6/lib -lXm' or `/usr/X11R6/lib/libXm.a', so there is no need to add `-L' or `-l' in front.

4.7.4.7. X11 fonts

If your port installs fonts for the X window system, put them in ${X11BASE}/lib/X11/fonts/local. This directory is new to XFree86 release 3.3.3. If it does not exist, please create it, and print out a message urging the user to update their XFree86 to 3.3.3 or newer, or at least add this directory to the font path in /etc/XF86Config.

4.7.4.8. Info files

The new version of texinfo (included in 2.2.2-RELEASE and onwards) contains a utility called `install-info' to add and delete entries to the `dir' file. If your port installs any info documents, please follow these instructions so your port/package will correctly update the user's ${PREFIX}/info/dir file. (Sorry for the length of this section, but it is imperative to weave all the info files together. If done correctly, it will produce a beautiful listing, so please bear with me! :)

First, this is what you (as a porter) need to know:

% install-info --help
install-info [OPTION]... [INFO-FILE [DIR-FILE]]
  Install INFO-FILE in the Info directory file DIR-FILE.

Options:
--delete          Delete existing entries in INFO-FILE;
                    don't insert any new entries.
 :
--entry=TEXT      Insert TEXT as an Info directory entry.
 :
--section=SEC     Put this file's entries in section SEC of the directory.
 :

Note that this program will not actually install info files; it merely inserts or deletes entries in the dir file.

Here's a seven-step procedure to convert ports to use install-info. I will use editors/emacs as an example.

  1. Look at the texinfo sources and make a patch to insert @dircategory and @direntry statements to files that don't have them. This is part of my patch:
    --- ./man/vip.texi.org	Fri Jun 16 15:31:11 1995
    +++ ./man/vip.texi	Tue May 20 01:28:33 1997
    @@ -2,6 +2,10 @@
     
     @setfilename ../info/vip
     @settitle VIP
    +@dircategory The Emacs editor and associated tools
    +@direntry
    +* VIP: (vip).		A VI-emulation for Emacs.
    +@end direntry
     
     @iftex
     @finalout
     :
    

    The format should be self-explanatory. Many authors leave a dir file in the source tree that contains all the entries you need, so look around before you try to write your own. Also, make sure you look into related ports and make the section names and entry indentations consistent (we recommend that all entry text start at the 4th tab stop).

    Note that you can put only one info entry per file because of a bug in `install-info --delete' that deletes only the first entry if you specify multiple entries in the @direntry section.

    You can give the dir entries to install-info as arguments (--section and --entry) instead of patching the texinfo sources. I do not think this is a good idea for ports because you need to duplicate the same information in three places (Makefile and @exec/@unexec of PLIST; see below). However, if you have a Japanese (or other multibyte encoding) info files, you will have to use the extra arguments to install-info because makeinfo can't handle those texinfo sources. (See Makefile and PLIST of japanese/skk for examples on how to do this).

  2. Go back to the port directory and do a `make clean; make' and verify that the info files are regenerated from the texinfo sources. Since the texinfo sources are newer than the info files, they should be rebuilt when you type make; but many Makefiles don't include correct dependencies for info files. In emacs' case, I had to patch the main Makefile.in so it will descend into the man subdirectory to rebuild the info pages.
    --- ./Makefile.in.org	Mon Aug 19 21:12:19 1996
    +++ ./Makefile.in	Tue Apr 15 00:15:28 1997
    @@ -184,7 +184,7 @@
     # Subdirectories to make recursively.  `lisp' is not included
     # because the compiled lisp files are part of the distribution
     # and you cannot remake them without installing Emacs first.
    -SUBDIR = lib-src src
    +SUBDIR = lib-src src man
     
     # The makefiles of the directories in $SUBDIR.
     SUBDIR_MAKEFILES = lib-src/Makefile man/Makefile src/Makefile oldXMenu/Makefile lwlib/Makefile
    --- ./man/Makefile.in.org	Thu Jun 27 15:27:19 1996
    +++ ./man/Makefile.in	Tue Apr 15 00:29:52 1997
    @@ -66,6 +66,7 @@
     	${srcdir}/gnu1.texi \
     	${srcdir}/glossary.texi
     
    +all: info
     info: $(INFO_TARGETS)
     
     dvi: $(DVI_TARGETS)
    

    The second hunk was necessary because the default target in the man subdir is called info, while the main Makefile wants to call all. I also deleted the installation of the info info file because we already have one with the same name in /usr/share/info (that patch is not shown here).

  3. If there is a place in the Makefile that is installing the dir file, delete it. Your port may not be doing it. Also, remove any commands that are otherwise mucking around with the dir file.
    --- ./Makefile.in.org	Mon Aug 19 21:12:19 1996
    +++ ./Makefile.in	Mon Apr 14 23:38:07 1997
    @@ -368,14 +368,8 @@
     	if [ `(cd ${srcdir}/info && /bin/pwd)` != `(cd ${infodir} && /bin/pwd)` ]; \
     	then \
     	  (cd ${infodir};  \
    -	   if [ -f dir ]; then \
    -	     if [ ! -f dir.old ]; then mv -f dir dir.old; \
    -	     else mv -f dir dir.bak; fi; \
    -	   fi; \
     	   cd ${srcdir}/info ; \
    -	   (cd $${thisdir}; ${INSTALL_DATA} ${srcdir}/info/dir ${infodir}/dir); \
    -	   (cd $${thisdir}; chmod a+r ${infodir}/dir); \
     	   for f in ccmode* cl* dired-x* ediff* emacs* forms* gnus* info* message* mh-e* sc* vip*; do \
     	     (cd $${thisdir}; \
     	      ${INSTALL_DATA} ${srcdir}/info/$$f ${infodir}/$$f; \
     	      chmod a+r ${infodir}/$$f); \
    
  4. (This step is only necessary if you are modifying an existing port.) Take a look at pkg/PLIST and delete anything that is trying to patch up info/dir. They may be in pkg/INSTALL or some other file, so search extensively.
    Index: pkg/PLIST
    ===================================================================
    RCS file: /usr/cvs/ports/editors/emacs/pkg/PLIST,v
    retrieving revision 1.15
    diff -u -r1.15 PLIST
    --- PLIST	1997/03/04 08:04:00	1.15
    +++ PLIST	1997/04/15 06:32:12
    @@ -15,9 +15,6 @@
     man/man1/emacs.1.gz
     man/man1/etags.1.gz
     man/man1/ctags.1.gz
    -@unexec cp %D/info/dir %D/info/dir.bak
    -info/dir
    -@unexec cp %D/info/dir.bak %D/info/dir
     info/cl
     info/cl-1
     info/cl-2
    
  5. Add a post-install target to the Makefile to create a dir file if it is not there. Also, call install-info with the installed info files.
    Index: Makefile
    ===================================================================
    RCS file: /usr/cvs/ports/editors/emacs/Makefile,v
    retrieving revision 1.26
    diff -u -r1.26 Makefile
    --- Makefile	1996/11/19 13:14:40	1.26
    +++ Makefile	1997/05/20 10:25:09	1.28
    @@ -20,5 +20,11 @@
     post-install:
     .for file in emacs-19.34 emacsclient etags ctags b2m
     	strip ${PREFIX}/bin/${file}
     .endfor
    +	if [ ! -f ${PREFIX}/info/dir ]; then \
    +	  ${SED} -ne '1,/Menu:/p' /usr/share/info/dir > ${PREFIX}/info/dir; \
    +	fi
    +.for info in emacs vip viper forms gnus mh-e cl sc dired-x ediff ccmode
    +	install-info ${PREFIX}/info/${info} ${PREFIX}/info/dir
    +.endfor
     
     .include <bsd.port.mk>
    

    Do not use anything other than /usr/share/info/dir and the above command to create a new info file. In fact, I'd add the first three lines of the above patch to bsd.port.mk if you (the porter) wouldn't have to do it in PLIST by yourself anyway.

  6. Edit PLIST and add equivalent @exec statements and also @unexec for pkg_delete. You do not need to delete info/dir with @unexec.
    Index: pkg/PLIST
    ===================================================================
    RCS file: /usr/cvs/ports/editors/emacs/pkg/PLIST,v
    retrieving revision 1.15
    diff -u -r1.15 PLIST
    --- PLIST	1997/03/04 08:04:00	1.15
    +++ PLIST	1997/05/20 10:25:12	1.17
    @@ -16,7 +14,15 @@
     man/man1/etags.1.gz
     man/man1/ctags.1.gz
    +@unexec install-info --delete %D/info/emacs %D/info/dir
     :
    +@unexec install-info --delete %D/info/ccmode %D/info/dir
     info/cl
     info/cl-1
    @@ -87,6 +94,18 @@
     info/viper-3
     info/viper-4
    +@exec [ -f %D/info/dir ] || sed -ne '1,/Menu:/p' /usr/share/info/dir > %D/info/dir
    +@exec install-info %D/info/emacs %D/info/dir
     :
    +@exec install-info %D/info/ccmode %D/info/dir
     libexec/emacs/19.34/i386--freebsd/cvtmail
     libexec/emacs/19.34/i386--freebsd/digest-doc
    

    Note that the `@unexec install-info --delete' commands have to be listed before the info files themselves so they can read the files. Also, the `@exec install-info' commands have to be after the info files and the @exec command that creates the the dir file.

  7. Test and admire your work. :) Check the dir file before and after each step.


FreeBSD Handbook : Installing Applications: The Ports collection : Making a port yourself : Special Considerations
Previous: Configuring the Makefile
Next: The pkg Subdirectory