On source trees¶
Over the past few weeks I’ve seen some seriously ugly build systems in use, from orphaned post-build or post-clean files to missed rebuilds and much worse. I want to run through a few simple rules, and hopefully highlight some points that will make it easier for users to actually use your software.
The tools¶
Firstly unless you have some really good reason not to use automake then you shouldn’t be hacking up your own makefiles. On top of that unless you have a really good reason to override the implicit rules you should not do so, and the “good reason” needs to be spelled out fully in comments around the rules in question. All too often people define their own rules and fail to take in to account what happens when somebody tries to use a cross compiler or run out of tree builds, automake takes care of this for you if used correctly.
Also, you probably can not use built tools during the build, if you really need to then give some deep consideration to how you are doing it. For example, you may need to build a special binary for the configuration platform to cope with cross-compiles. In practise it is normally not necessary to run built tools during the build, it is more likely the result of not planning the build adequately. In most circumstances it is the result of attempting to squeeze the package in to a build which needs redesigning.
You should never call cc/ld/make/etc manually. You should not forcibly override the values of CC/LD/MAKE/etc in makefiles, this is also true of a command’s options like C{,PP,XX}FLAGS/LDFLAGS/etc. This make it incredibly difficult for users to override these settings, especially if they’re duplicated across 20 different makefiles.
The build¶
If your build doesn’t support parallel builds it is broken, there are no circumstances where this isn’t true(although if you honestly believe you’ve found one I’d love to hear about it). It is also broken if you short-circuit parallelisation in any way during sections or the whole of the build.
On to tree cleaning and there is a wonderfully simple set of explanatory rules embedded in the template files of automake which should give you an idea of where particular files should be cleaned. From ansi2knr.am relating to removal of the ansi2knr support utility:
Why clean and not somewhere else? Not mostlyclean because people usually don’t want to recompile this file. And not distclean because of our informal rule: if make built it, then clean should delete it; if configure built it, then distclean should remove it (and if the maintainer built it, then maintainer-clean should remove it).
The most basic rule is after configuration, build, install and distclean the source tree should be exactly identical to a freshly unpacked tree. And the build tree should be completely empty.
The installation¶
If for some reason you need to manually write a rule to install a file you must make sure it it installs to $(DESTDIR)/. Any installation that tries to write to the live file system is broken, there really are no exceptions to this.
The extras¶
There are also a couple of convenience issues that need mentioning, these can be ignored but many users and packagers appreciate them nonetheless. I’m going to list the two that I appreciate the most below, but like I said the following aren’t rules.
Exuberant Ctags is pretty much standard now, and adding support for it is a really useful addition for many people who will find themselves needing to edit your source. For example, Exuberant Ctags supports many languages and it is trivial, yet very helpful, to include support for building TAGS files for all your sources with it. You must always check the configuration platform to make sure Exuberant Ctags is installed however, because not all tag generators are created equal. To add support for Exuberant Ctags include something like the following contrived example to your Makefile.am:
ETAGS_ARGS = --language-force=Make Makefile.am \
--language-force=Sh $(filter-out %.rb.in, $(bin_SCRIPTS:%=%.in)) \
--language-force=Rb $(filter %.rb.in, $(bin_SCRIPTS:%=%.in))
TAGS_DEPENDENCIES = Makefile.am $(bin_SCRIPTS:%=%.in)
Note
Obviously your fallback variables for when Exuberant Ctags isn’t installed shouldn’t list all the filetypes that won’t will not have tags built for them. Only redefining ETAGS_ARGS and not TAGS_DEPENDENCIES seems to be a common error.
Warning
When testing for Exuberant Ctags don’t just check for filenames, as many systems install the binary with all sorts of different names. For example, the Gentoo box I’m writing this on only installs a binary as /usr/bin/exuberant-ctags where some other systems I use only include it as /usr/local/bin/ctags. Because this is a configuration platform issue it is one of the unusual times where you can actually run the binary to test it during configure runs.
If you don’t plan on writing and including the automake default documentation such as NEWS and README, then use automake’s foreign option don’t just include empty files or templates for files like AUTHORS/NEWS/README/etc. I’m tempted to suggest this is as a rule, but I know a lot of people don’t treat this as seriously as me.
I have to admit that personally I prefer new packages to use the oft-warned GNITS automake option. In the event that you do not wish to use GNITS, at least enable support for std-options in automake. One doesn’t have to particularly like the GNU philosophy on coding standards, but as far as packaging standards go it is a great example to follow.
If any of the comments here don’t make sense to you, or you notice errors in my thinking drop me a mail. None of the rules or comments above are set in stone, and I’m open to suggestions and criticism.
Note
The current situation tends to make me believe there will be a follow-up to this involving writing test frameworks for your package, as many people seem to be falling in to the belief that if a tool is simple it doesn’t need a full test suite and that just isn’t true. So save yourself the pain of another rant from me, and start writing tests :)