Automatically Simple Since 2002
24 June 2014
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
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.
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.