(Originally published at 32bitsonline.com, 1999) FreeBSD Ports and Packages System Explained Bill Swingle What is the ports collection? If you've ever toyed around with one of the many Unix-based operating systems, chances are you've had to compile a thing or two from source code. Chances are that you've also encountered source code that would not compile on your system, due to it being written for a different Unix operating system, to poor coding on the author's part, or just because your system is missing other programs the compile depends on. The FreeBSD ports/packages system attempts to address all of these issues and make third party application installation a breeze. As an operating system, FreeBSD has a lot in common with most other Unix operating systems. This means that there are a lot of applications that, though originally written for another OS, such as Linux, will compile and run with little or no difficulty on FreeBSD. This is where the ports system comes into play. The ports system is really nothing more than a few files per application that describe how that application has to be modified to compile, install and run on FreeBSD. Even the downloading of the original application is handled by the ports system. Installing new applications comes down to running one command, "make install". How does it work? Let's look at a sample port build to get a better idea of how the process plays out. First you must cd into the directory for the application that you want to install. All of the 3100+ ports are divided into categories based on what kind of program it is. In this example we're going to install a popular GUI-based IRC client called xchat: # cd /usr/ports/irc/xchat This directory contains whatever source code patches are needed to get the program to compile and a Makefile that controls where the original source is downloaded from, how the patches are applied, how the program is compiled and where it is installed. It's hard to believe, but all of this is done by typing make install. # make install >> xchat-1.4.0.tar.bz2 doesn't seem to exist on this system. >> Attempting to fetch from http://xchat.org/files/source/1.4/. Receiving xchat-1.4.0.tar.bz2 (333132 bytes): 100% 333132 bytes transferred in 4.1 seconds (79.76 Kbytes/s) ===> Extracting for xchat-1.4.0 >> Checksum OK for xchat-1.4.0.tar.bz2. ===> xchat-1.4.0 depends on executable: bzip2 - found ===> xchat-1.4.0 depends on executable: gmake - found ===> xchat-1.4.0 depends on shared library: gtk12.2 - found ===> xchat-1.4.0 depends on shared library: Imlib.5 - found ===> xchat-1.4.0 depends on shared library: X11.6 - found ===> Patching for xchat-1.4.0 ===> Configuring for xchat-1.4.0 ... [configure output snipped] ... ===> Building for xchat-1.4.0 ... [compilation snipped] ... ===> Installing for xchat-1.4.0 ===> xchat-1.4.0 depends on shared library: gtk12.2 - found ===> xchat-1.4.0 depends on shared library: Imlib.5 - found ===> xchat-1.4.0 depends on shared library: X11.6 - found ... [install routines snipped] ... ===> Generating temporary packing list ===> Installing xchat docs in /usr/X11R6/share/doc/xchat ===> Registering installation for xchat-1.4.0 # Xchat is now installed. No messing with patches, crazy command line options, or even having to find the right ftp server to get the download from. You'll notice that the port even checked to see that several other applications that it depends on were already installed. In this case the dependencies were all already installed but, if it hadn't found any of them, it would have gone and installed them, as well using those applications entries in the ports system. What do packages have to do with all this? Well, if you're like me, every unix system that you own/run has a few applications in common that you install as soon as the base operating system is installed. I, generally, install the bash shell, the less pager, the vim editor, and ssh. Having to compile these things over and over again gets to be a bit of a pain if not merely time consuming. The ports system is tightly associated with the package system. Once you've built a port from source and installed it on the system, you can make a package out of it with the make package command. Make sure you're in the same directory that you ran make install from. # cd /usr/ports/irc/xchat # make package ===> Building package for xchat-1.4.0 Creating package /usr/ports/irc/xchat/xchat-1.4.0.tgz Registering depends: gettext-0.10.35 glib-1.2.6 gtk-1.2.6 imlib-1.9.8 jpeg-6b libungif-4.1.0 png-1.0.5 tiff-3.5.4. Creating gzip'd tar ball in '/usr/ports/irc/xchat/xchat-1.4.0.tgz' # Once again, the port makes sure that you have the correct dependencies and then it takes all of the files that were installed when you did a make install and puts them into a package. When make package is finished, it leaves you with a tarball called, in this case, xchat-1.4.0.tgz. This tarball contains all of the binaries that you just compiled from source. You can now take this package to another FreeBSD system and use the pkg_add command to install it without having to recompile it again. Normally pkg_add, when used without any options, will not print anything if it successfully installs the package. In the example below, we're running pkg_add with the -v option so you can get a little better idea of what it's actually doing. # pkg_add -v ./xchat-1.4.0.tgz Requested space: 968680 bytes, free space: 111746048 bytes in /var/tmp/instmp.a30314 Package `xchat-1.4.0' depends on `gettext-0.10.35'. - already installed. Package `xchat-1.4.0' depends on `glib-1.2.6'. - already installed. Package `xchat-1.4.0' depends on `gtk-1.2.6'. - already installed. Package `xchat-1.4.0' depends on `imlib-1.9.8'. - already installed. Package `xchat-1.4.0' depends on `jpeg-6b'. - already installed. Package `xchat-1.4.0' depends on `libungif-4.1.0'. - already installed. Package `xchat-1.4.0' depends on `png-1.0.5'. - already installed. Package `xchat-1.4.0' depends on `tiff-3.5.4'. - already installed. extract: Package name is xchat-1.4.0 ... [ extraction details snipped ] ... Attempting to record package into /var/db/pkg/xchat-1.4.0.. Attempting to record dependency on package `gettext-0.10.35' Attempting to record dependency on package `glib-1.2.6' Attempting to record dependency on package `gtk-1.2.6' Attempting to record dependency on package `imlib-1.9.8' Attempting to record dependency on package `jpeg-6b' Attempting to record dependency on package `libungif-4.1.0' Attempting to record dependency on package `png-1.0.5' Attempting to record dependency on package `tiff-3.5.4' Package xchat-1.4.0 registered in /var/db/pkg/xchat-1.4.0 The fun doesn't stop there, though. Within the FreeBSD project there is a whole team of people whose main responsibility is maintaining these ports and packages. In fact, the project has a cluster of nine servers whose sole purpose in life is to build all 3100+ ports each night to make sure that they still compile correctly. This testing procedure also includes testing the package facilities of each port which, of course, produces a viable package. These packages that are built each night are available on the main FreeBSD ftp server. I know what you're thinking, "Oh great, now I have to go digging through a gigantic ftp server to find these easy-to-install packages". Nope, this functionality is already built into pkg_add with the -r flag. From the pkg_add(1) man page: -r Use the remote fetching feature. This will determine the appropriate objformat and release and then fetch and install the package. So, not only will pkg_add install the package for you, it will also download the newest version for your platform. Because you're getting the newest version when using the -r option you don't have to worry about version numbers. In this example, as in all the others, pkg_add checks for dependencies. This time it finds one that is not installed so it downloads and installs it for you. # pkg_add -r xchat Fetching ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/i386/packages-current/Latest/xchat. tgz ... Done. Fetching ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/i386/packages-current/All/gtk-1.2.7.tgz ... Done. # In fact, you can specify multiple packages to install at the same time. When I bring up a new FreeBSD system, I run this command: # pkg_add -r bash less vim Fetching ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/i386/packages-current/Latest/bash.tgz... Done. updating /etc/shells Fetching ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/i386/packages-current/Latest/less.tgz... Done. Fetching ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/i386/packages-current/Latest/vim.tgz... Done. # Removing Installed Ports Since installing new applications is so easy, using the ports/packages system is a great way to try out new applications. Of course, at some point you're going to want to remove an application that you've installed using this method. Depending how you installed the application, you can remove it one of two ways. If you installed the application by compiling it with the make install command, you have to use the make deinstall command: # cd /usr/ports/irc/xchat # make deinstall ===> Deinstalling for xchat-1.4.0 # If you installed the application using the pkg_add command you must use the pkg_delete command: # pkg_delete -v xchat-1.4.0 Change working directory to /usr/X11R6 Delete file /usr/X11R6/bin/xchat ... [ deleted file list snipped ] ... When Good Ports Go Bad Each of the 3100+ ports in the ports collection has a maintainer who is responsible for making sure that the port stays up to date with the current version of the application. This includes making sure that the code continues to compile and that the original distributions are still available in the same location. The nightly testing of all of the ports generates a report for all of the maintainers letting them know when there are problems with their ports. Of course these maintainers are only human so sometimes these problems don't get fixed right away. The most common problem is when the original distribution has moved to another location. Without knowing where it has moved to, the ports system can't download it to build the application in the first place. Anytime you have a problem building any of the ports, you should report it to the port maintainer or to the [2]freebsd-ports@freebsd.org mailing list. The port maintainer is listed in the Makefile in each port and also on the [3]FreeBSD Ports website. Please include as much detail as possible when reporting a problem. References 1. mailto:unfurl@freebsd.org 2. mailto:freebsd-ports@freebsd.org 3. http://www.freebsd.org/ports/