<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The Daily Build &#187; software-engineering</title>
	<atom:link href="http://blog.bstpierre.org/tag/software-engineering/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.bstpierre.org</link>
	<description>Software Development, version 3.0</description>
	<lastBuildDate>Fri, 03 Feb 2012 02:59:01 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.4</generator>
		<item>
		<title>An Interesting pid File Race</title>
		<link>http://blog.bstpierre.org/pid-file-race</link>
		<comments>http://blog.bstpierre.org/pid-file-race#comments</comments>
		<pubDate>Wed, 26 May 2010 16:08:50 +0000</pubDate>
		<dc:creator>Brian St. Pierre</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[software-engineering]]></category>

		<guid isPermaLink="false">http://blog.bstpierre.org/?p=305</guid>
		<description><![CDATA[ISC&#8217;s dhcpd uses this code to check for an already-running daemon: /* Read previous pid file. */ if ((i = open (path_dhcpd_pid, O_RDONLY)) &#62;= 0) { status = read (i, pbuf, (sizeof pbuf) - 1); close (i); if (status &#62; 0) { pbuf [status] = 0; pid = atoi (pbuf); /* If the previous server [...]]]></description>
			<content:encoded><![CDATA[<p>ISC&#8217;s dhcpd uses <a href="http://google.com/codesearch/p?hl=en#5KTrgOW2hXs/pub/nslu2/sources/dhcp-3.0.4.tar.gz|9nqObdv7Xcs/dhcp-3.0.4/server/dhcpd.c&amp;q=_PATH_DHCPD_CONF&amp;d=3&amp;l=539">this code</a> to check for an already-running daemon:</p>
<pre>/* Read previous pid file. */
if ((i = open (path_dhcpd_pid, O_RDONLY)) &gt;= 0) {
    status = read (i, pbuf, (sizeof pbuf) - 1);
    close (i);
    if (status &gt; 0) {
        pbuf [status] = 0;
        pid = atoi (pbuf);

        /* If the previous server process is not still running,
           write a new pid file immediately. */
        if (pid &amp;&amp; (pid == getpid() || kill (pid, 0) &lt; 0)) {
            unlink (path_dhcpd_pid);
            if ((i = open (path_dhcpd_pid,
                           O_WRONLY | O_CREAT, 0644)) &gt;= 0) {
                sprintf (pbuf, "%d\n", (int)getpid ());
                write (i, pbuf, strlen (pbuf));
                close (i);
                pidfilewritten = 1;
            }
        } else
            log_fatal ("There's already a DHCP server running.");
    }
}
</pre>
<p>The problem with this strategy is that, if the box dies, there&#8217;s a stale pid file left in /var/run/dhcpd.pid. This wouldn&#8217;t be so bad &#8212; the code above checks [using <code>kill(pid, 0)</code>] to see if there&#8217;s a process running with that pid. But when the box is restarting, there will be a bunch of processes all starting in similar sequence each time. So on one boot, you might see dhcpd with a pid of 1001 and ntpd with a pid of 1002. If the box dies violently (e.g. power cut), the dhcpd pid file will contain 1001. On the second boot, assume ntpd starts first and gets a pid of 1001 and dhcpd is 1002. Now, the <code>kill(pid, 0)</code> will succeed, making it appear that dhcpd is already running, and dhcpd will exit.</p>
<p>How to fix this?</p>
<ol>
<li>Explicitly put the pid file under /tmp. Getting this right is fussy &#8212; make sure you avoid the race conditions associated with creating temp files. Use dhcpd&#8217;s &#8220;-pf&#8221; flag to tell it where to use the pid file. This avoids spurious &#8220;already running&#8221; messages, because dhcpd will never read a pid from an existing pid file. [You could also just remove the /var/run/dhcpd.pid file, but I'd rather explicitly provide the path in my startup script in case some dim bulb decides to change the compiled-in default.]</li>
<li>Be careful in your restart code to kill any existing dhcpd (assuming you really want a new dhcpd), or avoid trying to start a new one (assuming you want to use an already running dhcpd). <code>pgrep(1)</code> and <code>pkill(1)</code> will be useful here.</li>
</ol>
<p>In researching this, I saw this <a href="http://openbsd.monkey.org/misc/200601/msg00735.html">bit of wisdom from Henning Brauer</a>: &#8220;pid files are useless.&#8221;.</p>
<p>I heartily agree&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.bstpierre.org/pid-file-race/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Data vs Code</title>
		<link>http://blog.bstpierre.org/data-vs-code</link>
		<comments>http://blog.bstpierre.org/data-vs-code#comments</comments>
		<pubDate>Fri, 05 Feb 2010 16:08:05 +0000</pubDate>
		<dc:creator>Brian St. Pierre</dc:creator>
				<category><![CDATA[engineering]]></category>
		<category><![CDATA[c-programming]]></category>
		<category><![CDATA[software-engineering]]></category>

		<guid isPermaLink="false">http://blog.bstpierre.org/?p=285</guid>
		<description><![CDATA[I&#8217;ll take an array over a giant switch-case statement any day. The array definition will be more compact and easier to see all at once. Defining actions in an array enforces uniformity. You can put checks in the code to automatically verify that the array definition is complete. (I.e. verify it contains a definition for [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ll take an array over a giant switch-case statement any day.</p>
<ol>
<li>The array definition will be more compact and easier to see all at once.</li>
<li>Defining actions in an array enforces uniformity.</li>
<li>You can put checks in the code to automatically verify that the array definition is complete. (I.e. verify it contains a definition for every item it should have.) Yes, some tools can do this for certain types of switch statements. Using an array-based check is more portable and more foolproof.</li>
</ol>
<p>If you have a switch statement of mostly cut and paste cases, you can probably convert it to an array very easily, and then rewrite the switch statement to look up the value in the array and do whatever thing is supposed to be done, either via function pointers or by using an associated value from the array.</p>
<p>I did this on a horrible switch statement once. Dozens of cases, 80% were nearly identical but the few that weren&#8217;t were awful to untangle. Once I pulled the case bodies into separate functions, put function pointers into a table, and replaced the switch body with a lookup loop it was much cleaner. The code for the odd cases was eventually pushed out (it was a symptom of bad design). The whole exercise enabled another round of changes that allowed the functions for the case bodies to be collapsed back into the table &#8212; we ended up removing an entire unnecessary layer of indirection and made the design much easier to grok.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.bstpierre.org/data-vs-code/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Insist on Automatic Tests</title>
		<link>http://blog.bstpierre.org/insist-on-tests</link>
		<comments>http://blog.bstpierre.org/insist-on-tests#comments</comments>
		<pubDate>Fri, 29 Jan 2010 19:08:08 +0000</pubDate>
		<dc:creator>Brian St. Pierre</dc:creator>
				<category><![CDATA[engineering]]></category>
		<category><![CDATA[software-engineering]]></category>

		<guid isPermaLink="false">http://blog.bstpierre.org/?p=281</guid>
		<description><![CDATA[At some point your team is going to be gone. Not all at once (well, maybe, but in that case you won&#8217;t care), but over time turnover will completely replace your team. If you are the manager, and you outlast the team, you&#8217;re going to pay for low quality code when you try to bring [...]]]></description>
			<content:encoded><![CDATA[<p>At some point your team is going to be gone. Not all at once (well, maybe, but in that case you won&#8217;t care), but over time turnover will completely replace your team.</p>
<p>If you are the manager, and you outlast the team, you&#8217;re going to pay for low quality code when you try to bring in new people and they end up breaking everything becuase there&#8217;s no tests to check their bug fixes and/or enhancements.</p>
<p>If you are a surviving member of the team, you&#8217;re going to pay with huge headaches because you&#8217;ve got to fix code where you have no idea what might be broken as a result.</p>
<p><strong>Change is scary when you don&#8217;t have automatic tests.</strong> Just suck it up and write the tests!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.bstpierre.org/insist-on-tests/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>9 &#8220;Must-Have&#8221; Tools for Software Teams</title>
		<link>http://blog.bstpierre.org/must-have-tools-software-teams</link>
		<comments>http://blog.bstpierre.org/must-have-tools-software-teams#comments</comments>
		<pubDate>Mon, 18 Jan 2010 16:06:38 +0000</pubDate>
		<dc:creator>Brian St. Pierre</dc:creator>
				<category><![CDATA[tools]]></category>
		<category><![CDATA[software-engineering]]></category>
		<category><![CDATA[tool]]></category>

		<guid isPermaLink="false">http://blog.bstpierre.org/?p=254</guid>
		<description><![CDATA[The items below are useful systems based on my experience working with a bunch of different software teams at a handful of companies over the past decade-plus. I haven&#8217;t bothered to list things like compilers, interpreters, libraries, etc. If you don&#8217;t have those, you aren&#8217;t making software&#8230; Source control. This almost belongs in the &#8220;if [...]]]></description>
			<content:encoded><![CDATA[<p>The items below are useful systems based on my experience working with a bunch of different software teams at a handful of companies over the past decade-plus. I haven&#8217;t bothered to list things like compilers, interpreters, libraries, etc. If you don&#8217;t have those, you aren&#8217;t making software&#8230;</p>
<ol>
<li><strong>Source control.</strong> This almost belongs in the &#8220;if you don&#8217;t have it, you aren&#8217;t making software&#8221; category. There are so many free and simple to use tools that it is ridiculous to not use source control. Pick one of: subversion, git, or any of the dozens of other free tools and use it. I guess I&#8217;d say &#8220;if you don&#8217;t have it, you are making a mess&#8221;.</li>
<li><strong>Bug/issue tracker</strong>. Trac is a decent tool for keeping tabs on development tasks and bugs. Bugzilla is ok too. If you have a budget, there is an apparently infinite set of commercial systems available of varying quality. Almost anything is better than a list of scribbles on your whiteboard.</li>
<li><strong>Backup server.</strong> You <em>can</em> do software without it, but the odds are against you lasting long.</li>
<li><strong>Build system.</strong> Automated nightly/continuous builds are awesome. Whether you DIY, install something free like hudson, or purchase a commercial system, this is a key piece of making sure that the software maintains at least a minimum level of quality (i.e. it is always buildable). After having worked on a couple of teams that didn&#8217;t have such a system, and the build was always broken, I would never work without it again.</li>
<li><strong>IM / Jabber</strong>. Especially with a conference server where the rooms are archived and available via the web. Searchable is nice, but making them available where they can be grepped isn&#8217;t bad either. I didn&#8217;t become convinced of the value here until last summer.It sounds like an extra distraction and sometimes it can be, but you can turn it off when you&#8217;re heads-down coding. And it has the potential to <em>reduce</em> the number of interruptions from people walking into your office with questions that could have been answered in an IM. It&#8217;s lighter weight than email and rooms are broadcast by nature so you don&#8217;t have to spam a huge list of people to find the answer you&#8217;re looking for.</li>
<li><strong>Email lists</strong>. Must have web-browsable archives; the list without this has much less value. Search would be a nice bonus, though I haven&#8217;t seen it done well. This lets teams communicate a bit more formally than IM and provides a record of certain discussions and decisions.</li>
<li><strong>FTP server.</strong> Bonus points for a TFTP server. Maybe it&#8217;s because of the nature of embedded software, but every team I&#8217;ve been on has always had to fling around large files and images. Email is horribly inefficient for this. Also, most of the products I&#8217;ve worked on needed an FTP (or TFTP) server to boot from. You&#8217;re likely to install something on your development machine, which is fine, but it&#8217;s convenient to have a central team/company internal server so you can just tell someone that a file is in your public directory on &#8220;the ftp server&#8221;. Microsoft shops and folks that don&#8217;t need to boot via FTP can probably get away with samba shares.</li>
<li><strong>Doc server.</strong> Wiki is probably the best way to go if your team doesn&#8217;t <em>have</em> to produce overly-formal documentation. Wikis and formal document control systems that I&#8217;ve used have had horrible search, which sucks but I haven&#8217;t found a great solution. In the past I&#8217;ve done this with a combination of a formal doc tool plus a blog for the informal &#8220;howto&#8221; kind of notes that are always needed.</li>
<li><strong>Code review.</strong> I can&#8217;t say I&#8217;ve worked anywhere that had a dedicated code review tool. However, when all of the development machines are on NFS so that everyone has a view of your workspace, IM fits the bill reasonably well: post a review request to the chat room with the path to your changes and get an ad hoc on the spot code review. With some discipline and a supportive culture this works very smoothly. (This arrangement could probably be done with an internal pastebin, which I haven&#8217;t listed here as must-have since I haven&#8217;t really seen it used.)</li>
</ol>
<p>What would you add to this list? Any other tools or systems that, if missing, would make you think twice about taking a job?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.bstpierre.org/must-have-tools-software-teams/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>One Simple Step for Avoiding Shallow Reviews</title>
		<link>http://blog.bstpierre.org/one-simple-step-for-avoiding-shallow-reviews</link>
		<comments>http://blog.bstpierre.org/one-simple-step-for-avoiding-shallow-reviews#comments</comments>
		<pubDate>Wed, 25 Nov 2009 13:55:55 +0000</pubDate>
		<dc:creator>Brian St. Pierre</dc:creator>
				<category><![CDATA[reviews]]></category>
		<category><![CDATA[codereview]]></category>
		<category><![CDATA[process]]></category>
		<category><![CDATA[software-engineering]]></category>

		<guid isPermaLink="false">http://blog.bstpierre.org/?p=209</guid>
		<description><![CDATA[It's your job as a reviewer to find as many defects as possible. If you're not finding defects, you're wasting time.]]></description>
			<content:encoded><![CDATA[<p>We&#8217;ve all been guilty of giving a shallow review: &#8220;Looks ok.&#8221;</p>
<p>Given typical defect densities, any non-trivial design or code is going to contain some errors. Even seemingly trivial maintenance fixes are likely to be defective.</p>
<p><strong>It&#8217;s your job as a reviewer to find as many of these defects as possible. </strong>If you&#8217;re not finding defects, you&#8217;re wasting your time on reviews.</p>
<p>That &#8220;one simple step&#8221;? Remind yourself that there are almost certainly defects in the work product you&#8217;re reviewing, and then find them. It&#8217;s all about attitude.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.bstpierre.org/one-simple-step-for-avoiding-shallow-reviews/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Who Else Wants Better Short Term Memory?</title>
		<link>http://blog.bstpierre.org/who-else-wants-better-short-term-memory</link>
		<comments>http://blog.bstpierre.org/who-else-wants-better-short-term-memory#comments</comments>
		<pubDate>Thu, 12 Nov 2009 13:13:24 +0000</pubDate>
		<dc:creator>Brian St. Pierre</dc:creator>
				<category><![CDATA[engineering]]></category>
		<category><![CDATA[process]]></category>
		<category><![CDATA[codereview]]></category>
		<category><![CDATA[coding-standard]]></category>
		<category><![CDATA[software-engineering]]></category>

		<guid isPermaLink="false">http://blog.bstpierre.org/?p=197</guid>
		<description><![CDATA[In &#8220;Talent is Overrated&#8221;, Geoff Colvin at one point discusses how superstars in many fields use the memory technique of &#8220;chunking&#8221; to boost their short term memory. His simple example is the 13-letter word &#8220;lexicographer&#8221;. To you and I (assuming you speak English and have a decent vocabulary), it is easy to remember. We don&#8217;t [...]]]></description>
			<content:encoded><![CDATA[<p>In <a title="&quot;Talent is Overrated&quot; by Geoff Colvin -- on Amazon" href="http://www.amazon.com/dp/1591842247/?tag=bstpierreorg-20">&#8220;Talent is Overrated&#8221;</a>, Geoff Colvin at one point discusses how superstars in many fields use the memory technique of &#8220;<a title="More about chunking on wikipedia." href="http://en.wikipedia.org/wiki/Chunking_(psychology)">chunking</a>&#8221; to boost their short term memory.</p>
<p>His simple example is the 13-letter word &#8220;lexicographer&#8221;. To you and I (assuming you speak English and have a decent vocabulary), it is easy to remember. We don&#8217;t have to remember 13 letters, we just remember the whole chunk. But when presented with &#8220;trgdpxhdewfwm&#8221; for 3 seconds, you probably can&#8217;t remember more than half a dozen letters.</p>
<p>Another example is that chess masters can recall board positions after being shown a chess board with pieces on it for just a few seconds. They do this by chunking sets of pieces together &#8212; almost like &#8220;words&#8221; &#8212; whereas novices will try to remember individual pieces (&#8220;letters&#8221;).</p>
<p>It struck me that programmers do the same thing when reading and writing code.</p>
<p>The coding standard helps us, by telling us where the chunks are and how to draw the boundaries between chunks.</p>
<p>If you have a coding standard.</p>
<p>And apply it consistently.</p>
<p><strong>When you choose names at random, you destroy your short term memory.</strong> You become a crappy programmer, and you drag everyone around you down too.</p>
<p>Quick example in C. Assume you&#8217;re writing a small module for checking environmental status.</p>
<pre style="padding-left: 30px;">BOOL isOverTemp();
BOOL isUnderTemp();

int GetCurTemperature();

BOOL env_isOverVoltage();
BOOL env_isUnderVoltage();</pre>
<p>Anyone writing this pile of gibberish should be <span style="text-decoration: line-through;">fired</span> excommunicated.</p>
<p>Why?</p>
<p>For starters, I just wrote it, and I can&#8217;t now remember which was camel case and which was underscored. Also: which one was abbreviated?</p>
<p>Before you object that this is a contrived example, two points: (1) yes, it is contrived, that&#8217;s the point of an example, and (2) I have worked with far worse on an almost daily basis &#8212; the example above is fairly tame.</p>
<p>On the other hand, if you know the coding standard has some simple rules &#8212; <strong>and they are followed uniformly</strong> &#8212; you can easily remember the function names.</p>
<ol>
<li>Initial 2-3 letter module prefix (&#8220;env&#8221; for this example).</li>
<li>All functions are lowercase with underscores.</li>
<li>No abbreviations.</li>
</ol>
<p>Then we have:</p>
<pre style="padding-left: 30px;">BOOL env_is_over_temperature();
BOOL env_is_under_temperature();

int env_get_cur_temperature();

BOOL env_is_over_voltage();
BOOL env_is_under_voltage();</pre>
<p>Now, when you&#8217;re writing, reviewing, or maintaining code, you don&#8217;t need to constantly refer to the header or documentation to get it right. A simple three-line coding standard just boosted your memory capacity by over 643%.</p>
<p>(In the interest of full disclosure: I made that number up.)</p>
<p>I realize that implementing even this simple three line standard is controversial because all the camel case folks are pulling out big sticks and the underscore people are grabbing rocks. To which I say: just flip a coin and enjoy the extra brain power. Adopt a three-line standard, <strong>follow it</strong>, and save the curly-brace debate for the next major coding standard revision.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.bstpierre.org/who-else-wants-better-short-term-memory/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>3 Easy Ways to Stick to a Coding Standard</title>
		<link>http://blog.bstpierre.org/3-easy-ways-to-stick-to-a-coding-standard</link>
		<comments>http://blog.bstpierre.org/3-easy-ways-to-stick-to-a-coding-standard#comments</comments>
		<pubDate>Tue, 25 Aug 2009 18:40:58 +0000</pubDate>
		<dc:creator>Brian St. Pierre</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[codereview]]></category>
		<category><![CDATA[software-engineering]]></category>
		<category><![CDATA[tool]]></category>

		<guid isPermaLink="false">http://blog.bstpierre.org/?p=192</guid>
		<description><![CDATA[When you&#8217;re writing python, you don&#8217;t need a lot of debate over the minutiae of most coding standards. PEP 8 does that for you. Even better, there are some tools that make it really easy to stick to the standard. Why do this? Well, for one thing it makes code reviews easier when everyone follows [...]]]></description>
			<content:encoded><![CDATA[<p>When you&#8217;re writing python, you don&#8217;t need a lot of debate over the minutiae of most coding standards. <a href="http://www.python.org/dev/peps/pep-0008/">PEP 8</a> does that for you. Even better, there are some tools that make it really easy to stick to the standard.</p>
<p>Why do this? Well, for one thing it makes code reviews easier when everyone follows the same conventions. It also makes maintenance easier.</p>
<ol>
<li><a href="http://github.com/cburroughs/pep8.py/tree/master">pep8.py</a> is a style checker that enforces the rules of PEP 8. The &#8220;official home&#8221; (?) <a href="http://svn.browsershots.org/trunk/devtools/pep8/pep8.py">at browsershots.org </a>was dead as I was writing this. (Thanks GitHub!) Run pep8.py on your code and it will tell you where you&#8217;ve drifted from the standard.</li>
<li><a href="http://www.logilab.org/857">pylint</a> is lint for python. It provides more functionality than pep8.py, but is not a strict superset. (pep8.py is pickier about whitespace issues.) Pylint is also configurable to enforce various naming rules. Like most lints, the SNR is pretty low, but you can turn off most of the noise and get a reasonable signal for the things you want to check.</li>
<li>Subversion (as well as most other tools) can be configured to run a script every time you check in code. Run one or both of the above tools in the pre-commit hook and bad code will be rejected. (I&#8217;d be wary of doing this with pylint unless you&#8217;ve got the categories of &#8220;noisy&#8221; warnings turned off.) I don&#8217;t have anything cookbook for this yet, but I&#8217;m working on it&#8230;</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://blog.bstpierre.org/3-easy-ways-to-stick-to-a-coding-standard/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Makefiles are Software Too</title>
		<link>http://blog.bstpierre.org/makefiles-are-software-too</link>
		<comments>http://blog.bstpierre.org/makefiles-are-software-too#comments</comments>
		<pubDate>Tue, 14 Apr 2009 03:17:48 +0000</pubDate>
		<dc:creator>Brian St. Pierre</dc:creator>
				<category><![CDATA[engineering]]></category>
		<category><![CDATA[software-engineering]]></category>
		<category><![CDATA[tool]]></category>

		<guid isPermaLink="false">http://blog.bstpierre.org/?p=173</guid>
		<description><![CDATA[This post was inspired by recent experience with some horrible build scripts from the open source world &#8212; but I&#8217;ve seen enough in-house badness over the years that I wanted to establish some basic parameters for build scripts. This is a really broad way to divide the world, but I see two important categories of [...]]]></description>
			<content:encoded><![CDATA[<p>This post was inspired by recent experience with some horrible build scripts from the open source world &mdash; but I&#8217;ve seen enough in-house badness over the years that I wanted to establish some basic parameters for build scripts.</p>
<p>This is a really broad way to divide the world, but I see two important categories of build scripts. (By &#8220;build script&#8221; I mean Makefiles, SConsfiles, Ant files, and their ilk).</p>
<ol>
<li>Build scripts intended for in-house use, never seen by outsiders.</li>
<li>Build scripts that you distribute to external users.</li>
</ol>
<p>Both sets of build scripts are important. Let&#8217;s consider the build script (or Makefile system, or whatever you&#8217;re using) as a software system independent of the software that is being built. Its primary requirement is to reliably convert your source code into an executable. Any decent build script has numerous other requirements, most of which are probably implied. I have never seen a written requirement for the numerous build scripts I&#8217;ve written. I have only rarely heard them discussed &mdash; and never actually posed as &#8220;requirements&#8221;.</p>
<p>I have, always taken the following meta-requirements for granted. Based on my experience with some fairly awful build scripts, I guess these aren&#8217;t universally acknowledged.</p>
<ul>
<li>The build script should build all the &#8220;normal&#8221; executables with a single command.</li>
<li>The build script must encapsulate all environment variables within the script. (This is a corollary of the above.)</li>
<li>The build script should not unnecessarily rebuild source code in a directory tree that has previously been built. (This is <tt>make</tt>&#8216;s raison d&#8217;etre.)</li>
<li>The build script should be documented. It doesn&#8217;t have to be elaborate, but a five-line comment at the top of the script describing the available command-line variables would be nice.</li>
<li><tt>make clean</tt> or its equivalent must work reliably.</li>
<li>It should rarely be necessary to run <tt>make clean</tt>.</li>
<li>Bonus: the build should be parallelizable, to be able to take advantage of multicore machines and/or distributed builds.</li>
</ul>
<p>Back to those two categories. If you screw up an in-house build script, it&#8217;s primarily your team that&#8217;s going to suffer. I&#8217;m not aware of any bugs from SQA or Customers on projects I&#8217;ve been on that were traced back to a build script, but I can see where it could happen. Mainly what I&#8217;ve seen is developers habitually wasting time rebuilding source that should not need to be rebuilt. The worst offender in this respect was a build script that forced a &#8220;make clean&#8221; at the beginning of every build. In the immortal words of Dave Barry, I&#8217;m not making this up. Really.</p>
<p>(Actually, I think it was even worse when I was dealing with a build script that required a &#8220;make clean&#8221; every time around but didn&#8217;t have it coded into the script!)</p>
<p>I can&#8217;t say I have a completely clean conscience in this area: I wrote a big pile of Makefiles for a past employer in which I unknowingly used features (bugs?) of a specific version of GNU Make that were &#8220;fixed&#8221; in a subsequent version. As time went on it became (a) a much bigger task to fix the Makefile code that used the &#8220;feature&#8221; and (b) harder to keep the specific version of GNU Make that worked with the Makefiles! I imagine they&#8217;re still stuck with this situation&#8230; sorry guys.</p>
<p>In the second category, when you toss a slapped-together build script to your unsuspecting users you do all of human society a disservice. Now they are not only wasting their time fighting with a bad build script, but they often have the disadvantage of being unable to contact the author directly for support or commiserate with other experienced users of the system.</p>
<p>So do us all a favor: if you don&#8217;t know what you&#8217;re doing when you start to write your next build script, please ask for help. Otherwise we&#8217;ll have to resort to some sort of professional licensing scheme for build script authors.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.bstpierre.org/makefiles-are-software-too/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

