Archive for July, 2010
More of a quick splurge than anything – I was looking over some old code and noticed a unit test that creates a lazy list of tests, each of which asserts some properties about a bisection based search over a set of stub objects which are all based on an existing superclass and have a property defined which returns a randomised value each time you interact with it. Unusual but kind of cool. Here’s the code…
def check_detect_using_bisect(searchbase, subject):
searchbase = list(searchbase)
item = searchbase[max(0, min(subject, len(searchbase) -1))]
universe = sorted(searchbase, key=salsa_key)
search_result = detect(cmp, item, universe, key=salsa_key)
reason = "item (%i) mapped_to (%i)" % (universe.index(item), universe.index(search_result))
assert_that(search_result, is_(not_none()), reason)
assert_that(search_result.salsaId, is_(equal_to(item.salsaId)), reason)
[ (yield testcase) for testcase in check_detect_using_bisect() ]
Sometimes you want your build to do some additional work after compiling. For example, in my Erlang implementation of hamcrest, I dynamically generate the main header file after compiling to ensure that all the functions exported from the hamcrest_matchers module are imported when the header gets included and to ensure that wrapper macros for eunit are also generated for each of them.
Typically you’d just have a makefile deal with this, maybe like so:
./rebar compile; escript header_gen
But that kind of breaks other people’s builds if they want to use rebar themselves. The problem is that rebar doesn’t yet provide a mechanism for overriding the build/compile command for dependencies (at all, let alone individually) and thus if your build requires a makefile to be run then your consumers build has to incur the same kind of complexity. Fortunately there is a work-around. Rebar provides a compile_post_script hook which you can specify in your
rebar.config file. You specify a shell command and rebar will run this hook immediately after compilation. Unfortunately it also runs it when the compile command is applied to all your dependencies (again this is something which isn’t controllable yet) which typically will break because your shell command is not relevant to these apps. I spent a little time trying to do something clever with
erl --eval '...' but in the end that didn’t play nicely at all. I then tried to encode the whole thing in a compound shell command like
if [ -f hrlgen ]; then escript hrl; fi but then discovered that
rebar_utils:sh/1 (which runs the shell command) wraps the supplied command text in an
exec system call (which obviously isn’t going to work for a complex if..then expression). In the end, it was a comedic reptile that came to the rescue:
"env ERL_LIBS=deps python -c \"import os; os.path.isfile('hrlgen') and os.system('escript hrlgen') or None\""}.
This is surprisingly tricky, but in the end (with a bit of help from the safari java console) I determined that the problem is with DNS resolution and have a work-around. Whether this affects everyone or just those of us lucky to be behind a corporate firewall, I don’t know. The fix for me, was to install Java 1.5 and set my java preferences to always choose the 1.5 JVM for running web apps/applets, after which everything seems to play nicely.
Installing java 1.5 on Snow Leopard is itself quite tricky. The secret is to get hold of the java 1.5 update for Leopard and open it using Pacifist, which allows you to navigate into the /System/Library/Frameworks/JavaVM.framework/Versions directory within the installer package, select the 1.5.0 folder and the symlink to it (1.5) then right click and select “install to default location”. Props to this blogger for revealing the secret to that old chestnut. Please be very careful though – if you don’t delete the existing symlink first (which has 1.5 pointing to the current 1.6 install), then you’ll blow away your existing installation!
Unfortunately this means I no longer have an excuse not to attend boring finance meetings whilst working from home.
I love rebar as a build tool, but occasionally it doesn’t do what I want. One example that keeps cropping up is managing dependencies that require complex commands in order to build them. If the dependency you want to manage is built using autotools or requires a series of commands (
configure && make for example) then rebar is going to fail when you try and run
./rebar check-deps which is annoying. Read the rest of this entry »