<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/rss2full.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><rss 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" version="2.0">

<channel>
	<title>View within the Urban Jungle</title>
	
	<link>http://blogs.designingpatterns.com/urban-jungle</link>
	<description>Discussing nitty gritty software development details that Tony finds interesting</description>
	<pubDate>Thu, 25 Sep 2008 00:56:53 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://blogs.designingpatterns.com/urban-jungle/feed/" type="application/rss+xml" /><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Fblogs.designingpatterns.com%2Furban-jungle%2Ffeed%2F" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Fblogs.designingpatterns.com%2Furban-jungle%2Ffeed%2F" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://feeds.my.aol.com/add.jsp?url=http%3A%2F%2Fblogs.designingpatterns.com%2Furban-jungle%2Ffeed%2F" src="http://o.aolcdn.com/favorites.my.aol.com/webmaster/ffclient/webroot/locale/en-US/images/myAOLButtonSmall.gif">Subscribe with My AOL</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.bloglines.com/sub/http://blogs.designingpatterns.com/urban-jungle/feed/" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Fblogs.designingpatterns.com%2Furban-jungle%2Ffeed%2F" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://fusion.google.com/add?feedurl=http%3A%2F%2Fblogs.designingpatterns.com%2Furban-jungle%2Ffeed%2F" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Fblogs.designingpatterns.com%2Furban-jungle%2Ffeed%2F" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><item>
		<title>RDoc 2.2.1 Released</title>
		<link>http://blogs.designingpatterns.com/urban-jungle/2008/09/24/rdoc-221-released/</link>
		<comments>http://blogs.designingpatterns.com/urban-jungle/2008/09/24/rdoc-221-released/#comments</comments>
		<pubDate>Thu, 25 Sep 2008 00:56:53 +0000</pubDate>
		<dc:creator>tony</dc:creator>
		
		<category><![CDATA[rdoc]]></category>

		<category><![CDATA[ruby]]></category>

		<category><![CDATA[Add new tag]]></category>

		<category><![CDATA[documentation]]></category>

		<category><![CDATA[documentation generator]]></category>

		<category><![CDATA[software documentation]]></category>

		<guid isPermaLink="false">http://blogs.designingpatterns.com/urban-jungle/?p=23</guid>
		<description><![CDATA[RDoc 2.2.1 is available!  It can be downloaded here or through the gem system.  We are releasing RDoc again, so soon after the RDoc 2.2.0 release, in order to fix some bugs and include some community patches that were overlooked before the 2.2.0 release.  These changes needed to be checked-in immediately as [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://rdoc.rubyforge.org/">RDoc 2.2.1</a> is available!  It can be downloaded <a href="http://rubyforge.org/frs/?group_id=627">here</a> or through the <code>gem</code> system.  We are releasing RDoc again, so soon after the <a href="http://blogs.designingpatterns.com/urban-jungle/2008/09/19/rdoc-220-released/">RDoc 2.2.0 release</a>, in order to fix some bugs and include some community patches that were overlooked before the 2.2.0 release.  These <a href="http://rdoc.rubyforge.org/files/History_txt.html">changes</a> needed to be checked-in immediately as RDoc 2.2.1 will be part of the upcoming Ruby 1.9.1 release.  This RDoc release includes a patch by Hugh Sasse that provides basic support for parsing Perl files for <a href="http://perldoc.perl.org/perlpod.html">POD documentation</a>.  Additionally, <a href="http://rdoc.rubyforge.org/files/RI_txt.html">ri</a> will display the values of constants again, which has been broken for a few releases.  Also, <a href="http://rdoc.rubyforge.org/files/RI_txt.html">ri</a> <b>finally</b> should resolve methods inherited from a parent class correctly (i.e., <code>ri File.read</code>).  The (hopefully) last bug with this was in the documentation generation system, however, so a machine&#8217;s <code>ri</code> documentation will need to be rebuilt in order for this to work.  The <code>RubyGems</code> documentation can be rebuilt by running</p>
<pre>
gem rdoc --all
</pre>
<p>In order to rebuild the Ruby library documentation, <a href="http://www.ruby-lang.org/en/downloads/">download the source code</a> and run</p>
<pre>
rdoc --all --ri --op new_ri_docs
</pre>
<p>Then, replace the Ruby system <code>ri</code> directory, which can be found by running</p>
<pre>
ri --no-standard-docs --system --list-doc-dirs
</pre>
<p>with the <code>new_ri_docs</code> directory.  As this release is slated to ship with Ruby 1.9.1, we would love to hear about any issues so that we can fix them quickly.</p>
<div class="addthis"><a href="http://www.addthis.com/bookmark.php" onclick="window.open('http://www.addthis.com/bookmark.php?pub=designingpatterns&amp;url=http%3A%2F%2Fblogs.designingpatterns.com%2Furban-jungle%2F2008%2F09%2F24%2Frdoc-221-released%2F&amp;title=RDoc+2.2.1+Released', 'addthis', 'scrollbars=yes,menubar=no,width=620,height=520,resizable=yes,toolbar=no,location=no,status=no'); return false;" title="Bookmark using any bookmark manager!" target="_blank"><img src="http://s3.addthis.com/button1-bm.gif" width="125" height="16" border="0" /></a></div><div class="feedflare">
<a href="http://feeds.feedburner.com/~f/ViewWithinTheUrbanJungle?a=EJUgL"><img src="http://feeds.feedburner.com/~f/ViewWithinTheUrbanJungle?i=EJUgL" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blogs.designingpatterns.com/urban-jungle/2008/09/24/rdoc-221-released/feed/</wfw:commentRss>
		</item>
		<item>
		<title>RDoc 2.2.0 Released</title>
		<link>http://blogs.designingpatterns.com/urban-jungle/2008/09/19/rdoc-220-released/</link>
		<comments>http://blogs.designingpatterns.com/urban-jungle/2008/09/19/rdoc-220-released/#comments</comments>
		<pubDate>Fri, 19 Sep 2008 23:02:16 +0000</pubDate>
		<dc:creator>tony</dc:creator>
		
		<category><![CDATA[rdoc]]></category>

		<category><![CDATA[ruby]]></category>

		<category><![CDATA[documentation]]></category>

		<category><![CDATA[documentation generator]]></category>

		<category><![CDATA[hanna]]></category>

		<category><![CDATA[rdoc template]]></category>

		<category><![CDATA[software documentation]]></category>

		<guid isPermaLink="false">http://blogs.designingpatterns.com/urban-jungle/?p=22</guid>
		<description><![CDATA[RDoc 2.2.0 is available!  It can be downloaded here or through the gem system.  This release is the result of work by RDoc&#8217;s developers and by the community, through both making suggestions and submitting patches.  It is intended to provide a very stable cut of the 2.x functionality and also to fix [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://rdoc.rubyforge.org/">RDoc 2.2.0</a> is available!  It can be downloaded <a href="http://rubyforge.org/frs/?group_id=627">here</a> or through the <code>gem</code> system.  This release is the result of work by <a href="http://rubyforge.org/project/memberlist.php?group_id=627">RDoc&#8217;s developers</a> and by the community, through both making suggestions and submitting patches.  It is intended to provide a very stable cut of the 2.x functionality and also to fix several bugs that have lingered since the 1.x series.  This version&#8217;s unit tests cover a much larger range of functionality than any prior version&#8217;s tests, although the tests’ coverage still is far smaller than it should be.  I believe that this is the most reliable version yet.  In addition to bug fixes, this release includes several enhancements.  While the <a href="http://rdoc.rubyforge.org/files/History_txt.html">release notes</a> list all of these, I am going to highlight a few of them.</p>
<p>A number of fixes and small enhancements were made to the template system.  All built-in HTML templates now generate strict, valid XHTML.  All of the bugs introduced during the switch to ERB templates in RDoc 2.0.0 have been fixed.  In addition, this release provides basic support for creating HTML templates that do not use frames.  The built-in <code>frameless</code> template is an example.  3rd-party templates also now are supported more smoothly.  A template can be installed as a gem, and RDoc will find it with its <code>-T</code> command-line option.  The beautiful <a href="http://github.com/mislav/hanna/tree/master">Hanna template</a> is such a 3rd-party template.  This template eventually might be included with <a href="http://rdoc.rubyforge.org">RDoc</a> but for now easily can be used instead of the built-in templates.  <a href="http://rdoc.rubyforge.org">RDoc&#8217;s own documentation</a> uses this template.</p>
<p><a href="http://rdoc.rubyforge.org/files/RI_txt.html">ri</a> has been enhanced in several ways.  All of its use cases are much faster, some many times so.  In addition, Daniel Choi contributed a patch that adds an interactive mode; in this mode, <a href="http://rdoc.rubyforge.org/files/RI_txt.html">ri</a> gets input from the user in order to disambiguate method lookups and allows the user to browse a class’ methods.  The search directory option (<code>-d</code>) also has been fixed, so that <a href="http://rdoc.rubyforge.org/files/RI_txt.html">ri</a> once again can look for documentation in a user-specified directory.  <a href="http://rdoc.rubyforge.org/files/RI_txt.html">ri&#8217;s</a> caching scheme, which it uses to speed up its searches, is capable of caching documentation from user-specified directories, and so using this option does not result in any performance degradation.</p>
<p>A number of <a href="http://rubyforge.org/tracker/?atid=2475&amp;group_id=627&amp;func=browse">future enhancements</a> have been identified that hopefully will improve <a href="http://rdoc.rubyforge.org">RDoc</a> dramatically.  We would love input on its future technical direction and would welcome any new project volunteers.</p>
<div class="addthis"><a href="http://www.addthis.com/bookmark.php" onclick="window.open('http://www.addthis.com/bookmark.php?pub=designingpatterns&amp;url=http%3A%2F%2Fblogs.designingpatterns.com%2Furban-jungle%2F2008%2F09%2F19%2Frdoc-220-released%2F&amp;title=RDoc+2.2.0+Released', 'addthis', 'scrollbars=yes,menubar=no,width=620,height=520,resizable=yes,toolbar=no,location=no,status=no'); return false;" title="Bookmark using any bookmark manager!" target="_blank"><img src="http://s3.addthis.com/button1-bm.gif" width="125" height="16" border="0" /></a></div><div class="feedflare">
<a href="http://feeds.feedburner.com/~f/ViewWithinTheUrbanJungle?a=4GYNL"><img src="http://feeds.feedburner.com/~f/ViewWithinTheUrbanJungle?i=4GYNL" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blogs.designingpatterns.com/urban-jungle/2008/09/19/rdoc-220-released/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Tricking out Ruby Documentation: Picking the Right Documentation Generator Tool</title>
		<link>http://blogs.designingpatterns.com/urban-jungle/2008/08/26/tricking-out-ruby-documentation-picking-the-right-documentation-generator-tool/</link>
		<comments>http://blogs.designingpatterns.com/urban-jungle/2008/08/26/tricking-out-ruby-documentation-picking-the-right-documentation-generator-tool/#comments</comments>
		<pubDate>Tue, 26 Aug 2008 19:10:45 +0000</pubDate>
		<dc:creator>tony</dc:creator>
		
		<category><![CDATA[rdoc]]></category>

		<category><![CDATA[ruby]]></category>

		<category><![CDATA[software documentation]]></category>

		<category><![CDATA[documentation]]></category>

		<category><![CDATA[documentation generator]]></category>

		<category><![CDATA[hanna]]></category>

		<category><![CDATA[rdoc template]]></category>

		<category><![CDATA[rdtool]]></category>

		<category><![CDATA[templates]]></category>

		<category><![CDATA[yard]]></category>

		<category><![CDATA[yardoc]]></category>

		<guid isPermaLink="false">http://blogs.designingpatterns.com/urban-jungle/?p=20</guid>
		<description><![CDATA[In my other blog, I recently wrote a post about the characteristics of a good software documentation creation and publishing pipeline.  A documentation generator is the core of such a pipeline.  Designing Patterns has written several open-source Ruby gems, and in order to create a documentation pipeline for these, I evaluated the documentation [...]]]></description>
			<content:encoded><![CDATA[<p>In <a href="http://blogs.designingpatterns.com/acropolis">my other blog</a>, I recently wrote <a href="http://blogs.designingpatterns.com/acropolis/2008/07/31/characteristics-of-a-good-software-documentation-pipeline/">a post</a> about the characteristics of a good software documentation creation and publishing pipeline.  A <a href="http://en.wikipedia.org/wiki/Documentation_generator">documentation generator</a> is the core of such a pipeline.  Designing Patterns has written several open-source Ruby gems, and in order to create a documentation pipeline for these, I evaluated the documentation generators for Ruby.  I think that <a href="http://rdoc.rubyforge.org/">RDoc</a> is the best such tool.</p>
<p>I previously have used <a href="http://java.sun.com/j2se/javadoc/">Javadoc</a> and <a href="http://www.stack.nl/~dimitri/doxygen/">Doxygen</a>, but neither supports Ruby.   There are multi-language tools that understand Ruby code in a basic way, such as <a href="http://www.naturaldocs.org/">Natural Docs</a> and <a href="http://www.xs4all.nl/~rfsber/Robo/robodoc.html">ROBODoc</a>, but none that offers strong support for the language&#8217;s features and idioms.  <a href="http://rdoc.rubyforge.org/">RDoc</a> is the standard <a href="http://en.wikipedia.org/wiki/Documentation_generator">documentation generator</a> used within the Ruby community.  Like <a href="http://www.stack.nl/~dimitri/doxygen/">Doxygen</a>, it can parse source code and, even without any comments, generate web pages documenting the code.  It has a number of very impressive strengths:</p>
<ul>
<li>It has very strong support for Ruby syntax and idioms, including being able to document attributes, methods that accept blocks, and metaprogramming constructs.</li>
<li>It provides a very natural markup language that can be written and read easily, even as plain text.</li>
<li>It has a powerful cross-referencing engine that automatically generates class and method cross-reference links in the text of the web pages that it produces.</li>
<li>It inlines or links to a method&#8217;s source code in the HTML documentation that it generates for the method.</li>
<li>Using <a href="http://www.graphviz.org/">graphviz</a>, it can embed class diagrams into the web pages that it generates.</li>
<li>It can generate several different formats of documents, including HTML, XML, texinfo (which in turn can be used to create PDF documents), and Windows Help.</li>
<li>It includes ri, the standard Ruby tool for viewing documentation on the command-line, and can generate documentation for ri.
<li>It can parse C code and understands the C/Ruby calling conventions, so it can generate documentation for classes written in both C and Ruby.</li>
<li>It uses a powerful templating system based on embedded Ruby to generate HTML, allowing developers to create new templates in order to customize the look of their web documentation.</li>
<li>There is tremendous support for it in the standard Ruby tools; the gem system, rake, and hoe use it to generate documentation.</li>
</ul>
<p>Unfortunately, <a href="http://rdoc.rubyforge.org/">RDoc</a> has some significant weaknesses, including:</p>
<ul>
<li>Its markup language is not very expressive; in particular, there is no descriptive markup for programming elements, like method parameters and return values.  Both <a href="http://www.stack.nl/~dimitri/doxygen/">Doxygen</a> and <a href="http://java.sun.com/j2se/javadoc/">Javadoc</a> offer such markup.  At Designing Patterns, we compensate for this to some extent by using an emacs macro to generate markup that simulates descriptive markup for programming elements (see <a href="http://configtoolkit.rubyforge.org/classes/ConfigToolkit/ConstrainedArray.html#M000025">this method documentation</a> for example).</li>
<li>The web pages produced by the default HTML template look pretty poor.  <a href="http://www.ruby-doc.org/core/">This</a> is an example, generated for Ruby&#8217;s Core Library.  It looks dated and, worse, the frames at the top make reading the pages difficult.  I always find myself making the top frames taller in order to see more of the class, file, and method lists but then later making the top frames shorter in order to see more text in the central frame.  At Designing Patterns, we use a beautiful 3rd party template, <a href="http://github.com/mislav/hanna/tree/master">Hanna</a>, to produce documentation like <a href="http://configtoolkit.rubyforge.org">this</a>.</li>
<li>Although Ruby&#8217;s standard tools support <a href="http://rdoc.rubyforge.org/">RDoc</a>, they often offer limited ability to specify <a href="http://">RDoc</a> options, such as which HTML template to use.  I fixed this to some extent with a patch that allows one to specify <a href="http://rdoc.rubyforge.org/">RDoc</a> options through the <code>RDOCOPT</code> environment variable, similar to how the <code>RUBYOPT</code> environment variable allows one to specify options for the Ruby interpreter.</li>
</ul>
<p><a href="http://rdoc.rubyforge.org/">RDoc</a> has many strengths, and its flaws, while significant, can be compensated for well enough to make it very suitable for our company&#8217;s purposes.  Its maturity, the support for it in the standard Ruby tools, and its widespread adoption by the Ruby community make it particularly attractive for use in a production toolchain.  While designing a documentation pipeline around it, I have submitted a number of patches and lately have become an <a href="http://rdoc.rubyforge.org/">RDoc</a> developer.  Active development recently has been restarted, and so I have no doubt that its flaws will be fixed and that it will continue to improve in future releases.</p>
<p>There are two other <a href="http://en.wikipedia.org/wiki/Documentation_generator">documentation generator</a> tools for Ruby.  The first is <a href="http://rubyforge.org/projects/rdtool/">RDtool</a>.  This was used heavily prior to <a href="http://rdoc.rubyforge.org/">RDoc</a>, but, unlike <a href="http://rdoc.rubyforge.org/">RDoc</a> and <a href="http://www.stack.nl/~dimitri/doxygen/">Doxygen</a>, it does not generate documentation for classes and methods automatically.  In fact, it is not a source code documentation generator at all but is instead a more general formatting tool; <a href="http://rdoc.sourceforge.net/rd/index.html">this</a> discusses the differences between <a href="http://rubyforge.org/projects/rdtool/">RDTool</a> and <a href="http://rdoc.rubyforge.org/">RDoc</a> in greater depth.  <a href="http://rubyforge.org/projects/rdtool/">RDTool&#8217;s</a> lack of support for source code means that much more formatting is required in order to create proper documentation, and so I immediately rejected using it.  The other alternative is <a href="http://yard.rubyforge.org/">Yard</a> (also called Yardoc).  This is a relatively recent tool in the vein of <a href="http://www.stack.nl/~dimitri/doxygen/">Doxygen</a> and <a href="http://rdoc.rubyforge.org/">RDoc</a>.  It offers the following advantages over <a href="http://rdoc.rubyforge.org/">RDoc</a>:</p>
<ul>
<li>It provides descriptive markup for programming elements, very similar to that provided by <a href="http://www.stack.nl/~dimitri/doxygen/">Doxygen</a> and <a href="http://java.sun.com/j2se/javadoc/">Javadoc</a>.</li>
<li>It offers an API to customize the parsing of source files, allowing it to accommodate new metaprogramming constructs easily.</li>
<li>In a class&#8217; documentation, it shows methods inherited from a parent class.</li>
<li>The default look of its generated web pages is better than <a href="http://rdoc.rubyforge.org/">RDoc&#8217;s</a>.</li>
</ul>
<p><a href="http://yard.rubyforge.org/">Yard</a>, however, has the following disadvantages:</p>
<ul>
<li>It is not very mature.  In fact, the version that I tried crashed on one of my gems.</li>
<li>It cannot parse C code, and so it can not create documentation for the Ruby Core Library or for gems written in C and Ruby.</li>
<li>There is no built-in support for it in the standard Ruby tools.</li>
<li>It only provides built-in support for generating HTML, although it was written to allow the addition of other output formats with relative ease.</li>
</ul>
<p>Given the above <a href="http://yard.rubyforge.org">Yard</a> vs. <a href="http://rdoc.rubyforge.org/">RDoc</a> points, I think that <a href="http://rdoc.rubyforge.org/">RDoc</a> is the better choice for Designing Patterns as <a href="http://yard.rubyforge.org/">Yard</a> does not seem ready for our production use.  It does, however, have a number of interesting and exciting features.  I hope that the two tools will cross-pollinate and even share code in the future.</p>
<p>In forthcoming posts, I will discuss how to create a documentation pipeline around <a href="http://rdoc.rubyforge.org/">RDoc</a> that utilizes its strengths and masks its weaknesses.</p>
<div class="addthis"><a href="http://www.addthis.com/bookmark.php" onclick="window.open('http://www.addthis.com/bookmark.php?pub=designingpatterns&amp;url=http%3A%2F%2Fblogs.designingpatterns.com%2Furban-jungle%2F2008%2F08%2F26%2Ftricking-out-ruby-documentation-picking-the-right-documentation-generator-tool%2F&amp;title=Tricking+out+Ruby+Documentation%3A+Picking+the+Right+Documentation+Generator+Tool', 'addthis', 'scrollbars=yes,menubar=no,width=620,height=520,resizable=yes,toolbar=no,location=no,status=no'); return false;" title="Bookmark using any bookmark manager!" target="_blank"><img src="http://s3.addthis.com/button1-bm.gif" width="125" height="16" border="0" /></a></div><div class="feedflare">
<a href="http://feeds.feedburner.com/~f/ViewWithinTheUrbanJungle?a=Z9qfgK"><img src="http://feeds.feedburner.com/~f/ViewWithinTheUrbanJungle?i=Z9qfgK" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blogs.designingpatterns.com/urban-jungle/2008/08/26/tricking-out-ruby-documentation-picking-the-right-documentation-generator-tool/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Non-trivial Non-Recursive Make</title>
		<link>http://blogs.designingpatterns.com/urban-jungle/2008/06/02/non-trivial-non-recursive-make/</link>
		<comments>http://blogs.designingpatterns.com/urban-jungle/2008/06/02/non-trivial-non-recursive-make/#comments</comments>
		<pubDate>Mon, 02 Jun 2008 15:46:04 +0000</pubDate>
		<dc:creator>tony</dc:creator>
		
		<category><![CDATA[build systems]]></category>

		<category><![CDATA[make]]></category>

		<category><![CDATA[pattmake]]></category>

		<category><![CDATA[gmake]]></category>

		<category><![CDATA[non-recursive build]]></category>

		<guid isPermaLink="false">http://blogs.designingpatterns.com/urban-jungle/?p=15</guid>
		<description><![CDATA[An earlier post discusses why non-recursive build systems are superior to recursive build systems and shows how to build a simple hello_world program non-recursively with make.  The non-recursive hello_world build has several shortcomings, however.  The worst is that adding a new directory to the build requires adding a line like this to the [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blogs.designingpatterns.com/urban-jungle/2008/05/27/non-recursive-builds-always-are-better-than-recursive-builds/">An earlier post</a> discusses why non-recursive build systems are superior to recursive build systems and shows how to build a simple <code>hello_world</code> program non-recursively with <code>make</code>.  The non-recursive <code>hello_world</code> build has several shortcomings, however.  The worst is that adding a new directory to the build requires adding a line like this to the top-level makefile:</p>
<pre name="code" class="c">

include new_directory/non_recursive.mk
</pre>
<p>It might not seem like a significant problem in this small example, but it becomes so in larger systems.  Hard coding directories in makefiles is a mistake that duplicates knowledge of the directories that need to be built, already contained in the simple presence of makefiles in the directories.  This duplication results in having to make two changes in order to add a new directory to the build: a directory-specific makefile must be created and a line must be added to some parent makefile.  Renaming a directory similarly requires two changes.  A former employer&#8217;s recursive build system required that each directory&#8217;s makefile list the subdirectories that needed to be built, and it was quite common for a developer to forget to modify the parent directory makefiles when adding or renaming directories.  The build within the created or renamed directory worked perfectly well, of course, allowing the error to propagate and break the top-level production build.  Another problem with hard coding all build directories into the top-level makefile is that many different developers will need to edit the file often in order to modify the build&#8217;s directory list.  Depending on the sophistication of the system&#8217;s version control software, this will lead to work being slowed by contention over the file or by programmers always having to merge others&#8217; changes into their work.</p>
<p>A better solution is for <code>make</code> itself to detect the directories that need to be built automatically, removing any need to duplicate and maintain this information in the makefiles.  This is what <a href="http://sourceforge.net/projects/pattmake/">pattmake</a> does, and it is surprisingly simple to accomplish.  Assuming that the directory-specific makefiles in the build system always have the same name (such files are named <code>contents.mk</code> in the <code>pattmake</code> system, for instance), the <code>find</code> utility can be invoked from within <code>make</code> to discover the directories that need to be built (I originally got this technique from <a href="http://www.amazon.com/Managing-Projects-Make-Nutshell-Handbooks/dp/0596006101/">this gmake book</a>).  I&#8217;ve created a new <code>hello_world</code> build that demonstrates this (the source code for which can be <a href='http://blogs.designingpatterns.com/urban-jungle/2008/06/02/non-trivial-non-recursive-make/hello_world2/' rel='attachment wp-att-19'>downloaded here</a>).  This example requires at least <a href="http://www.gnu.org/software/make/">gmake 3.81</a> and can be run with <code>make -f build.mk all</code>.</p>
<p>Here is <code>build.mk</code>:</p>
<pre name="code" class="c">

include rules.mk

DIR_SPECIFIC_MAKEFILE_NAME := contents.mk

buildable_dirs = \
	$(shell find . -name $(DIR_SPECIFIC_MAKEFILE_NAME) | \
	sed 's/$(DIR_SPECIFIC_MAKEFILE_NAME)//')

define process_dir
  PROGRAMS :=

  include $1/contents.mk

  ALL_PROGRAMS += $$(PROGRAMS)

  clean::
	$(RM) $1/*.o
	$(RM) $1/*.a

  #
  # The last line of the function must be left blank
  # in order to avoid some quirky, broken gmake
  # behavior when expanding macros within foreach
  # loops.
  #

endef

define process_dirs
  $(foreach DIR, $(buildable_dirs),\
	$(call process_dir,$(DIR)))
endef

ALL_PROGRAMS :=

$(eval $(process_dirs))

.PHONY:
	all \
	clean

all: $(ALL_PROGRAMS)

clean::
	$(RM) $(ALL_PROGRAMS)
</pre>
<p>Here is <code>bin/contents.mk</code>:</p>
<pre name="code" class="c">

bin/hello_world: bin/hello_world.o lib/hello.a
        $(CXX) $(LDFLAGS) -o $@ $^

PROGRAMS += bin/hello_world
</pre>
<p>Here is <code>lib/contents.mk</code>:</p>
<pre name="code" class="c">

lib/hello.a: lib/hello.o
</pre>
<p>The <code>build.mk</code> code may seem very confusing to those who have not done significant <code>make</code> programming, but it&#8217;s doing something quite simple.  The apparent complication stems from <a href="http://wiki.designingpatterns.com/index.php/Make#Flaws">make&#8217;s very unwieldy language</a>.  Before explaining the details, I am going to provide a broad overview of <code>build.mk's</code> flow.  <code>buildable_dirs</code> (line #5) is a <code>make</code> function that invokes the UNIX <code>find</code> utility (via the <a href="http://www.gnu.org/software/make/manual/make.html#Shell-Function">built-in shell function</a>) to get the paths of all <code>contents.mk</code> files in or under <code>make's</code> current working directory.  The results then are piped to <code>sed</code> in order to remove <code>contents.mk</code> from the paths, yielding a list of directories containing a <code>contents.mk</code> file.</p>
<p>The <code>process_dirs</code> function (line #29) loops over the directories returned by <code>buildable_dirs</code> with the <a href="http://www.gnu.org/software/make/manual/make.html#Foreach-Function">built-in foreach function</a> and calls the <code>process_dir</code> function for each directory.  The <code>process_dir</code> function (line #9)  includes the specified directory&#8217;s <code>contents.mk</code> file, aggregates any programs defined by <code>contents.mk</code> (the <code>PROGRAMS</code> variable) into the <code>ALL_PROGRAMS</code> variable, and adds an action to the <code>clean</code> target that will remove the files created by the build (object files and libraries) in the directory.  At the end of <code>build.mk</code>, a <code>.PHONY all</code> target (line #42) is defined to build <code>ALL_PROGRAMS</code>, and a command is added to the <code>clean</code> target to remove <code>ALL_PROGRAMS</code>.</p>
<p><code>build.mk's</code> main complication is the use of <code>gmake's</code> <a href="http://www.gnu.org/software/make/manual/make.html#Eval-Function">built-in eval function</a> to call <code>process_dirs</code> (line #36).  <code>eval</code> allows makefile code to be generated and interpreted dynamically.  It is passed a function call and makes two passes over the specified function:</p>
<ol>
<li>In the first pass, <code>gmake</code> evaluates all unescaped variables in the function (a variable evaluation can be escaped by adding an extra <code>$</code>; thus <code>$$(PROGRAMS)</code> is an escaped evaluation and won&#8217;t be evaluated until the second pass).  This pass respects neither comments nor conditionals, since <code>gmake</code> is not interpreting the code but instead just evaluating <strong>all</strong> unescaped variables in order to generate code.</li>
<li>In the second pass, <code>gmake</code> interprets the code generated by the first pass in the normal fashion.</li>
</ol>
<p>The <code>foreach</code> function normally cannot be used to generate code (trying to do so will cause <code>make</code> to die with an error), but it can if evaluated during <code>eval's</code> first pass and so <code>process_dirs</code> must be called with <code>eval</code>.</p>
<p><code>process_dirs</code> uses the <a href="http://www.gnu.org/software/make/manual/make.html#Call-Function">built-in call function</a> to invoke <code>process_dir</code> (line #31).  The <code>call</code> function allows arguments to be passed to a user-defined <code>make</code> function; the first argument is bound to <code>$1</code> within the function, the second to <code>$2</code>, etc.  So when <code>process_dir</code> is called with the <code>$(DIR)</code> argument, <code>$(DIR)</code> is bound to <code>$1</code> inside the function.  Note, however, that since <code>process_dirs</code> is invoked through <code>eval</code> and the call to <code>process_dir</code> within <code>process_dirs</code> is unescaped, <code>process_dir</code> effectively also is invoked through <code>eval</code> and so is evaluated in two passes.  Thus, <code>$1</code> is evaluated in <code>eval's</code> first pass, and so it can be used safely in commands (such as <code>$(RM) $1/*.o</code> on line #17).  Normally, variables in commands are not evaluated when <code>make</code> interprets the command, but instead the evaluation is deferred until the command actually is executed after all makefile code has been interpreted.  This results in the variable evaluating to the last value the variable had during the interpretation of the makefile, <strong>not</strong> the value that the variable had when the command was interpreted (assuming otherwise is a very common mistake when writing makefiles).</p>
<p>The evaluation of the <code>PROGRAMS</code> variable within <code>process_dir</code> (line #14) must be escaped until <code>eval's</code> second pass, because <code>PROGRAMS</code> only will be defined when <code>contents.mk</code> is included, which <code>gmake</code> does during the second pass.</p>
<p>Another small complication is that the <code>clean</code> target has <a href="http://www.gnu.org/software/make/manual/make.html#Double_002dColon">double-colon</a> rules, which essentially allow multiple actions to be chained to a target.  <code>clean</code> has one action for each directory built (the removal of the directory&#8217;s object and library files) and one action at the end of <code>build.mk</code> (the removal of the programs listed in <code>ALL_PROGRAMS</code>).</p>
<p>This <code>hello_world</code> build has several advantages over the previous version.  Firstly, as promised, it automatically discovers the directories that need to be built, eliminating any need on the part of the developer to duplicate this information inside of makefiles.  Secondly, it allows arbitrary makefile code to be interpreted before and after each directory-specific makefile is included.  The build leverages this to add <code>clean</code> actions for each directory.  It also aggregates the programs defined by each <code>contents.mk</code> (the <code>PROGRAMS</code> variable) into <code>ALL_PROGRAMS</code>.  This sandboxes the directory-specific makefiles in that they do not need to reference (and thus potentially corrupt) variables like <code>ALL_PROGRAMS</code> that contain information for the entire build.  In the original <code>hello_world</code> example, a developer accidentally could have assigned to <code>PROGRAMS</code> rather than appending new programs to it, which would have wiped out all programs appended in prior directory-specific makefiles.  This kind of error might not be noticed until production because the build for the developer&#8217;s directory and all directories built afterward would work perfectly.</p>
<p>This <code>hello_world</code> build has a robust, non-recursive implementation that eliminates the duplication of directory information in the build, makes adding directories to the build trivially easy, allows <code>make</code> code to be run for each of the build&#8217;s directories, and sandboxes directory-specific makefiles.  It could form the basis of a production quality build system, and the <code>pattmake</code> build system&#8217;s core is just an elaboration of this example.</p>
<div class="addthis"><a href="http://www.addthis.com/bookmark.php" onclick="window.open('http://www.addthis.com/bookmark.php?pub=designingpatterns&amp;url=http%3A%2F%2Fblogs.designingpatterns.com%2Furban-jungle%2F2008%2F06%2F02%2Fnon-trivial-non-recursive-make%2F&amp;title=Non-trivial+Non-Recursive+Make', 'addthis', 'scrollbars=yes,menubar=no,width=620,height=520,resizable=yes,toolbar=no,location=no,status=no'); return false;" title="Bookmark using any bookmark manager!" target="_blank"><img src="http://s3.addthis.com/button1-bm.gif" width="125" height="16" border="0" /></a></div><div class="feedflare">
<a href="http://feeds.feedburner.com/~f/ViewWithinTheUrbanJungle?a=VfyAmI"><img src="http://feeds.feedburner.com/~f/ViewWithinTheUrbanJungle?i=VfyAmI" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blogs.designingpatterns.com/urban-jungle/2008/06/02/non-trivial-non-recursive-make/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Non-recursive Make Builds always are Better than Recursive Make Builds</title>
		<link>http://blogs.designingpatterns.com/urban-jungle/2008/05/27/non-recursive-builds-always-are-better-than-recursive-builds/</link>
		<comments>http://blogs.designingpatterns.com/urban-jungle/2008/05/27/non-recursive-builds-always-are-better-than-recursive-builds/#comments</comments>
		<pubDate>Tue, 27 May 2008 20:23:20 +0000</pubDate>
		<dc:creator>tony</dc:creator>
		
		<category><![CDATA[build systems]]></category>

		<category><![CDATA[make]]></category>

		<category><![CDATA[pattmake]]></category>

		<category><![CDATA[gmake]]></category>

		<category><![CDATA[non-recursive build]]></category>

		<category><![CDATA[recursive build]]></category>

		<guid isPermaLink="false">http://blogs.designingpatterns.com/urban-jungle/?p=4</guid>
		<description><![CDATA[Pattmake is the gmake-based build system used by Designing Patterns (I discuss why I chose to use gmake here).  I had three main requirements when designing pattmake:

That it be non-recursive
That it easily accommodates simultaneous builds for different architectures
That files generated by builds (build artifacts and targets, such as object files) be put in a [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://sourceforge.net/projects/pattmake/">Pattmake</a> is the <code>gmake</code>-based build system used by Designing Patterns (I discuss why I chose to use <code>gmake</code> <a href="http://blogs.designingpatterns.com/urban-jungle/2008/05/06/welcome-to-the-jungle/">here</a>).  I had three main requirements when designing <code>pattmake</code>:</p>
<ol>
<li>That it be non-recursive</li>
<li>That it easily accommodates simultaneous builds for different architectures</li>
<li>That files generated by builds (build artifacts and targets, such as object files) be put in a different directory than that of the associated source code</li>
</ol>
<p>I will discuss the reasons for and the implementation of each requirement in my next blog entries.</p>
<p>The first requirement might be a bit surprising, since recursive build systems still are very common.  They are fundamentally and irretrievably flawed, however.  Briefly, in a recursive build system, <code>make</code> spawns a new <code>make</code> process in order to build a subdirectory.  This seems like a wonderful idea because:</p>
<ul>
<li><code>Make</code> <a href="http://wiki.designingpatterns.com/index.php/Make#Scenarios">works best</a> when the source files are in <code>make's</code> current working directory.  Developers do not have to take different source directories into account when writing rules, for instance.</li>
<li>The makefile for a given directory is completely independent of those for other directories.</li>
<li>Writing a recursive makefile requires minimal knowledge of the build infrastructure, since a recursive makefile is not very different than a standalone makefile.</li>
</ul>
<p>These are very compelling advantages, and so recursive build systems often are used despite their fundamental flaw.  A bit of background knowledge about <code>make's</code> implementation is required in order to understand the flaw, however.  <code>Make</code> <a href="http://www.gnu.org/software/make/manual/make.html#Reading-Makefiles">works</a> in two phases</p>
<ol>
<li><code>Make</code> processes the makefile, finding all possible targets, associating prerequisites with those targets, and storing commands that transform prerequisites into targets.  From this information, it constructs a dependency graph.</li>
<li><code>Make</code> locates the target that it is supposed to build and works backward through the dependency graph from that target, rebuilding anything that is out of date using the commands stored in the first phase.</li>
</ol>
<p>Recursive build systems are flawed because they restrict each <code>make</code> instance to creating a dependency graph with only the build information contained in the directory the instance is processing, resulting in truncated graphs.  I&#8217;m going to prove this with the build for an example <code>hello_world</code> program (you have three chances to guess the program&#8217;s functionality, and the first two don&#8217;t count), the source for which can be downloaded <a href='http://blogs.designingpatterns.com/urban-jungle/2008/05/27/non-recursive-builds-always-are-better-than-recursive-builds/hello_world/' rel='attachment wp-att-13'>here</a> .  This program&#8217;s build should work with any reasonably modern <code>make</code>, although I&#8217;ve only tested with <code>gmake</code>.  The directory structure is:</p>
<pre>
  non_recursive.mk
  recursive.mk
  rules.mk
  bin:
      hello_world.cc
      non_recursive.mk
      recursive.mk
  lib:
      hello.cc
      hello.h
      non_recursive.mk
      recursive.mk
</pre>
<p>The package actually contains two build systems for the <code>hello_world</code> program, one recursive (consisting of <code>rules.mk</code> and all of the <code>recursive.mk</code> files; build with <code>make -f recursive.mk all</code>) and one non-recursive (consisting of <code>rules.mk</code> and all of the <code>non_recursive.mk</code> files; build with <code>make -f non_recursive.mk all</code>).  Here is <code>bin/recursive.mk</code>:</p>
<pre name="code" class="c">

TOP_LEVEL_DIR=..

include $(TOP_LEVEL_DIR)/rules.mk

hello_world: hello_world.o ../lib/hello.a
        $(CXX) $(LDFLAGS) -o $@ $^
</pre>
<p>When <code>make</code> recurses and launches a new instance for the <code>bin</code> directory, the new instance knows almost nothing about <code>lib/hello.a</code>.  The only thing that it knows is the library&#8217;s time of last modification, which, if more recent than <code>hello_world's</code> time of last modification, will trigger a relink of <code>hello_world</code>.  It does not know, however, how <code>lib/hello.a</code> is itself built and thus whether or not it needs to be rebuilt before linking <code>bin/hello_world</code>.  The new instance has incomplete dependency information and thus can produce an incorrect <code>bin/hello_world</code> build.  If the <code>hello_world()</code> function declaration and definition in <code>lib/hello.h</code> and <code>lib/hello.cc</code> are changed without <code>lib</code> being rebuilt, for instance, a broken <code>bin/hello_world</code> will be built.  <code>bin/hello_world</code> will link against a stale <code>lib/hello.a</code> and get the old function definition, because the <code>make</code> instance for <code>bin</code> cannot trigger a rebuild for <code>lib/hello.a</code> as it is built in a different subdirectory.  <code>bin/hello_world.o</code> will be compiled with the new function declaration in <code>lib/hello.h</code>, however.  This will result in a likely fatal mismatch between the <code>hello_world()</code> function that <code>bin/hello_world.cc</code> tries to call and the <code>hello_world()</code> function that actually exists in <code>lib/hello.a</code>.  The textbook solution for this problem is to duplicate the dependency of <code>bin/hello_world</code> on <code>lib/hello.a</code> in the top-level <code>recursive.mk</code> like so:</p>
<pre name="code" class="c">

TOP_LEVEL_DIR=.

include $(TOP_LEVEL_DIR)/rules.mk

.PHONY: \
        all \
        bin \
        lib \
        clean

all: bin

bin: lib
        (cd $@; $(MAKE) -f recursive.mk)

lib:
        (cd $@; $(MAKE) -f recursive.mk)

#
# This is not a good way to implement clean,
# but for this simple example...
#
clean:
        $(RM) bin/*.o bin/hello_world lib/*.o lib/*.a
</pre>
<p><code>Make</code> is told that both <code>bin</code> and <code>lib</code> are <a href="http://www.gnu.org/software/make/manual/make.html#Phony-Targets">.PHONY targets</a>.  <code>.PHONY</code> is a directive (<strong>not</strong> a real target) that informs <code>make</code> that the targets that it modifies are not actual file system objects (and so are not physically built by <code>make</code>) and always should be rebuilt by <code>make</code> if they appear in the dependency chain (that is, <code>.PHONY</code> targets&#8217; prerequisites should be evaluated and any associated commands should be run).  Since they are not really file system objects, <code>make</code> never will try to check <code>.PHONY</code> targets&#8217; modification times.  <code>.PHONY targets</code> can be used to alias a group of physical targets.  In this case, <code>bin</code> and <code>lib</code> are aliases for all of the targets in the given subdirectory, resulting in <code>make</code> always recursing into the given subdirectory.  The dependency of <code>bin/hello_world</code> on <code>lib/hello.a</code> is duplicated in the dependency of <code>bin</code> on <code>lib</code>, which forces <code>make</code> to recurse first into <code>lib</code> and then into <code>bin</code>.  This textbook solution is flawed in two ways.  Firstly, duplication of dependency information is used to paper over the underlying problem, and it is very easy to modify the dependency in one place without changing it in the other place (resulting in a subtly broken build).  Secondly, this band-aid only works if the build is kicked off at the top-level; a programmer who accidentally builds <code>bin/hello_world</code> in <code>bin</code> will create a broken executable if <code>lib/hello.a</code> is stale (the error scenario described above).</p>
<p>The problem described in the example may seem manageable, but the negative effects of a recursive build become corrosively bad in much larger software systems that have many more executables and libraries, a much more complicated web of dependencies, and code generation.  A former employer had such a situation, and broken builds due to dependencies not being duplicated properly were quite common.  The band-aid described above became very fragile.  Peter Miller&#8217;s <a href="http://aegis.sourceforge.net/auug97.pdf">seminal paper</a> on non-recursive builds mentions that many shops in fact decide to forgo the textbook band-aid and, instead, build the same code multiple times in order to paper over the recursive <code>make</code> instances&#8217; lack of full dependency knowledge.  This &#8220;solution&#8221; leads to a dramatically slower build, which can become a development bottleneck very quickly for large systems.  </p>
<p>The alternative, a non-recursive build system, has a higher initial setup cost (the build system infrastructure is significantly more complicated than that of an equivalent recursive build system) and carries with it a steeper learning curve, but, by providing <code>make</code> with the full dependency graph, is the superior solution.  The simplest non-recursive build system consists of a single makefile that is responsible for building multiple directories.  This might be fine for small to medium projects but does not scale well.  A far better alternative and the one that <code>pattmake</code> uses is to have a single makefile per directory that handles building the directory but to have <code>make</code> <strong>include</strong> these directory-specific makefiles rather than recursively processing them.  This allows each directory to have a makefile that is independent of those for other directories, just as in recursive build systems.  The top-level <code>non_recursive.mk</code> in the <code>hello_world</code> example demonstrates this technique:</p>
<pre name="code" class="c">

TOP_LEVEL_DIR=.

include rules.mk

include bin/non_recursive.mk
include lib/non_recursive.mk

.PHONY:
        all \
        clean

all: $(PROGRAMS)

#
# This is not a good way to implement clean,
# but for this simple example...
#
clean:
        $(RM) bin/*.o bin/hello_world lib/*.o lib/*.a
</pre>
<p>Here is <code>bin/non_recursive.mk</code>:</p>
<pre name="code" class="c">

bin/hello_world: bin/hello_world.o lib/hello.a
        $(CXX) $(LDFLAGS) -o $@ $^

PROGRAMS += bin/hello_world
</pre>
<p>Here is <code>lib/non_recursive.mk</code>:</p>
<pre name="code" class="c">

lib/hello.a: lib/hello.o
</pre>
<p>While the makefiles may look a bit odd because sources and targets have to have a directory specified (<code>make</code> builds everything with the top-level directory as its current working directory in this system, which is quite different than in the recursive build where <code>make</code> changes to the directory to be processed before spawning a new <code>make</code> instance), developers quickly will get used to this.  In fact, even recursive build systems may have such complication if the targets are being put into a different directory than the source, which is quite common for multi-architecture builds.  The benefits of a non-recursive build system are:</p>
<ul>
<li><code>Make</code> always is able to build a full dependency graph, without any duplication of dependencies on the part of the programmer.  Note that the top-level <code>non_recursive.mk</code> in the <code>hello_world</code> example does <strong>not</strong> contain any dependency relationship between <code>bin</code> and <code>lib</code>.</li>
<li>Unlike recursive build systems, in which only full, top-level system builds can be correct, non-recursive build systems can build specified targets (say a particular program) correctly, since, regardless of what it&#8217;s told to build, <code>make</code> always creates a full dependency graph.  Note that <code>make -f non_recursive.mk bin/hello_world</code> works perfectly well while <code>make -f recursive.mk bin/hello_world</code> fails horribly.  It is very easy for a non-recursive build system to provide this functionality in whichever subdirectory it is invoked, which <code>pattmake</code> does (although the <code>hello_world</code> example does not).</li>
<li>Well organized, complex build systems, either recursive or non-recursive, often have large build rule files (containing, for instance, implicit rules to transform <code>.c</code> files into <code>.o</code> files) that need to be included in each makefile.  This ensures that the same build rules are used throughout the build.  Even the simple <code>hello_world</code> example has such a file, <code>rules.mk</code>.  Each recursive makefile has to include such system-wide files (every <code>recursive.mk</code> in the <code>hello_world</code> example does this), forcing make to process such files many times (once per each directory).  Non-recursive makefiles, however, are processed by being included by some top-level makefile, and so only the top-level makefile needs to include the system-wide makefiles (<code>rules.mk</code> only is included by the top-level <code>non_recursive.mk</code> in the <code>hello_world</code> example).  Thus, <code>make</code> only needs to process the system-wide makefiles once per non-recursive build.</li>
</ul>
<p>The ability of non-recursive build systems to deliver correct builds consistently, without any duplication of dependency information, should lead to their always being chosen over recursive build systems.</p>
<div class="addthis"><a href="http://www.addthis.com/bookmark.php" onclick="window.open('http://www.addthis.com/bookmark.php?pub=designingpatterns&amp;url=http%3A%2F%2Fblogs.designingpatterns.com%2Furban-jungle%2F2008%2F05%2F27%2Fnon-recursive-builds-always-are-better-than-recursive-builds%2F&amp;title=Non-recursive+Make+Builds+always+are+Better+than+Recursive+Make+Builds', 'addthis', 'scrollbars=yes,menubar=no,width=620,height=520,resizable=yes,toolbar=no,location=no,status=no'); return false;" title="Bookmark using any bookmark manager!" target="_blank"><img src="http://s3.addthis.com/button1-bm.gif" width="125" height="16" border="0" /></a></div><div class="feedflare">
<a href="http://feeds.feedburner.com/~f/ViewWithinTheUrbanJungle?a=1Nk0tH"><img src="http://feeds.feedburner.com/~f/ViewWithinTheUrbanJungle?i=1Nk0tH" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blogs.designingpatterns.com/urban-jungle/2008/05/27/non-recursive-builds-always-are-better-than-recursive-builds/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Welcome to the Jungle!</title>
		<link>http://blogs.designingpatterns.com/urban-jungle/2008/05/06/welcome-to-the-jungle/</link>
		<comments>http://blogs.designingpatterns.com/urban-jungle/2008/05/06/welcome-to-the-jungle/#comments</comments>
		<pubDate>Tue, 06 May 2008 21:34:47 +0000</pubDate>
		<dc:creator>tony</dc:creator>
		
		<category><![CDATA[build systems]]></category>

		<category><![CDATA[make]]></category>

		<category><![CDATA[pattmake]]></category>

		<category><![CDATA[cmake]]></category>

		<category><![CDATA[gmake]]></category>

		<category><![CDATA[rake]]></category>

		<category><![CDATA[scons]]></category>

		<guid isPermaLink="false">http://blogs.designingpatterns.com/urban-jungle/2008/05/06/welcome-to-the-jungle/</guid>
		<description><![CDATA[Welcome to Designing Patterns and welcome to View within the Urban Jungle!  I will discuss low-level, technical subject matter on this blog (View from the Acropolis posts will be higher-level).  The posts will not be restricted to a particular language, toolkit, software, or technology but rather will be drawn from whatever I am working on [...]]]></description>
			<content:encoded><![CDATA[<p>Welcome to <a href="http://www.designingpatterns.com/">Designing Patterns</a> and welcome to <a href="http://blogs.designingpatterns.com/urban-jungle/">View within the Urban Jungle</a>!  I will discuss low-level, technical subject matter on this blog (<a href="http://blogs.designingpatterns.com/acropolis">View from the Acropolis</a> posts will be higher-level).  The posts will not be restricted to a particular language, toolkit, software, or technology but rather will be drawn from whatever I am working on at the moment.  A major focus of this blog, however, will be to document the reasons that I choose a particular solution, not just the solution itself.  In addition, I also will point out any general patterns that I see in a solution or technique.</p>
<p>I am responsible for selecting, deploying, and maintaining the build system at Designing Patterns.  Prior to Designing Patterns, I worked in a group (about 30 programmers, spread across three continents) with a home-brewed build system based on <a href="http://www-306.ibm.com/software/awdtools/clearcase/">ClearCase&#8217;s</a> <a href="http://publib.boulder.ibm.com/infocenter/cchelp/v7r0m0/index.jsp?topic=/com.ibm.rational.clearcase.tutorial.doc/a_clearmake.htm">clearmake</a> <a href="http://en.wikipedia.org/wiki/Make_(software)">make</a> variant.  By the time that I left, the build system was a real asset to the group; in my opinion, it was best of breed for the entire company.   As this is the system with which I have had by far the most experience, its strengths and shortcomings have molded my vision of a build system.  My former employer&#8217;s system has the following features:</p>
<ul>
<li>All builds      are done within ClearCase dynamic views.</li>
<li>Builds can be started from      the top-level or from any subdirectory.  The build recursively builds      subdirectories, although this behavior needs to be specified for a      particular subdirectory in the directory&#8217;s makefile.</li>
<li>Rules for building C, C++,      Java, and FORTRAN code are present.  Perl scripts automatically are syntax      checked before being staged for release.  Executables and shared      libraries are linked.  Code is generated and then compiled.</li>
<li>Unit testing is integrated into the build process.  The unit tests for a library are placed in a test      subdirectory and are run as part of the build; failure of any of the tests      stops the build.  The tests automatically are <a href="http://www-306.ibm.com/software/awdtools/purify/">Purified</a> and tested for adequate code coverage.</li>
<li>Parallel builds are supported      fully.</li>
<li>Multiple architectures are      supported; all build artifacts are placed in architecture-specific      directories (allowing builds for different architectures to be running      simultaneously).</li>
<li>32-bit and 64-bit builds are      supported; libraries can be dual-built.</li>
<li>Most makefiles are quite      simple, due to the system&#8217;s scaffolding having been hidden inside make      include files.</li>
<li>C header files and FORTRAN      include files included in a source file automatically are registered as      dependencies of the object file built from the source file.  This      feature relies on ClearCase&#8217;s build auditing capabilities (basically,      ClearCase keeps track of which files are read while building a given      target, and automagically identifies them as dependencies).</li>
<li>Leveraging ClearCase&#8217;s      facilities, the build system &#8220;winks in&#8221; all targets that would      not be built any differently than in the production build; this      substantially cuts down the build time of development systems, since, even      in large projects, most of the system&#8217;s files are unchanged and so      associated targets do not need to be built.</li>
</ul>
<p>I wish that I could claim responsibility for this wonderful build system, but I did not know much about build systems while working at my former employer.  I could make the necessary changes to makefiles for my projects, but I did not really understand how make worked in any depth.</p>
<p>After taking responsibility for the Designing Patterns build system, I researched the available options.  To my surprise, I found that <code>make</code> no longer was state of the art.  There are many higher-level build tools.  Some leverage the capabilities of full-fledged programming languages to describe builds (<a href="http://rake.rubyforge.org/">rake</a>, which uses Ruby, <a href="http://www.scons.org/">SCons</a>, which uses Python, and <a href="http://ant.apache.org/">ant</a>, which uses Java, are examples).  Others, like <a href="http://www.cmake.org/HTML/index.html">CMake</a>, generate platform-appropriate build instructions (makefiles on UNIX, Visual Studio project files on Windows, etc.).  Despite the availability of these tools, I decided that Designing Patterns initially will use <a href="http://www.gnu.org/software/make/">gmake</a>.  All of the build experience at Designing Patterns has been with <code>make</code> variants, and it is beneficial to deploy a system that easily will be picked up by everyone, given how many other things must be learned.  <code>Make</code> still is used very widely; source code for packages quite often is built using makefiles generated by <a href="http://en.wikipedia.org/wiki/Automake">automake</a> in the open source world, for instance.  Also, <code>make</code> is a very general, omnipresent build tool that can be molded to handle almost any task.  Many of the higher-level build tools are very closely associated with the needs of a particular language (Ruby&#8217;s <code>rake</code>, for instance); this does not mean that they cannot be used in other contexts, but it does mean that their target audience is relatively homogenous, and so that these other contexts may not be that well supported.  This is a very important point for Designing Patterns, as we still are exploring the technologies that we will use for our products, and we do not want the build system to be a factor in those decisions.  I choose the <code>gmake</code> variant because it is a very portable <code>make</code> (since it runs on virtually all platforms, <code>gmake's</code> makefiles automatically are portable), and it has a very expressive <code>make</code> language.  Designing Patterns will revisit this decision in the future, however, in light of the development work on our products.  Initially using <code>gmake</code> gives us a baseline against which to compare the capabilities of other, higher-level systems in the future.</p>
<p>I am in the process of writing the Designing Pattern&#8217;s <code>gmake</code> build system, which we are calling <a href="http://pattmake.sourceforge.net">pattmake</a>, and which we will release to the public.  Later blog entries will discuss its features and implementation, both of which were informed by my former employer&#8217;s build system.</p>
<div class="addthis"><a href="http://www.addthis.com/bookmark.php" onclick="window.open('http://www.addthis.com/bookmark.php?pub=designingpatterns&amp;url=http%3A%2F%2Fblogs.designingpatterns.com%2Furban-jungle%2F2008%2F05%2F06%2Fwelcome-to-the-jungle%2F&amp;title=Welcome+to+the+Jungle%21', 'addthis', 'scrollbars=yes,menubar=no,width=620,height=520,resizable=yes,toolbar=no,location=no,status=no'); return false;" title="Bookmark using any bookmark manager!" target="_blank"><img src="http://s3.addthis.com/button1-bm.gif" width="125" height="16" border="0" /></a></div><div class="feedflare">
<a href="http://feeds.feedburner.com/~f/ViewWithinTheUrbanJungle?a=Zs3N6H"><img src="http://feeds.feedburner.com/~f/ViewWithinTheUrbanJungle?i=Zs3N6H" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blogs.designingpatterns.com/urban-jungle/2008/05/06/welcome-to-the-jungle/feed/</wfw:commentRss>
		</item>
	<feedburner:awareness xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://api.feedburner.com/awareness/1.0/GetFeedData?uri=ViewWithinTheUrbanJungle</feedburner:awareness></channel>
</rss>
