The Rub

AUTOMATICALLY SIMPLE SINCE 2002

Package GCC 4.2.1 for FreeBSD 10

tl;dr

If you just want a binary package suitable for installing GCC 4.2.1 on 64-bit FreeBSD 10, and you trust me, run:

# pkg add http://php.therub.org/pub/freebsd/base-gcc-4.2.1-20140624.txz

Summary

FreeBSD 10 no longer ships with GCC in base. It can still be installed with a /etc/src.conf tweak and a buildworld/installworld.

In a distributed Ansible environment, this can be inconvenient. I prefer to deploy from generic images and build them up using repeatable, binary processes, and minimizing builds which can introduce subtle differences.

For these reasons, I decided to create a pkgng style package with the exact binaries that the buildworld would have produced. This allows me to distribute it along with the rest of my ansible playbooks in a scalable and repeatable way.

To create the actual “one-off” package, I will use a shell script from danrue/oneoff-pkg-create.

Capturing GCC Binaries

To determine the fileset that adding GCC to the FreeBSD build will produce, first, install FreeBSD 10 and do a buildworld/installworld. Capture the list of files on the file system with find:

find / > /root/pre_gcc.out

To get the legacy GCC 4.2.1 in FreeBSD 10, add the following to /etc/src.conf:

# cat /etc/src.conf
WITH_GCC=yes
WITH_GNUCXX=yes

Perform buildworld/installworld again. Note that the only thing that changed is /etc/src.conf.

Again, run the find:

find / > /root/post_gcc.out

The difference between pre_gcc.out and post_gcc.out will be the files that will need to be packaged.

First, cut out /usr/obj and /usr/src noise, and sort the files:

cd /root
cat pre_gcc.out | grep -v ^\.\/usr\/obj | grep -v ^\.\/usr\/src | sort > pre_trimmed.out
cat post_gcc.out | grep -v ^\.\/usr\/obj | grep -v ^\.\/usr\/src | sort > post_trimmed.out

Diff the files:

diff pre_trimmed.out post_trimmed.out > gcc_manifest

Go through gcc_manifest and clean it up, removing any diff markers, the first few characters from each line (leaving only file paths), and any non-gcc related files that may have slipped in. Be sure to add a leading / to each file, giving it an absolute filesystem path.

At this point, you need to get all the files into an independent directory structure. You could do it with a find but I opted for tar:

tar cvf gcc421.tar -T gcc_manifest

Note that if you didn’t want to go through the effort of making a package, this tar file could be deployed to other servers using the -P option. This approach is effective but lacks some tracability and control.

tar xvPf gcc421.tar

To make a package, clone danrue/oneoff-pkg-create. Expand the tar file, create a manifest_template (follow the example), and run build-pkg.sh to bundle the files and manifest into a pkg.