<?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>Symphonious &#187; Build Systems</title> <atom:link href="http://www.symphonious.net/category/code-and-geek-stuff/build-systems/feed/" rel="self" type="application/rss+xml" /><link>http://www.symphonious.net</link> <description>Living in a state of accord.</description> <lastBuildDate>Wed, 25 Jan 2012 21:25:34 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.3.1</generator> <item><title>Controlling Focus in Firefox</title><link>http://www.symphonious.net/2010/11/24/controlling-focus-in-firefox/</link> <comments>http://www.symphonious.net/2010/11/24/controlling-focus-in-firefox/#comments</comments> <pubDate>Wed, 24 Nov 2010 21:03:02 +0000</pubDate> <dc:creator>Adrian Sutton</dc:creator> <category><![CDATA[Build Systems]]></category> <category><![CDATA[Code and Geek Stuff]]></category> <category><![CDATA[JavaScript]]></category> <guid
isPermaLink="false">http://www.symphonious.net/?p=1479</guid> <description><![CDATA[I have a bunch of JavaScript unit tests and for some of them I need to trigger a real keypress &#8211; one that activates the browser’s default functionality, not just triggers the JavaScript listeners. To do that, I have a simple signed applet that uses the AWT Robot to programmatically trigger the keypresses. Mostly, this [...]]]></description> <content:encoded><![CDATA[<p> I have a bunch of JavaScript unit tests and for some of them I need to trigger a real keypress &#8211; one that activates the browser’s default functionality, not just triggers the JavaScript listeners. To do that, I have a <a
href="https://github.com/ephox/JSRobot/">simple signed applet that uses the AWT Robot</a> to programmatically trigger the keypresses. Mostly, this works brilliantly.</p><p> The problem I’m having is that about 1 time in 10, the focus goes AWOL and the key events generated by the robot simply aren’t delivered anywhere. It’s generally not reliable, though I have got a setup now where I can make it happen within a few minutes of running the tests on a loop.</p><p> The problem is specific to Firefox 3.6 &#8211; I’ve never seen it fail on anything else. I’m testing against Firefox 2.0, 3.0, 3.6 and 4.0 beta 6. 3.6.3 and 3.6.12 to be precise. It fails on all the OS’s I’ve tried: Linux (Ubuntu 10.10), Mac OS X (10.6) and Windows Vista.</p><h2> The Simple Question</h2><p> <strong>Is there a sure-fire way in JavaScript to force focus to a specific element?</strong></p><p> The normal Element.focus() doesn’t seem to be strong enough as I’m already calling that (and I’ve tried oh so many variations of it). I’m even ok with requiring that element to be of a specific type (e.g. a text input). JavaScript is ideal but if it can be done with a signed Java applet I’m ok with that too. Config options, browser plugins and maybe even native code would all be a possibility.</p><h2> The Simple Answer (Update)</h2><p> It turns out that the ineffectiveness of Element.focus() is a usability/security feature of Firefox which is configurable.  In the “Content” tab of preferences, click the “Advanced…” button beside JavaScript and then ensure that “Raise or lower windows” is checked. Annoyingly simple after the amount of effort it took to work out what was going wrong.</p><p> <img
alt="Firefox advanced JavaScript preferences window" src="http://www.symphonious.net/wp-content/uploads/2010/11/Screen-shot-2010-11-25-at-14.07.20.png" /></p><h2> The Detail</h2><p> Here’s what I know:</p><ul><li> The test runner framework loads the actual test pages inside an iframe.<ul><li> The signed applet is inside this iframe.</li></ul></li><li> The test that is giving me trouble uses TinyMCE, which itself uses an iframe, so we have an iframe inside an iframe and that’s where we need to get focus.</li><li> To make sure that the actual browser pane has focus (rather than the URL bar etc), when the page first loads the applet clicks just above itself (thus moving focus to the actual test page inside the first iframe).<ul><li> I can watch this happen so I know the click is in the right place.</li></ul></li><li> The page is definitely fully loaded before the problematic test runs. It’s not the first test in that file but it is the first test that actually uses the robot (the click still happens on page load). I can’t remember a failure where it wasn’t the first test using the robot that failed but can’t be 100% certain of that.</li><li> I’m using the JavaScript focus() method to move focus to the element I’m targeting.<ul><li> I’ve found I need to focus the main window, then each nested iframe window and document body and then finally the element I want to target to make sure that the focus is on the right frame.</li><li> I can check that document.activeElement is pointing to the right place.</li></ul></li><li> When the focus gets lost, even manually typing keys does nothing.<ul><li> But typing tab will move the focus back to the right spot and then typing the key the test was expecting will make the test pass correctly.</li></ul></li><li> The key event is <em>definitely</em> firing from the AWT robot, because if that key is the tab key, it correctly moves the focus back to where it should be (but I have no way to know programmatically that I need to repeat the keystroke).</li></ul><h2> Why Not Selenium?</h2><p> Just to cover this off, there are a few reasons that this project isn’t using Selenium:</p><ol><li> It was an existing project which already had tests using QUnit and most of the tests don’t need this Robot functionality so can be done in pure JS.</li><li> It’s a pure JS project so it’s really nice to also write the tests in JavaScript (the robot has a nice JS wrapper).</li><li> This approach lets me run the tests in any browser without requiring any setup at all. No need to install and configure anything &#8211; you could very likely walk up to a computer in an internet cafe and have the tests pass which makes life <em>so</em> much easier.</li><li> It should work damn it! I want to know why it doesn’t and why Selenium, which also uses the AWT Robot doesn’t hit the same problem (or maybe it does?).</li></ol><h2> Murphy’s Law</h2><p> Just before starting to write this post (some 30 minutes ago due to distractions), I had the crazy idea to add a java.awt.TextField to the applet and make the applet a little bit bigger (150x40px instead of 10x10px). The tests have been running continuously with that new configuration since then without a single failure. The text area is never used in any way, but for some reason just having it there seems to make life better. I don’t get it.</p><p> Due to a power outage I can’t run it on the actual build servers until tomorrow so I’m going to post this anyway since you just <em>know</em> it will start failing again just as soon as I think I’ve got it fixed.</p><p> Update 10 seconds after posting: Yep, there it goes, failed again.</p>]]></content:encoded> <wfw:commentRss>http://www.symphonious.net/2010/11/24/controlling-focus-in-firefox/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>JavaScript Testing in the Cloud</title><link>http://www.symphonious.net/2010/06/08/javascript-testing-in-the-cloud/</link> <comments>http://www.symphonious.net/2010/06/08/javascript-testing-in-the-cloud/#comments</comments> <pubDate>Tue, 08 Jun 2010 17:25:30 +0000</pubDate> <dc:creator>Adrian Sutton</dc:creator> <category><![CDATA[Build Systems]]></category> <category><![CDATA[JavaScript]]></category> <guid
isPermaLink="false">http://www.symphonious.net/?p=1347</guid> <description><![CDATA[One of the things Ephox is contributing to TinyMCE is a build farm to run the automated tests in various browsers which winds up publishing it’s results for all to see. This has been pretty interesting to set up and there are a range of different approaches. Matt Raible posted recently about his experiences using [...]]]></description> <content:encoded><![CDATA[<p> One of the things <a
href="http://tinymce.ephox.com">Ephox is contributing to TinyMCE</a> is a build farm to run the automated tests in various browsers which <a
href="http://tinymce.ephox.com/test-results">winds up publishing it’s results for all to see</a>. This has been pretty interesting to set up and there are a range of different approaches.  Matt Raible posted recently about <a
href="http://raibledesigns.com/rd/entry/running_selenium_tests_on_sauce">his experiences using Selenium with Sauce Labs</a>. I had initially looked into that as well, but was worried about a few of the issues Matt hit and TinyMCE had already written a lot of tests using <a
href="http://docs.jquery.com/QUnit">QUnit</a> rather than Selenium.</p><p> Instead I’ve wound up with quite a neat little set up based around Hudson. The master Hudson server is running on an EC2 instance, so the configuration and control interface is easily available from anywhere. However, EC2 can only run specific Windows server versions so it can’t provide all the browsers we need. Instead, the slaves are run as VMWare instances back behind the firewall in our UK office. They use Hudson’s webstart slave support so they connect out to the master, avoiding the need to punch a hole in the firewall. At this stage we have Windows XP, Vista and Windows 7 running a suite of browsers (roughly grouped as “old”, “previous version” and “latest” on each of those VMs). We’re also using the master server to run the Linux browser tests.</p><p> The next challenge was to get QUnit working with continuous integration so it’s results are reported back correctly. Unlike JSUnit or Selenium, QUnit doesn’t really have anything like this built in, though it does provide some hooks to make it possible. I simply took the JSUnit server, which is completely agnostic about what actually runs in the browser, and a simple HTML and JavaScript harness to marshall the QUnit test results and submit them back to the server.</p><p> Finally we want to set up a workflow so tests on different VMs can run in parallel but builds are only published if they actually pass all the tests. To achieve that, I’ve split the build into three parts:</p><ol><li> The build itself. Minifies the JavaScript and various other stuff to build the zip package that would be distributed. At this stage, that zip is just left on the Hudson server and not published anywhere. It may be possible to do this using the “touchstone build” option for the configuration matrix type but I haven’t investigated that yet.</li><li> The test project is set up as a configuration matrix type, so Hudson automatically duplicates the build on any slaves that are chosen (in this case, all of them plus the master to cover Linux). Each slave then downloads the zip package from the previous build phase and runs the tests. If any of the VM builds fail the test project is considered to fail and the process stops.</li><li> Finally if the tests all pass the packaging project starts which simply publishes the zips to various places. It uses the workspace clone plugin to effectively pick up where the build step left off.</li></ol><p> With this approach we are essentially building a full release candidate, testing it and then finally releasing it. While the tests don’t exercise it fully enough, this has the advantage of actually testing that the intended files are making it into the zip. Most unit test setups run the tests based on just the compiled classes with no guarantee that they’ll come out the same way after being packaged up. While I was just grabbing the full zip out of pure convenience, it is nice to know that catastrophic packaging problems would be picked up by the tests now and I can quite easily build out more tests to pick up smaller errors as well.</p><p> Current issues:</p><ul><li> The slaves are extremely good at reconnecting after the server reboots, but if the slaves themselves reboot sometimes their authentication has timed out and they can’t re-download the JNLP file without help. It would be nice if I could specify authentication credentials for Java WebStart on the command line.</li><li> The test project is mostly triggered by the build project completing, but it also polls for changes in the git repository of the test harness. That way if we change the harness it verifies that all the projects that test harness is used by will still build and pass successfully rather than giving us a surprise failure on a later, unrelated change. Unfortunately you can’t decide which Hudson instance will be the one polling for updates and winds up distributing it out to the remote slaves (in itself a pretty stupid thing to do in this particular setup). When you restart the server though it takes a few moments for the slaves to reconnect and in the mean time Hudson moves the polling back to the master server, which has an out of date workspace for that project so it almost always detects a change.  The net result is that restarting the server causes all the tests to run for no reason.</li><li> The matrix project type basically makes a set of sub-projects for each VM so things like Twitter notifications report on multiple cryptic projects rather than just reporting on the overall project (hence I’ve given up on the twitter notifications).</li></ul><p> Things to improve:</p><ul><li> Add a Mac into the mix &#8211; Safari is covered from the Windows builds anyway but there can be subtle differences between versions on different OS’s and since it’s all automated, we may as well be thorough.</li><li> Make the slaves redundant. I’d like to effectively duplicate each of the slave VMs so that I have a “latest browser” VM pool rather than a specific VM. That way if one of the VM fails to reconnect or isn’t available for some reason, there is a reasonable chance that the other one will be available. If they’re both up and running it gives extra throughput which is always good too.</li></ul><p> Overall, I’m quite pleased with the setup and look forward to growing the test coverage for TinyMCE.</p>]]></content:encoded> <wfw:commentRss>http://www.symphonious.net/2010/06/08/javascript-testing-in-the-cloud/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Building in the Cloud</title><link>http://www.symphonious.net/2010/04/26/building-in-the-cloud/</link> <comments>http://www.symphonious.net/2010/04/26/building-in-the-cloud/#comments</comments> <pubDate>Mon, 26 Apr 2010 13:59:07 +0000</pubDate> <dc:creator>Adrian Sutton</dc:creator> <category><![CDATA[Build Systems]]></category> <category><![CDATA[Code and Geek Stuff]]></category> <guid
isPermaLink="false">http://www.symphonious.net/?p=1334</guid> <description><![CDATA[Once upon a time, the state of the art for building software projects was to have a continuous integration server so your builds were repeatable, reliable and performed in a controlled environment. As a bonus they also ran a whole suite of automated tests so you knew that what came out was at least reasonable [...]]]></description> <content:encoded><![CDATA[<p> Once upon a time, the state of the art for building software projects was to have a continuous integration server so your builds were repeatable, reliable and performed in a controlled environment. As a bonus they also ran a whole suite of automated tests so you knew that what came out was at least reasonable quality.</p><p> Those days have gone.</p><p> These days, it’s far more common to have a build and test farm churning away to handle the volume of tests, various different modules and projects that are all built separately and of course the requirement to run the tests on a huge variety of different platforms and environments. VMWare has been a big help in this area for quite some time, effectively letting teams build a private cloud before it was cool to call it a private cloud. Now with the growing availability of public cloud instances, it makes a lot of sense to stop buying and maintaining hardware and simply move the whole system into the public cloud.</p><p> I’ve recently had the opportunity to try that out with a new project but have been so focussed on getting things up and running that I haven’t found the time to write up the details and my thoughts about it all. I’m going to try and go back over things so I have a record of the things I’ve learnt, starting with this post and some thoughts on the advantages and disadvantages of moving builds into a public cloud<a
class="footnote" id="footlink1:1272287358179" href="#footnote1:1272287358179">1</a>.</p><h2> Advantages</h2><h3> Power on Demand</h3><p> If you have a lot of projects, you can use the dynamic scaling of the cloud to add more build servers for those times when everyone seems to commit at once and avoid big backlogs, without paying for that hardware all the time. This is less useful when you only have one project, at least with EC2. Since it takes so long to spin up a new instance, if you probably don&#39;t want to have servers that will be needed for every build spun down when not in use &#8211; it might reduce the EC2 build, but it will make your builds too slow.</p><p> Even so, it is a lot easier to justify continuously running a number of EC2 servers so you can run tests in parallel than it is to justify buying a number of physical servers yourself. Not to mention how much easier it is to setup and maintain multiple instances.</p><h3> No More Down Time</h3><p> If only it were that simple.  Moving to the public cloud won’t eliminate down time, but it does do a pretty good job of making hardware faults someone else’s problem. Even if a hardware fault or something else does take out a critical part of your build system, it’s usually quite simple to run up a replacement and get everything working again. You never have to pay for idle backup hardware or waste time repairing machines.  Plus, with the ability to take a snapshot and store it, backups are easier than ever both to take and to restore.</p><h3> Available Anywhere</h3><p> Moving to a public cloud means that the current build status is available without any hassle from anywhere in the world.  Basically, it gets moved out from behind the corporate firewall.  This isn’t an advantage for everyone &#8211; many companies already have a very well setup and maintained VPN that is routinely used. While this can work pretty seamlessly, it’s surprisingly complex to get VPNs up and running for everyone in the company, resulting in plenty of time being wasted on system administration and providing tech support. For developers who mostly work in the office, the barrier of setting up VPN may be high enough to prevent them occasionally working from home or makes them less productive when they are occasionally on the road.</p><h3> Accessing Builds</h3><p> With a build server in the sky, everyone in your company can easily grab the builds and it’s often quicker to deploy them to the website or other places.  I’ve taken advantage of the fast and free data transfer between EC2 and S3 so keep a complete backlog of builds available for support purposes.  Previously, this was done with a  shared drive and every so often we ran out of space and had to delete some of the less likely to be needed builds<a
class="footnote" id="footlink2:1272289368056" href="#footnote2:1272289368056">2</a>. S3 doesn’t ever run out of space which is nice.</p><p> If you have dependency management, you will probably want to move the repository into the cloud as well &#8211; either on the master build server or a dedicated instance if you have enough demand for that.</p><h3> Competitive Advantage</h3><p> One of the biggest misconceptions I’ve come across  when dealing with build systems is the idea that “we’re an IT company, this kind of thing is a key competitive advantage”. Continuous integration, automated testing and deployment technologies can all be competitive advantages, but maintaining the hardware they run on almost never is. Maintaining hardware or software for a source control system is almost never a competitive advantage, unless your product happens to be a source control system.</p><p> If you can stop spending money buying hardware, and you can stop wasting time maintaining servers internally, you can spend more time and money on the software side of your build systems or on developing your products and <em>that’s</em> where you get the real competitive advantage. There’s no such thing as an “IT company”, it’s just too broad a category &#8211; find the specific area that you should build competitive advantages in and then focus in on that and get someone else to worry about providing anything else.</p><h2> Disadvantages</h2><h3> Security</h3><p> Everyone worries about security in the cloud and often needlessly so, but moving the build server outside your corporate firewall makes it less secure.  On the other hand, you then wind up paying more attention to properly securing it rather than just depending on the firewall, so it’s not all bad news. Since the build server has to have access to your source code, it is a vector of attack that you really want to take seriously and make sure you mitigate.</p><h3> Accessing Source Control</h3><p> If the build server is outside the firewall, your source code will need to be too. For small to mid-size companies, I’ve come to think that hosted source control is the right way to go anyway &#8211; why would you want to waste your time maintaining source control servers? Subversions isn’t particularly nice to use if the server is on the other side of the world, but the distributed version control systems like git have no difficulties with it. The way I see it is that if it’s worth hosting either your source control or your build servers internally, it’s worth hosting both internally.  If not, move them both to a hosted environment and you’ll have more time to focus on developing the software that actually makes you money.</p><h3> Accessing Builds</h3><p> If all of or most of your development team is in one office, having the builds stored externally is a bit of a disadvantage because now you have longer to wait while they download, and in a backwards, outdated country like Australia<a
class="footnote" id="footlink3:1272289470367" href="#footnote3:1272289470367">3</a>, it can also chew into the limited download quota you have.</p><h2> When is This a Bad Idea?</h2><p> I can think of two situations when this may not make sense:</p><ol><li> You’re a big company and can take advantage of economies of scale all by yourself.  IBM, Apple, Microsoft and especially Google can maintain a private cloud cheaper than they could move it to a public cloud. I’m not sure where the cut off would be, but I suspect companies much smaller than those would still be included in this batch.</li><li> You have a centrally located team, slow internet and/or a slow source control system. Moving stuff externally doesn’t make sense if it becomes too slow to access.  However, I’d still be looking to fix the internet and source control &#8211; a centrally located team would still be better off without maintaining hardware if it was fast enough.</li></ol><p> Why else wouldn’t you want to do this?</p><p
class="footnote"> <a
href="#footlink1:1272287358179" id="footnote1:1272287358179">1</a> &#8211; I use Amazon EC2 pretty much exclusively as a cloud provider but I’d definitely be interested in hearing about other options and what benefits they might bring.  I suspect pretty much all of this would apply regardless of which cloud provider you went with though. <a
class="footnotereturn" href="#footlink1:1272287358179">↩</a></p><p
class="footnote"> <a
href="#footlink2:1272289368056" id="footnote2:1272289368056">2</a> &#8211; naturally we could go and rebuild them based on the source code in subversion, but who can be bothered when you could just grab a pre-built version?<a
class="footnotereturn" href="#footlink2:1272289368056">↩</a></p><p
class="footnote"> <a
href="#footlink3:1272289470367" id="footnote3:1272289470367">3</a> &#8211; at least in terms of internet access<a
class="footnotereturn" href="#footlink3:1272289470367">↩</a></p>]]></content:encoded> <wfw:commentRss>http://www.symphonious.net/2010/04/26/building-in-the-cloud/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>Stop Concatenating CSS Files</title><link>http://www.symphonious.net/2010/04/05/stop-concatenating-css-files/</link> <comments>http://www.symphonious.net/2010/04/05/stop-concatenating-css-files/#comments</comments> <pubDate>Mon, 05 Apr 2010 14:49:49 +0000</pubDate> <dc:creator>Adrian Sutton</dc:creator> <category><![CDATA[Build Systems]]></category> <category><![CDATA[Code and Geek Stuff]]></category> <guid
isPermaLink="false">http://www.symphonious.net/?p=1326</guid> <description><![CDATA[One of the common examples of the limits of Maven and other “strict” build tools was how difficult is to concatenate CSS files together as part of the build. It’s nice to be able to split CSS files up to categorize things but the extra HTTP requests really slow down page loads, so the build [...]]]></description> <content:encoded><![CDATA[<p> One of the common examples of the limits of Maven and other “strict” build tools was how difficult is to concatenate CSS files together as part of the build. It’s nice to be able to split CSS files up to categorize things but the extra HTTP requests really slow down page loads, so the build should concatenate them back together.  What I’ve come to realise though, is that building a custom concatenation script is just another instance where people are reinventing the wheel in build systems, and getting less power as a result.</p><p> Instead of using plain CSS and concatenating, use something like <a
href="http://lesscss.org/">LESS</a> to compile the CSS. You can specify the CSS files to import with the usual @import statement and LESS will do the concatenation for you. This is particularly nice since the order of import is specified right in the CSS files, rather than in the build script and you can build full hierarchies of imports. Plus, you get the full power of LESS, with variables, includes etc etc if and when you want to use it. There are a range of CSS compilers beyond LESS and a range of ways LESS can be integrated into a variety of build tools, however I wound up just doing it dynamically with the <a
href="http://www.asual.com/lesscss/">LESS Servlet</a>. Then it sets headers appropriately and optimises CSS and JavaScript with YUI compressor while it’s at it.</p><p> This of course leaves me wondering if something like <a
href="http://code.google.com/closure/">Google’s Closure</a> could do the same kind of thing for JavaScript files. The question being not just, can Google’s Closure concatenate JavaScript files for me, but rather can it do that <em>plus</em> give me a bunch of other useful tools for free?</p>]]></content:encoded> <wfw:commentRss>http://www.symphonious.net/2010/04/05/stop-concatenating-css-files/feed/</wfw:commentRss> <slash:comments>3</slash:comments> </item> <item><title>Using Ivy for Dependency Management</title><link>http://www.symphonious.net/2010/01/25/using-ivy-for-dependency-management/</link> <comments>http://www.symphonious.net/2010/01/25/using-ivy-for-dependency-management/#comments</comments> <pubDate>Mon, 25 Jan 2010 14:59:30 +0000</pubDate> <dc:creator>Adrian Sutton</dc:creator> <category><![CDATA[Build Systems]]></category> <guid
isPermaLink="false">http://www.symphonious.net/?p=1297</guid> <description><![CDATA[At first glance, Ivy looks like a re-implementation of Maven’s dependency management that works nicely with ant, and to some degree it is, but it also adds some pretty significant improvements and some pretty significant complexity. Maven Compatibility Firstly, Ivy is compatible with Maven repositories, so if you think the way Maven manages dependencies is [...]]]></description> <content:encoded><![CDATA[<p> At first glance, <a
href="http://ant.apache.org/ivy/">Ivy</a> looks like a re-implementation of Maven’s dependency management that works nicely with ant, and to some degree it is, but it also adds some pretty significant improvements and some pretty significant complexity.</p><h3> Maven Compatibility</h3><p> Firstly, Ivy is compatible with Maven repositories, so if you think the way Maven manages dependencies is perfect, but don’t want to buy into the rest of Maven, Ivy provides a good answer. The configuration is a little bit different and you’ll have to learn a little bit about Ivy’s configurations which are both more powerful and more complex than Maven’s dependency “scope”, but you won’t have to go too far into them.</p><p> Ivy will use the Maven 2 repository by default so all the same libraries are available &#8211; complete with all the metadata problems.</p><h3> Ivy Configurations</h3><p> Configurations are probably the biggest difference between Ivy and Maven’s dependency management. At the simplest level they are roughly equivalent to setting the scope attribute in Maven. It lets you choose whether a library is required only for compilation, if it should be included in the packaged WAR/EAR or if it’s used only for testing. Since Ivy doesn’t actually build the project, what a configuration means is a lot more flexible than what I scope means in Maven. Each Ivy setup needs to setup the configurations it needs from scratch and it’s up to the Ant build process to ensure the libraries are used as intended.</p><p> If you import a project from the Maven repository, Ivy will convert the various scopes into the following configurations:</p><table
border="1" width="100%" cellspacing="0" cellpadding="0" class="PrimaryBordersTable"><tr><th
id="id_6273"> Name</th><th
id="id_6274"> Description</th><th
id="id_6275"> Example Library</th></tr><tr><td
headers="id_6273"> default</td><td
headers="id_6274"> runtime dependencies and master artifact can be used with this conf</td><td
headers="id_6275"></td></tr><tr><td
headers="id_6273"> master</td><td
headers="id_6274"> contains only the artifact published by this module itself, with no transitive dependencies</td><td
headers="id_6275"> The project’s jar itself</td></tr><tr><td
headers="id_6273"> compile</td><td
headers="id_6274"> this is the default scope, used if none is specified. Compile dependencies are available in all classpaths</td><td
headers="id_6275"> commons-lang</td></tr><tr><td
headers="id_6273"> provided</td><td
headers="id_6274"> this is much like compile, but indicates you expect the JDK or a container to provide it. It is only available on the compilation classpath, and is not transitive</td><td
headers="id_6275"> Servlet APIs</td></tr><tr><td
headers="id_6273"> runtime</td><td
headers="id_6274"> this scope indicates that the dependency is not required for compilation, but is for execution. It is in the runtime and test classpaths, but not the compile classpath</td><td
headers="id_6275"> An AOP runtime library?</td></tr><tr><td
headers="id_6273"> test</td><td
headers="id_6274"> this scope indicates that the dependency is not required for normal use of the application, and is only available for the test compilation and execution phases</td><td
headers="id_6275"> JUnit</td></tr><tr><td
headers="id_6273"> system</td><td
headers="id_6274"> this scope is similar to provided except that you have to provide the JAR which contains it explicitly. The artifact is always available and is not looked up in a repository</td><td
headers="id_6275"> ??</td></tr><tr><td
headers="id_6273"> sources</td><td
headers="id_6274"> this configuration contains the source artifact of this module, if any</td><td
headers="id_6275"> Source for the project</td></tr><tr><td
headers="id_6273"> javadoc</td><td
headers="id_6274"> this configuration contains the javadoc artifact of this module, if any</td><td
headers="id_6275"> JavaDoc for the project</td></tr><tr><td
headers="id_6273"> optional</td><td
headers="id_6274"> contains all optional dependencies</td><td
headers="id_6275"> Anything optional</td></tr></table><p> The three most commonly used configurations for dependencies are compile, provided and test &#8211; most projects will only ever need to add dependencies in those categories. The master, sources and javadoc configurations typically don’t contain any dependencies, they are used for publishing the results of the build into &#8211; the same configurations defined here are used by other projects that depend on this one. The default configuration is provided to make this easy, by including all the runtime dependencies and the project’s jar itself in one configuration.</p><p> It’s also worth nothing that configurations can extend each other. In the Maven import, runtime extends compile so any libraries you compile against are also available at run time. Default extends runtime and master. You could of course ignore the extends functionality and just include multiple lib dirs on the classpath within your normal ant script as you would if the jars were directly checked in to source control, but the functionality is reasonably simple and makes it very explicitly clear what jars are on what classpath<a
class="footnote" id="footlink1:1264424269169" href="#footnote1:1264424269169">1</a>.</p><p> My approach has been to stick with these configurations &#8211; they’re simple enough but cover every conceivable situation that I can currently imagine. The only real difference I’m not currently using the master configuration &#8211; the produced jars are just put directly into default. That means you can’t easily require the library without any dependencies, but it means that the defaults can be used for what most libraries produce (a single jar file with the same name as the project and in the default configuration).</p><h3> Ivy Repositories</h3><p> Ivy has it’s own concept of a repository that uses Ivy descriptor files instead of the Maven POM files and gives the full power, flexibility and complexity of Ivy’s configuration concepts. The configurations might be handy, but what I find most useful, is the fact that Ivy supports multiple different types of repositories.  So instead of having to run specific software to provide the repository, it can be accessed via sftp, ssh, a shared drive or even subversion. This makes setting up your own repository significantly easier &#8211; it’s quite likely you already have a server that’s available via ssh somewhere. I also like the fact that the whole Ivy configuration can be included in the project itself, so once you check out the source code, you have all the config settings you need to be able to build it<a
class="footnote" id="footlink2:1264426193822" href="#footnote2:1264426193822">2</a>.</p><h4> Importing Libraries</h4><p> Ivy can pull libraries from the public maven repository and import them into your private one which makes it reasonably quick to spin up a private repository and get rid of the dependency on the public one altogether. However, it’s still a fairly slow process and takes up the bulk of the time required to get Ivy up and running.  That said, it immediately solves a <em>lot</em> of headaches about incorrect meta-data or missing libraries in the maven repository.</p><p> What I found was missing however, was a simple tool to add new libraries that don’t exist in the Maven repository. For a single jar, it’s pretty easy to create the directory structure and an ivy.xml file for it, but when you have a large number like the GData APIs, it can take up a huge amount of time.  I whipped up a simple bash script to work out most of the meta-data from a jar file (module name and version number), create the directory structure and a simple ivy.xml file then upload it to the repository. It doesn’t add the dependencies automatically but that’s easy once the directory structure and basic ivy.xml has been created.</p><h4> Namespaces</h4><p> One of the most common problems with the Maven repository is the number of Apache libraries that still use the Maven 1 naming scheme. For example Commons IO is available under <em>both</em> the org.apache.commons group <em>and </em>the commons-io group. To Maven and Ivy, the different groups mean it’s actually a different library so it can potentially wind up on the classpath twice. When you import libraries from the Maven repository, ivy lets you configure namespaces to avoid this problem.  Essentially, Ivy will rewrite the group name to consistently use one or the other, resulting in a more consistent repository and no duplicate jars on the classpath. The rename is done both for the imported library and anything else you import that depends on it so things automatically point to the right place.</p><h3> Actual Usage</h3><p> Actually using Ivy is really quite straight forward.  There are a lot of different ant tasks you can use, largely due to the huge amount of flexibility Ivy provides, but you can also keep it quite straight forward.  I’ve got five basic uses at the moment:</p><ol><li> configure &#8211; I’m calling this outside of any target at the moment so it always happens before anything else.  It sets up Ivy using the configuration file designed for this project.  So it has the right configurations set up and points to the private repository instead of the default Maven one.</li><li> retrieve &#8211; actually calculate the dependencies and link them into the specified directories.  Each configuration gets the jar files placed in it’s own sub-directory.  From then on, to use the dependencies in the ant script, just point at the appropriate directory.  I also set this to use symlinks when possible so the files actually stay in Ivy’s cache directory and it just creates a symlink to save some time.</li><li> Inline retrieves &#8211; the retrieve task can also be configured to retrieve a library that you specify directly via attributes instead of in an ivy.xml file.  This is really handy for things that the build scripts itself want to use, like a scala compiler or cobertura. Otherwise each project would have to have the same dependencies.</li><li> Import &#8211; I have an ant task set up specifically to make it easy to import libraries from the Maven repository.  It uses a slightly different settings file (which includes the Maven repository) and prompts for the group, module and revision to import.</li><li> buildlist &#8211; this is a handy little task for building sub-modules within a project. It looks at each project’s dependencies and calculates the correct build order which you can then pass in to subant.  Very much like the Maven reactor.</li></ol><p> The nice thing is that Ivy just plugs in to your existing ant file without many changes at all.</p><h3> Tracking Versions</h3><p> Ivy has some nice ideas for working with versions which I haven’t found in Maven before though they may exist. Firstly, it can generate a build number by looking at the latest version available in the repository and adding one which is much better than having a normal ant buildnumber file on a shared drive somewhere.  Secondly, when Ivy published an artifact to the repository, it rewrites the ivy.xml to include the specific version of dependencies that it was built with, so anything that depends on it will get known good libraries, even if it was using a SNAPSHOT style build.  In Ivy the SNAPSHOT version is equivalent to latest.integration, but it always generates some form of version number when the build is published, so you never get a latest.integration version in the repository.  By default it uses a date stamp which actually works out really well.</p><p> Aside from latest.integration you can also specify a range of restrictions for acceptable versions which is handy but probably too complex to be worth the effort in most cases.  Ivy already resolves most version conflicts automatically by evicting the older versions which works fine as long as the libraries maintain backwards compatibility<a
class="footnote" id="footlink3:1264429445570" href="#footnote3:1264429445570">3</a>. So when commons-httpclient requires commons-logging 1.0 but commons-io requires commons-logging 1.1, you wind up with just commons-logging 1.1 on the classpath and everything works.</p><h3> Sharing Projects and Modules</h3><p> Ultimately, the main reason I was looking to move away from jar files in source control was to make it easy to share modules between different projects. Right now, that would basically have to be done by either forking the code, occasionally building a jar and dropping it in or using svn:externals &#8211; none of which are particularly appealing.  With Ivy, the buildlist can handle any submodule being dumped into the project directory and you can pull a version of the module from the repository regardless of whether or not you have the source code checked out for it. There are now two modes you can use sub-modules in:</p><ol><li> Just declare it as a dependency and Ivy will grab the version from the repository. Just like including a jar in source control but a little easier.</li><li> Declare it as a dependency and check out a copy of the source as a submodule of the project you’re currently working on. This then gets picked up by the Ivy buildlist task and automatically inserted in the right place in the build process.  Now you can easily make changes to the module and use them in your outer project without doing a full release.  You only need to push a new version into the shared repository when you’ve got the bugfix or new API completely sorted out and ready for others to use. In the mean time, everything still builds with a single execution of ant.</li></ol><h3> Speed</h3><p> The project I tested this out on has a lot of dependencies &#8211; it took ages to import them all into the private repository, many required manually fixing up metadata problems as well. With the jar files in subversion, the build server could check out the full source (including libraries) and build the project in 3-4 minutes (the build server and the subversion repository have a gigabit connection between them). The first build it did with Ivy took the build time up to about 25 minutes as it downloaded all the dependencies (the Ivy repository was in the US, the build server was in Australia), but because Ivy keeps a local cache of everything it downloaded the second build went back down to the usual 3-4 minutes.</p><p> Ivy can be a bit slow at calculating dependencies though I probably wouldn’t have noticed it if the project didn’t have as many submodules, each of which require Ivy to calculate the dependencies before building in. In the grand scheme of things though, the time that Ivy spends working out dependencies is small enough to be insignificant compared to whatever the rest of the build is doing. Since the jar files are just dropped in to a normal directory, it’s also easy to add a flag to completely skip Ivy and use the existing dependencies if you do have small tasks that are run really frequently. With a remote subversion server you can waste <em>far</em> more time updating, moving or deleting jar files.</p><h3> Summary</h3><p> I think Ivy is a pretty clear winner.  It’s simple to set up a private repository and avoid all the common problems people hit with the Maven repository, what complexity Ivy adds can be isolated to the template build scripts so individual projects stay quite simple and with buildlist it’s now easy to share modules between projects which had been causing me a lot of headaches.</p><p> The downside: there’s a reasonable amount of learning that the team will have to take on and at first glance Ivy looks like it adds more complexity than benefit so getting buy-in isn’t a guarantee.</p><p
class="footnote"> <a
href="#footlink1:1264424269169" id="footnote1:1264424269169">1</a> &#8211; once you “resolve” the dependencies you can simply look in the appropriate directory and see all the jar files for that configuration in one place<a
class="footnotereturn" href="#footlink1:1264424269169">↩</a></p><p
class="footnote"> <a
href="#footlink2:1264426193822" id="footnote2:1264426193822">2</a> &#8211; I also put the Ivy jar files in subversion so that it’s available and doesn’t need to be installed separately. So the requirements to build are just a JDK, ant and a checked out source tree<a
class="footnotereturn" href="#footlink2:1264426193822">↩</a></p><p
class="footnote"> <a
href="#footlink3:1264429445570" id="footnote3:1264429445570">3</a> &#8211; and if they don’t you’re in a lot of trouble as the project that wanted the newer version is unlikely to work with an older version anyway.<a
class="footnotereturn" href="#footlink3:1264429445570">↩</a></p>]]></content:encoded> <wfw:commentRss>http://www.symphonious.net/2010/01/25/using-ivy-for-dependency-management/feed/</wfw:commentRss> <slash:comments>3</slash:comments> </item> <item><title>Ant, Subant and Basedir</title><link>http://www.symphonious.net/2010/01/25/ant-subant-and-basedir/</link> <comments>http://www.symphonious.net/2010/01/25/ant-subant-and-basedir/#comments</comments> <pubDate>Mon, 25 Jan 2010 10:08:51 +0000</pubDate> <dc:creator>Adrian Sutton</dc:creator> <category><![CDATA[Build Systems]]></category> <category><![CDATA[Code and Geek Stuff]]></category> <guid
isPermaLink="false">http://www.symphonious.net/?p=1294</guid> <description><![CDATA[Here’s an important lesson for people combining ant scripts &#8211; the way basedir is calculated is very unlikely to be what you expect. In particular, if you combine the &#60;ant&#62; task with the &#60;subant&#62; task you’re probably in for a surprise. I learnt this important life lesson when the improved build scripts I’d been working [...]]]></description> <content:encoded><![CDATA[<p> <img
alt="Apache Ant logo" width="115" height="75" src="http://www.symphonious.net/wp-content/uploads/2010/01/project-logo_6038245254255283799.gif" style=" float: left;" />Here’s an important lesson for people combining ant scripts &#8211; the way basedir is calculated is very unlikely to be what you expect. In particular, if you combine the &#60;ant&#62; task with the &#60;subant&#62; task you’re probably in for a surprise.</p><p> I learnt this important life lesson when the improved build scripts I’d been working on failed on the build server even though it worked perfectly on my machine. The difference is that the build server is running cruise control and it has a wrapper ant script which checks out a fresh copy of the project then uses the &#60;ant&#62; task to build it. The ant task was:</p><pre>
<code>&#60;ant antfile=&quot;build.xml&quot; target=&quot;dist&quot; dir=&quot;projectDir&quot; /&#62;</code>
</pre><p> As far as that main antfile is concerned, everything is perfect &#8211; the basedir is the directory that it’s build.xml is in and all is good with the world. However, if that build.xml happens to use subant, the basedir <em>will not be changed</em>. Basically, basedir is now a user configured property rather than a calculated value so it doesn’t get changed. However, if you instead use:</p><pre>
<code>&#60;ant antfile=&quot;projectDir/build.xml&quot; target=&quot;dist&quot; /&#62;</code>
</pre><p> It all works out. The main build.xml still gets the basedir as projectDir but when it uses subant, the basedir will be automatically changed to whatever directory the build file subant points to is in.</p><p> The behavior is explained in <a
href="https://issues.apache.org/bugzilla/show_bug.cgi?id=29658">this bug report</a> which is closed as WONTFIX for backwards compatibility. Thankfully ant 1.8 adds a useNativeBasedir attribute which provides much more predictable basedir behavior for the ant task.</p>]]></content:encoded> <wfw:commentRss>http://www.symphonious.net/2010/01/25/ant-subant-and-basedir/feed/</wfw:commentRss> <slash:comments>2</slash:comments> </item> <item><title>Three Types of Ant Scripts</title><link>http://www.symphonious.net/2010/01/22/three-types-of-ant-scripts/</link> <comments>http://www.symphonious.net/2010/01/22/three-types-of-ant-scripts/#comments</comments> <pubDate>Fri, 22 Jan 2010 09:27:22 +0000</pubDate> <dc:creator>Adrian Sutton</dc:creator> <category><![CDATA[Build Systems]]></category> <guid
isPermaLink="false">http://www.symphonious.net/?p=1292</guid> <description><![CDATA[Bryan comments on the three types of ant scripts: In my experience, there are three types of Ant scripts that you encounter &#34;in the wild&#34;: Small Ant scripts, generally Java-only, which can use most of Ant&#39;s default behaviors and are clear and simple. A lot of open source build scripts are this way. Serious commercial [...]]]></description> <content:encoded><![CDATA[<p> <a
href="http://bryanpendleton.blogspot.com/2010/01/ant-version-18-is-nearing-release.html">Bryan comments on the three types of ant scripts</a>:</p><blockquote><p> In my experience, there are three types of Ant scripts that you encounter &quot;in the wild&quot;:</p><ul><li> Small Ant scripts, generally Java-only, which can use most of Ant&#39;s default behaviors and are clear and simple. A lot of open source build scripts are this way.</li><li> Serious commercial Ant scripts written before macrodef and import became available. These are generally impossible to understand and evolve, and the reality is that a small cadre of Build Wizards keep them running. Such systems often involve a substantial number of custom Ant tasks.</li><li> Serious commercial Ant scripts written to use macrodef and import. In my experience, the need for custom Ant tasks drops way off with Ant releases post-1.6.</li></ul></blockquote><p> This really does ring true to me.  Ant scripts can fairly quickly become unwieldy and difficult to work with if you aren’t using import and macrodef, but with them you can achieve so much more without the complexity getting out of hand. They won’t absolve you of the need to properly understand ant and the declarative paradigm it wants you to work with, but it’s much more approachable.</p><p> If I can ever get someone to add the optional dependencies for scripting support on our build servers<a
class="footnote" id="footlink1:1264152423184" href="#footnote1:1264152423184">1</a> I may well find they help a lot too.</p><p
class="footnote"> <a
href="#footlink1:1264152423184" id="footnote1:1264152423184">1</a> &#8211; which happen to be Windows boxes, behind a firewall on the other side of the world from me, so not easy to make remote changes on <a
class="footnotereturn" href="#footlink1:1264152423184">↩</a></p>]]></content:encoded> <wfw:commentRss>http://www.symphonious.net/2010/01/22/three-types-of-ant-scripts/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>Comparing Build Systems</title><link>http://www.symphonious.net/2010/01/11/comparing-build-systems/</link> <comments>http://www.symphonious.net/2010/01/11/comparing-build-systems/#comments</comments> <pubDate>Mon, 11 Jan 2010 12:58:10 +0000</pubDate> <dc:creator>Adrian Sutton</dc:creator> <category><![CDATA[Build Systems]]></category> <guid
isPermaLink="false">http://www.symphonious.net/?p=1274</guid> <description><![CDATA[After spending some time thinking about and using different build systems, I can’t say I really like any of them all that much. I know have a reasonably complex project, using submodules that can be built with ant, buildr, maven and gradle &#8211; with varying degrees of support for the Ephox specific requirements and reporting. [...]]]></description> <content:encoded><![CDATA[<p> After spending some time <a
href="http://www.symphonious.net/2010/01/04/on-build-systems/">thinking about</a> and using different build systems, I can’t say I really like any of them all that much. I know have a reasonably complex project, using submodules that can be built with ant, buildr, maven and gradle &#8211; with varying degrees of support for the Ephox specific requirements and reporting.</p><h3> <a
href="http://maven.apache.org/">Maven</a></h3><p> Ah, the Java world’s favorite whipping boy. The more I play with Maven, the more I start to understand why it gets such a bad wrap: it’s too easy to get started and do it all wrong. Maven is not a build tool that is quick to start using &#8211; it requires planning, common conventions, a number of extras systems such as repository servers be set up and templates to be designed. However, Maven does an unfortunately good job of working if you just create a simple pom.xml and run mvn.</p><p> If you want Maven to work reliably though, you need to set up a bunch of stuff:</p><ul><li> Private repository servers, including vetting all the meta-data that goes into it. Don’t just import the central Maven repository.</li><li> A company specific parent POM. This should specify explicit versions for each Maven plugin, point the project at the private repository servers and anything else that is standard across the company.</li><li> Build plugins for anything custom you need. Real Maven plugins are the best way to extend things &#8211; trying to put it all in your pom.xml or similar build scripts rapidly gets too complex and unmaintainable.</li><li> Strictly follow the Maven way.</li></ul><p> Make no mistake, that’s a lot of work, but it sets up a very robust, enterprise build system and most of it only needs to be done once for the entire company, so starting a project from then on does become pretty simple.</p><p> All in all, it’s more work than I really want to take on &#8211; especially the building of custom plugins. Ephox doesn’t follow the Maven way strictly enough either &#8211; the most problematic area being how to release and version snapshots.</p><h3> <a
href="http://buildr.apache.org/">Buildr</a></h3><p> Lots of people talk about using rake to build Java projects, but rake by itself simple doesn’t know enough about Java to really shine. Buildr is a layer over rake that adds Java knowledge. I actually quite like Buildr and think it has a fair bit of promise.</p><p> It can use the Maven repository for dependencies, so if you go that way you need to set up your own private repository again. Support for Thankfully, Buildr can also use plain jar files so if you don’t want to go the repository route, you don’t have to. The big downside is how complex it can be to get transitive dependencies working &#8211; partly by design and partly due to bugs and current limitations.</p><p> Buildr can run on either C-Ruby or JRuby. Start-up is faster on C-Ruby, but JRuby can run things like Javac without spawning a new JVM, so it fairly quickly starts to make up the time difference. Installing either version is quite easy.</p><p> It is a little odd to be writing the build script for a Java project in Ruby. The language difference doesn’t really matter, but having a different set of libraries for things like IO and file system stuff is an unfortunate overhead. If you’re using Ruby in some other form, it’s no problem, otherwise it’s extra training and ramp-up cost.</p><p> I also had a <em>lot</em> of problems because Buildr was including stuff on the test classpath by default. Some version of JUnit and JMock are meant to be included, but it varies between versions and the documentation doesn’t always match up with what happens. Given that JMock 2 is very much incompatible with JMock 1.3, it didn’t go so well. The odd thing is that Buildr can be quite flexible &#8211; it supports TestNG and a few other libraries, but with JUnit it really wants to also use JMock. There is a way to specify a different version, but the group name is hard coded, so you can’t go back to JMock 1.3 because it has a different group name<a
class="footnote" id="footlink1:1263215332489" href="#footnote1:1263215332489">1</a>. It would be far better for Buildr to just leave the mock framework as a dependency the project developer has to add if they want it.</p><p> Overall, Buildr is a pretty good solution, it’s quick and easy to get up and running (beware the central repository though) but it’s still fairly immature which caused me a fair few problems. The good news is that every issue I ran into was already a known problem that the Buildr team is working on resolving, so it’s pretty likely to become a very good option in the future.</p><h3> <a
href="http://www.gradle.org/">Gradle</a></h3><p> Gradle is a particularly interesting project. It feels a lot like a Java-oriented version of Rake with elements of Buildr, Maven and Ant mixed in. It has the best ant integration story of any of the non-ant build tools. Like Buildr it can pretty seamlessly utilise ant tasks but within the scripting language rather than with XML. Gradle can also import an existing ant build file and use the targets it defines as if they were native. That’s surprisingly powerful and useful, especially if you already have various build scripts and utilities written in ant.</p><p> Gradle also has a really nice approach to multi-project builds, allowing you to inherit configuration from the parent build script and pull in project dependencies easily. However, it’s not all smooth sailing. The main project build file starts to get pretty complex because it winds up configuring both itself and the sub-modules in the one file. The inheritance doesn’t really make sense if you have a mix of sub-module types, say some Java, some Scala and some just web resources. In hindsight, it would probably be better to ignore the built-in inheritance and just use normal file import functionality within each module to select the default module behavior to use.</p><p> Sadly, the multi-project stuff really came crashing down because of some pretty unexpected behavior about what the current project actually was. Depending on when a particular bit of script gets accessed, it might take project() to mean the current sub-module or it might wind up referring to the last sub-module that gets processed. It made sense when you think through the way the code works, but it’s far from intuitive when you’re just trying to build your project. I really couldn’t see myself recommending Gradle until this is significantly simplified and made intuitive.</p><p> Gradle also handles transitive dependencies much better than Buildr, though I had some confusion of when dependencies were transitive and when they weren’t. Gradle is one of the most flexible tools in terms of how dependencies are handled &#8211; using either the maven repository, ivy or defining dependencies as groups directly in the build files, allowing you to check jar files directly into svn if you prefer.</p><p> Gradle was also one of the slowest of the tools I tried. Once it’s up and running, build times are equivalent to ant, but a do-nothing target took just over 4 seconds whereas ant took well under a second. For a full build, that’s not a big deal &#8211; a project that ant builds in 2 minutes would take gradle 2 minutes and 4 seconds. The problem is when you’re running a really simple task as part of some development (e.g. trying to remove duplication that simian had flagged).</p><h3> <a
href="http://ant.apache.org/">Ant</a></h3><p> I’m beginning to think Ant should have been called Cockroach instead &#8211; at the end of the build tool war, you can bet ant will still be there going strong. It’s really quite scary that it’s been around for about 10 years now and is up to version 1.8, and not for lack of maintainers. Ant doesn’t use convention over configuration &#8211; you have to code up your entire build by piecing together the task building blocks it provides. That said, the tasks ant provides are it’s key strength &#8211; powerful, flexible and in almost every case very well designed &#8211; piecing together a build process from ant tasks is <em>much </em>simpler than piecing together one from scratch or with command line stuff like make would use.</p><p> Since you’re writing the whole build script yourself though, ant files can become very long winded and hard to maintain. If you want to use ant successfully, you have to build a set of base scripts that provide the kind of standard project system that tools like Maven and Gradle give you. The benefit being that you can build it the way you want, not the way the tools want you to, without ever having to fight the tool.</p><p> Thankfully, Ant actually has some pretty powerful tools to build up that project system. It’s simple to import other build files so you can break your script up, and it’s simple to use extension points by overriding targets in the actual project build file. Ant 1.8 adds ‘extension-point’ to make this even easier, but it’s quite good even without that. It’s not quick to build up the right structure but like the infrastructure required for Maven, you can probably share your ant templates company wide (or perhaps much further). <a
href="http://www.easyant.org/">Easyant</a> seems to be an attempt to provide a ready-made project convention on top of ant, but I think it went a bit too far and buried the ant functionality too deeply.</p><p> What I wound up with is a set of build scripts that define various useful macros and targets &#8211; version numbering, tagging in subversion, working with dependencies on sub-modules &#8211; and a set of scripts that define module types such as jar, war and the parent project. Frankly, that approach has revolutionised the way I work with ant.</p><p> The build scripts are now basically a first class project in and of themselves. They can be re-used across multiple projects and improved over time as different projects have various needs. Those improvements can then be easily shared back with the original projects since the scripts aren’t being copied into every project, just treated like any other dependency.</p><p> The build files in the project and sub-module are then very short and simple, since they only have to define any non-standard behavior and the required dependencies. This makes the build process for the project much simpler to maintain and understand. It obviously makes it much easier to start a new project or module as well.</p><p> I also found it really useful to define macros to make things more readable. For example, many but not all projects need to include a copy of EditLive! so there’s a set of predefined targets to grab the right version and make it available. Targets that need EditLive! just depend on the “editlive” predefined target, but that doesn’t allow a specific version of EditLive! to be requested. So there’s also a macro defined, editlive-version, that lets you set the version to use. All it does is set a few properties that control where to get EditLive! from, but the final syntax is much easier to read the the previous method of putting them directly in a properties file allowed. I may be overusing the technique at the moment, but it’s quite useful<a
class="footnote" id="footlink2:1263216861633" href="#footnote2:1263216861633">2</a>.</p><p> However, there are some drawbacks. It got fairly difficult to keep track of which properties were declared at which points in the build &#8211; especially as the number of build files being imported increased. There were a few builds tagged as ${version-major}.${version-minor} because of that. Fortunately, that confusion was limited to within the build framework I was building &#8211; not the actual build files for the project itself, and I found that it was mostly caused by my habit of defining every variable in a properties file that’s included at the top of the build script. For build frameworks, it’s a lot better to declare properties as late as possible, within targets. That way, the property is set at the same time as the first work related to it is being done and any dependent information would already be set. Essentially, it uses the target dependencies to work out the right order for setting properties.</p><p> The downside of building this framework is that now we have to maintain it ourselves as well &#8211; it would be much nicer to use something like Maven or Gradle and have their dev teams deal with the on-going maintenance. However, since we do have some Ephox specific stuff, we’ll always be maintaining some amount of build infrastructure and since we’re currently maintaining it separate for every project, this approach is a lot better than the status quo.</p><h3> Conclusion</h3><p> Ultimately, I think that ant is still the best choice, but it really is vital to set up a build framework that you can reuse, rather than doing everything from scratch for each project. Buildr and Gradle look like they have some huge potential in the future though, but they need some more time to improve stability, simplicity and consistency. I’d guess that their version 2.0’s will be something pretty serious to reckon with. Maven is an awesome tool but it just requires too much effort to get it working right. However, the consistency in how a project is built that the Maven project has brought to the Java would is absolutely revolutionary &#8211; neither Buildr or Gradle could be anywhere near as simple as they are if it weren’t for the work and evangelism of the Maven team to embed the Maven way in to the Java world’s consciousness. Sure we’re still fighting over many parts of it, but <a
href="http://www.symphonious.net/2010/01/06/project-directory-structure/">the Maven project structure is now well established and a very powerful convention</a>.</p><p
class="footnote"> <a
href="#footlink1:1263215332489" id="footnote1:1263215332489">1</a> &#8211; that pesky Maven 1 to Maven 2 transition again…<a
class="footnotereturn" href="#footlink1:1263215332489">↩</a></p><p
class="footnote"> <a
href="#footlink2:1263216861633" id="footnote2:1263216861633">2</a> &#8211; I would also note that the greatest improvement ever added to ant is the <em>else</em> attribute on the condition task (in ant 1.6.2). Makes it much easier and more maintainable to set a property value to one of two options. <a
class="footnotereturn" href="#footlink2:1263216861633"><em>↩</em></a></p>]]></content:encoded> <wfw:commentRss>http://www.symphonious.net/2010/01/11/comparing-build-systems/feed/</wfw:commentRss> <slash:comments>6</slash:comments> </item> <item><title>Project Directory Structure</title><link>http://www.symphonious.net/2010/01/06/project-directory-structure/</link> <comments>http://www.symphonious.net/2010/01/06/project-directory-structure/#comments</comments> <pubDate>Wed, 06 Jan 2010 19:05:55 +0000</pubDate> <dc:creator>Adrian Sutton</dc:creator> <category><![CDATA[Build Systems]]></category> <guid
isPermaLink="false">http://www.symphonious.net/?p=1272</guid> <description><![CDATA[Having spent a bunch of time looking at various build systems and tools, one of the simplest and most effective improvements I’ve discovered is to always use the Maven project structure. It doesn’t matter if you’re not using Maven, there’s no downside to using it and every build tool that uses convention over configuration uses [...]]]></description> <content:encoded><![CDATA[<p> Having spent a bunch of time looking at various build systems and tools, one of the simplest and most effective improvements I’ve discovered is to always use the Maven project structure. It doesn’t matter if you’re not using Maven, there’s no downside to using it and every build tool that uses convention over configuration uses the Maven structure.</p><p> Previously I’ve been of the opinion that the directory structure really didn’t matter much &#8211; I went with whatever happened to be auto-generated by whatever tool I was using that day. There is a small overhead in remembering to look for the JavaSource directory instead of src or source when you switch projects but it’s incredibly minimal and not worth worrying about on its own.  When it comes to build scripts, getting these basics in the same place saves a whole lot of configuration and makes everything simpler.</p><p> When you start using sub-modules within the project it really becomes clear just how much time you can waste tweaking bits of build script to work with even slightly different directory structures. Not only do many build systems give you more functionality automatically, you suddenly get the ability to re-use build scripts and templates across different modules and across projects.</p><p> Don’t think that using the Maven directory structure means you have to play by all the Maven rules though.  You can still generate more than one artifact from a project if that suits you best, you can check jar files into source control rather than using a repository etc, but source files go in src/main/java (or scala or groovy or webapp etc) and test files go in src/test/java (or scala or groovy etc).</p><p> Simple,quick and easy to switch to<a
class="footnote" id="footlink1:1262804739903" href="#footnote1:1262804739903">1</a> and saves a surprising amount of setup work in your build scripts &#8211; especially when you first get the project up and running.</p><p
class="footnote"> <a
href="#footlink1:1262804739903" id="footnote1:1262804739903">1</a> &#8211; assuming your current build scripts aren’t completely sadistic <a
class="footnotereturn" href="#footlink1:1262804739903">↩</a></p>]]></content:encoded> <wfw:commentRss>http://www.symphonious.net/2010/01/06/project-directory-structure/feed/</wfw:commentRss> <slash:comments>2</slash:comments> </item> <item><title>On Build Systems</title><link>http://www.symphonious.net/2010/01/04/on-build-systems/</link> <comments>http://www.symphonious.net/2010/01/04/on-build-systems/#comments</comments> <pubDate>Mon, 04 Jan 2010 12:37:14 +0000</pubDate> <dc:creator>Adrian Sutton</dc:creator> <category><![CDATA[Build Systems]]></category> <category><![CDATA[Code and Geek Stuff]]></category> <guid
isPermaLink="false">http://www.symphonious.net/?p=1264</guid> <description><![CDATA[Recently, the subject of build tools and systems has come up again at Ephox and it appears the topic is rising up again around the internet. As part of this I’ve been reading up on and playing with a bunch of build tools to get a feel for their benefits and limitations, so it seemed [...]]]></description> <content:encoded><![CDATA[<p> Recently, the subject of build tools and systems has come up again at Ephox and it appears the topic is rising up again around the internet. As part of this I’ve been reading up on and playing with a bunch of build tools to get a feel for their benefits and limitations, so it seemed worthwhile writing up what I find as I go along.</p><h3> The Projects</h3><p> Which build tool suits best clearly depends on the type of project you’re working with. I’m currently playing with three quite different projects:</p><ol><li> EditLive! &#8211; a big, old code base with a few dependencies and a quite complex ant-based build process. While the primary code base is Java, the distribution includes a bunch of JavaScript and other ancillary files, documentation and is packaged up in three or four different distribution packages.</li><li> “EPipes” &#8211; a brand new, very simple Java library with no dependencies (other than JUnit). Ant and Maven build scripts at the moment.</li><li> “E2” &#8211; a newish internal web app with quite a few dependencies (including a complex transitive dependency tree), a few sub-projects and the need to include EditLive!</li></ol><p> One important thing to note here is that I’m not trying to solve deployment as part of the build script &#8211; I’m only interesting in building the software ready to be deployed where it’s required and no server management etc<a
class="footnote" id="footlink1:1262603535788" href="#footnote1:1262603535788">1</a>.</p><h3> The Problems</h3><h4> Complexity</h4><p> Simple projects have nice simple build scripts, but as you add multiple output formats and various other filtering steps into the build process the build scripts grow in complexity and become hard to understand. The build script becomes a software project in its own right and chews up large amounts of engineering time.</p><h4> Sub-modules and Internal Dependencies</h4><p> Breaking code up into separate modules is one of the most powerful ways to reduce complexity and increase maintainability, but if those modules are all just thrown into the same project and built together, it’s very common for interdependencies to leak through the code because there’s nothing to enforce the separation. What you want to be able to do is break the project up into separate sub-projects which are built in isolation so that the build fails if you add unwanted dependencies.</p><p> However, that means that instead of building one project, you’re now building multiple projects to get the final output and duplication gets introduced into the build system. In most cases you also want to be able to make changes across the modules without doing a full release or even committing. For example, you may want to add a new configuration option to one of your sub-modules that the main code base requires. Ideally you should be able to try that approach out in your own sandbox without having to commit, build and release the sub-module first.</p><p> Internal dependencies are a slight variant on this &#8211; they are at least conceptually developed by a different team, so you don’t need to make concurrent changes, but you do need to depend on versions that potentially aren’t publicly released yet. The real challenge here is that they may use a different build system and may not be available in or meet the assumptions of any particular dependency management scheme. Including EditLive! usually presents this kind of challenge.</p><h4> Transitive Dependencies</h4><p> When you depend on a library it usually requires a bunch of other libraries in turn. It’s usually pretty easy to grab all of the required library and shove them in at the start, but when you later go to upgrade that library or remove the dependency on it, you need to know which libraries it pulled in and whether or not they are still required, which versions are required etc.</p><h4> Build Reliability</h4><p> We write all kinds of automated tests for our code to ensure it works correctly, but most of the time our build scripts are completely untested. As complexity increases the chances of errors in the build scripts increases pretty dramatically. The challenge is that the build script is what runs the tests, so who tests the tester?</p><h4> Spin-Up</h4><p> Creating a new project or a new sub-project takes too long or it doesn’t get started with the right set of quality controls (e.g. it’s not running checkstyle yet, or not checking code coverage etc).</p><h4> Repeatability</h4><p> The single most important aspect of a build system is that it is 100% repeatable. An interesting exception at Ephox is that we never do two builds with the same version number. It was originally a poor-mans repeatability &#8211; if you want consistency only conduct the test once. We’ve kept it around even though we have a very reliable build system because a) it’s a bit of a safety blanket and b) code signing certificates have an expiry date that we can’t avoid, so the jar signature might be valid on one build and invalid on the other even though we do everything exactly the same.</p><h3> False Problems</h3><p> There are a few false problems that people bring up a lot when discussing build systems. Usually these are actually contributing factors rather than actual problems, sometimes they’re just personal preference showing through.</p><h4> XML is not a Programming Language</h4><p> This has to the most common false problem. It’s pretty clear that there are XML dialects which <em>are</em> in fact programming languages but that’s not really what the complaint is about. The real point here is that the build script is either too complex or too verbose. It might also be a complaint about productivity when editing the build script. It’s important to dig into these particular complaints because understanding what the real problem is leads to finding the right solution. If productivity is the problem, better editing tools are often the best solution. Often ant’s use of XML is being confused with the declarative intent of ant. In other words, with ant you’re build script <em>isn’t</em> a programming language and isn’t trying to be &#8211; you’re just trying to use it wrong (and perhaps the tool isn’t the right choice for you).</p><h4> Downloading the Internet</h4><p> This is commonly levelled at maven since it uses it’s own dependency management system to reduce the initial size of it’s download. Complaining that maven is so complex it has to download extra modules just to run clean is a red-herring &#8211; it could just as easily have included those modules with the initial download and been just as complex without needing to download anything. Ant for instance is “so complex” it requires you to program your own clean.</p><p> That said, accessing the internet can be a real problem in various ways. Does the build work the same way on the internal intranet as it does when working from home? What happens if the internet connection is unreliable? Does downloading stuff mean that the build isn’t reproducible? Once you identify the real problems, most build tools provide solutions to them in various ways. For example, all of those problems apply to maven by default, but can actually be solved<a
class="footnote" id="footlink2:1262606067896" href="#footnote2:1262606067896">2</a>.</p><h4> The Build is Too Slow</h4><p> This can be a real problem if your build tool happens to be the bottle-neck but that’s fairly unlikely. More likely is that your unit tests are too slow, or that it’s too hard to make the build run in a distribution fashion, or that the complexity has introduced bugs into the build script and it’s doing work that’s either not needed or has already been done once before.</p><h4> My Build is a Unique and Special Snowflake</h4><p> It’s easy to believe that your software project is somehow special and there’s no other software that’s built like it out there. More likely though, it’s a pretty close variant on a theme rather than something completely unique to itself. Down this path lies building your own build tool &#8211; from scratch at the extreme. A custom built build tool can be the right choice, but it’s no cakewalk. I just look at the pain many newly open-sourced projects have had because they have an unusual build process. Huge amounts of time are spent teaching people how to set up the build environment and compile the project before they can start contributing. That cost is encountered with every new team member even if you never open-source your code. Plus, now instead of one project to build, now you have two and it’s unlikely to reduce the complexity.</p><p> So dig into this false problem further and really understand it:</p><ul><li> Are you mixing in deployment stuff into the build and would that be better split out?</li><li> Is there something about your project you could or should change to make it easier to build?</li><li> Can you build custom modules for your build system rather than trying to do everything in the build script? For example, build an ant task or a maven plugin to perform particularly custom tasks.</li><li> Would you be better running an external script as part of the build rather than replacing the whole build process?</li></ul><p> The key theme here is to identify the parts of your project that follow common patterns and the parts that are more unusual then leverage existing tools for the common parts. Depending on how much is common and how much is unusual will affect which tools is right, but you can usually avoid having to write a completely custom build system.</p><h3> The Options I See So Far</h3><p> There are a lot of build tools out there these days, but here are the ones I’ve found so far that are worth investigating:</p><ul><li> <a
href="http://ant.apache.org/">ant</a> All our systems are built around it so far but we need to find better ways of using it to solve the problems we’re seeing.</li><li> <a
href="http://maven.apache.org/">Maven</a> The other Java build system. Maven has a real love it or hate it thing so it’s hard to know. I see huge potential with Maven and have huge concerns as well. I can’t put much faith in what I’ve read against Maven though because the articles always seem to lack:<ul><li> A sense of rationality. Huge diatribes are easy to find, careful analysis is much less common.</li><li> Using a private maven repository. This is a must for Maven but is usually just mentioned off-hand as a solution that was put in the too hard basket rather than really tried.</li><li> Building custom plugins for custom parts of the build. People who complain maven “just can’t do” something haven’t looked at building a plugin for it, or calling out to an external script etc.</li></ul></li><li> <a
href="http://rake.rubyforge.org/">Rake</a> Except Rake doesn’t seem to really know anything about building Java projects so it would have to be combined with another library, possibly <a
href="http://raven.rubyforge.org/">Raven</a>, but I need to do more looking into how best to use rake with Java projects and Rake in general.</li></ul><p> Anything else that would be worth looking into would be good to know as well. I’m deliberately ignoring make since the build process needs to run cross-platform and while that’s possible in make, it’s a pretty big challenge.</p><p
class="footnote"> <a
href="#footlink1:1262603535788" id="footnote1:1262603535788">1</a> &#8211; I tend to be of the view that your build and deployment systems should be separate even if they do wind up using the same tools. That way you separate the configuration from your actual code since the deployment step does the configuration rather than it being baked into what gets built. It’s also a pretty good split-point to help reduce complexity and lets you pick a deployment tool that best fits rather than having to use the same tool for both. <a
class="footnotereturn" href="#footlink1:1262603535788">↩</a></p><p
class="footnote"> <a
href="#footlink2:1262606067896" id="footnote2:1262606067896">2</a> &#8211; whether the effort required to solve them is worth it or not depends on the particulars of the project and potentially how many projects that effort can be amortised over; it usually needs to be done per company rather than per project. <a
class="footnotereturn" href="#footlink2:1262606067896">↩</a></p>]]></content:encoded> <wfw:commentRss>http://www.symphonious.net/2010/01/04/on-build-systems/feed/</wfw:commentRss> <slash:comments>10</slash:comments> </item> </channel> </rss>
