pkgsrc on SmartOS - fixing broken builds
This is the second in a series of posts looking at pkgsrc on SmartOS. In the previous post I got us up and running with building packages. This post will focus on what to do when the build fails.
Currently pkgsrc is able to build around 9,500 packages on SmartOS, however pkgsrc carries over 12,000 packages in total, so there is a reasonable chance that you will come across a package which will not produce a binary package.
Let’s have a look at some of the most common failure modes and the facilities pkgsrc provides for them to be fixed.
Adjusting the environment
Probably the most common failures on Solaris are those caused by incorrect compiler or linker flags, where the author of the software has not taken into account differences across Unix platforms. Examples include:
-
the usage of
u_int*
types (e.g.u_int32_t
) instead of the portableuint*
C99 types (e.g.uint32_t
). -
missing
-lsocket -lnsl
when using the socket interface.
pkgsrc provides an easy way to pass CFLAGS
, LDFLAGS
and other
common environment variables to the build, and these are often enough to
resolve such issues.
Taking net/nsd
as an example:
If we edit the Makefile and add the following line below CONFIGURE_ARGS
:
then a rebuild resolves the problem and results in a binary package:
By using CFLAGS.SunOS
rather than the global CFLAGS
this is only performed
on systems where uname
is SunOS
.
We can resolve missing libraries in a similar way, taking net/rootprobe
as an
example:
Add the following to the Makefile:
and hey presto, out comes a binary package:
Not all packages can be fixed directly like this, only those which obey the
normal ${CC}
and ${LD}
environment variables, as pkgsrc creates wrappers
for those commands where it can insert these alterations. For packages which
directly call e.g. gcc
, some additional digging will be required to see how
the arguments can be passed.
Taking net/3proxy
as an example, the build fails with missing socket
libraries:
but adding LDFLAGS.SunOS+= -lsocket -lnsl
to the Makefile as before does not
resolve the problem. Delving further into the Makefile we can see that the
build is driven from a custom Makefile rather than through autoconf/automake:
and it is there we will need to perform the changes. First, let’s find the
work area, which we can get from the WRKSRC
variable:
Picking out the relevant bits from Makefile.unix
:
Here, the author has provided no functionality for adding to the environment, and has instead chosen to hardcode a specific compiler and build flags, significantly reducing the portability of their software - good luck to Clang/LLVM or SunStudio users!
If the author had provided a way in to add to these flags, for example:
then we could have fixed that in the main pkgsrc Makefile
with
or similar, however we now have no choice but to directly edit Makefile.unix
.
Thankfully, pkgsrc provides a couple of ways to easily do this, which we will
look at over the next few sections.
The substitution framework
The subst
framework allows basic editing of files within the work area. I
will show the solution for the above problem, and then discuss it:
Firstly, we need to limit this to SunOS systems, else we would break platforms
which do not have libsocket
or libnsl
. Including ../../mk/bsd.prefs.mk
gives us access to the OPSYS
variable so we can test the platform we are
running on.
Next we set up the substitution framework:
-
SUBST_CLASSES
creates a new class, which I have namedlibs
. This class name is then appended to the remainingSUBST_*
variables to assign them to that class. -
SUBST_STAGE
defines the make stage when the substitution will be run, and should almost always bepre-build
, to ensure it is done after any configuration stage which could rewrite files itself. -
SUBST_MESSAGE
is optional, and is simply a line which will be printed to the user when the substitution takes places. -
SUBST_FILES
is a list of files the substitution operates on. -
SUBST_SED
is the actual substitution, in the form of ased(1)
operation. Here we append-lsocket -lnsl
to any line beginning withLDFLAGS
. Note$$
is required to getmake
to escape a$
.
Two other subst
features you may want are:
-
SUBST_VARS.foo= VARNAME
is a shortcut for the-e 's,@VARNAME@,${VARNAME},g'
operation, common with autoconf-based packages. -
SUBST_FILTER_CMD.foo= <cmd>
allows you to run an arbitrary command, rather than the default ofsed
.
For more information, see the implementation in pkgsrc/mk/subst.mk
.
## Patches
While CFLAGS
, LDFLAGS
and the substitution framework allow for simple
one-liner fixes, often more significant changes are required, and in those
cases the only sensible option is to create patches. Thankfully, there are
some tools provided in pkgsrc to make this a relatively easy process.
First, let’s take a broken package, devel/bglibs
:
which comes from the following function:
Unfortunately, while SmartOS provides the TCP_CORK
flag, it does not
understand SOL_TCP
, and so we need to modify the test and add an additional
one.
Before doing this, we should install the pkgtools/pkgdiff
package, which
contains a pkgvi
wrapper. This allows you to edit a file, and if you make
changes, it will save the resulting diff in the pkgsrc patches
directory
ready for use. Much easier than delving into the work area and creating
patches yourself.
Now edit the offending file:
This is what I changed the function to:
This still isn’t ideal, and would be better converted to a proper autoconf test where we can test functionality instead of definitions, but it will do for example purposes.
After writing, you should get output such as:
and running the pkgdiff
command will show you the diff.
The final step is storing the diff into a patch file, and that is accomplished with:
The mkpatches
command creates a new file in the patches
directory called
patch-net_cork.c
, and the bmake mps
(short for the makepatchsum
target)
regenerates the distinfo
file with the correct checksum for that patch.
Finally, you can rebuild
and, hey presto .. another failure!
Now that you know how to fix this, I’ll leave it to you to come up with a patch ;)
One final word on this, you will perhaps notice during the build some warnings:
These files are left by mkpatches
, and to remove them you can run
Also note that both patch-ab
and patch-ac
changed, even though we only
modified the net/cork.c
file. This is due to differences in diff(1)
output, and is ultimately harmless.
Summary
pkgsrc provides a number of ways to fix up broken software:
-
CFLAGS
,LDFLAGS
, and other environment variables. -
The
subst.mk
framework for simple file changes. -
Patch files for more substantial changes.
The important thing, after using any of these features, is to feed back your changes so that we can integrate them into pkgsrc and everyone can benefit. Probably the easiest way to do that is simply raise an issue against our GitHub pkgsrc fork, and either myself or Filip can commit the patch upstream.
All Posts
- 16 Jul 2015 » Reducing RAM usage in pkgin
- 03 Mar 2015 » pkgsrc-2014Q4: LTS, signed packages, and more
- 06 Oct 2014 » Building packages at scale
- 04 Dec 2013 » A node.js-powered 8-bit CPU - part four
- 03 Dec 2013 » A node.js-powered 8-bit CPU - part three
- 02 Dec 2013 » A node.js-powered 8-bit CPU - part two
- 01 Dec 2013 » A node.js-powered 8-bit CPU - part one
- 21 Nov 2013 » MDB support for Go
- 30 Jul 2013 » What's new in pkgsrc-2013Q2
- 24 Jul 2013 » Distributed chrooted pkgsrc bulk builds
- 07 Jun 2013 » pkgsrc on SmartOS - creating new packages
- 15 Apr 2013 » What's new in pkgsrc-2013Q1
- 19 Mar 2013 » Installing SVR4 packages on SmartOS
- 27 Feb 2013 » SmartOS is Not GNU/Linux
- 18 Feb 2013 » SmartOS development preview dataset
- 17 Jan 2013 » pkgsrc on SmartOS - fixing broken builds
- 15 Jan 2013 » pkgsrc on SmartOS - zone creation and basic builds
- 10 Jan 2013 » Multi-architecture package support in SmartOS
- 09 Jan 2013 » Solaris portability - cfmakeraw()
- 08 Jan 2013 » Solaris portability - flock()
- 06 Jan 2013 » pkgsrc-2012Q4 illumos packages now available
- 23 Nov 2012 » SmartOS and the global zone
- 24 Oct 2012 » Setting up Samba on SmartOS
- 10 Oct 2012 » pkgsrc-2012Q3 packages for illumos
- 23 Aug 2012 » Creating local SmartOS packages
- 10 Jul 2012 » 7,000 binary packages for OSX Lion
- 09 Jul 2012 » 9,000 packages for SmartOS and illumos
- 07 May 2012 » Goodbye Oracle, Hello Joyent!
- 13 Apr 2012 » SmartOS global zone tweaks
- 12 Apr 2012 » Automated VirtualBox SmartOS installs
- 30 Mar 2012 » iptables script for Debian / Ubuntu
- 20 Feb 2012 » New site design
- 11 Jan 2012 » Set up anonymous FTP upload on Oracle Linux
- 09 Jan 2012 » Kickstart Oracle Linux in VirtualBox
- 09 Jan 2012 » Kickstart Oracle Linux from Ubuntu
- 22 Dec 2011 » Last day at MySQL
- 15 Dec 2011 » Installing OpenBSD with softraid
- 21 Sep 2011 » Create VirtualBox VM from the command line
- 14 Sep 2011 » Creating chroots for fun and MySQL testing
- 30 Jun 2011 » Graphing memory usage during an MTR run
- 29 Jun 2011 » Fix input box keybindings in Firefox
- 24 Jun 2011 » How to lose weight
- 23 Jun 2011 » How to fix stdio buffering
- 13 Jun 2011 » Serving multiple DNS search domains in IOS DHCP
- 13 Jun 2011 » Fix Firefox URL double click behaviour
- 20 Apr 2011 » SSH via HTTP proxy in OSX
- 09 Nov 2010 » How to build MySQL releases
- 29 Apr 2010 » 'apt-get' and 5,000 packages for Solaris10/x86
- 16 Sep 2009 » ZFS and NFS vs OSX
- 12 Sep 2009 » pkgsrc on Solaris
- 09 Dec 2008 » Jumpstart from OSX
- 31 Dec 2007 » Set up local caching DNS server on OSX 10.4