Boost logo

Boost-Build :

Subject: [Boost-build] bjam patch and 'prebuild' rule
From: Ray Lambert (codemonkey_at_[hidden])
Date: 2010-07-27 00:33:49


Hi,

I just wanted to let the list know that earlier today I posted a patch
(#4470) to the tracker that updates the bjam builtin SHELL rule. It
does two things:

1. It fixes the exit code issue that was discussed on the list recently
by applying the WIFEXITED() and WEXITSTATUS() macros to the value
returned by pclose().

2. It adds a new SHELL option called 'strip-eol' that will strip any
trailing white space (inc. newlines) from the command result before it
is returned (unless 'no-output' is in effect).

The 'strip-eol' option is actually a better solution for the newline
issue than the 'rtrim.jam' rule that I posted a short while ago but
ultimately either will work.

Lastly, I also wanted to share another rule I wrote that others may find
useful. I call this rule "prebuild" because I use it to invoke an
external tool prior to a build but, more importantly, it allows one to
cleanly "sense" an external condition and use it to effect a build.

The rule represents something that I've been trying to get working for
some time without a lot of luck. I finally got the basic mechanism
working recently after someone on this list posted a solution for
something similar that demonstrated a technique that I wasn't aware of;
namely, conditionally defining a target as an empty alias to make it
effectively into a no-op. I hadn't previously considered that an empty
alias was possible or even useful. Unfortunately, I can't remember who
it was that posted the technique but, if you know who you are, thanks!

To use the rule you pass it a target name and a shell command. It runs
the shell command and, if the exit code is non-zero, it defines the
target using "notfile" (and empty actions). If the exit code is zero it
defines the rule as an empty alias. You can then make other targets
dependent on this target and they will rebuild when the external tool
wants them to.

Here's a brief usage example:

----------------------------------------------------------------------------------------------------
import prebuild ;

prebuild extcond : "./prebuild.sh" ;

obj foo : foo.cpp : <dependency>extcond ;

exe myapp : [ glob *.cpp : foo.cpp ] ;
----------------------------------------------------------------------------------------------------

Nice and clean. :)

Lastly, here's the rule itself (posted at end).

Note that, by default, it will print all of the output from the external
command IF the exit code is non-zero (this allows a message detailing
what is causing the rebuild, if you desire one). You can suppress this
by passing the 'no-echo' option. If (like me) you don't like the extra
blank line that is printed after the output, you can modify it to use
the 'rtrim' rule that I posted earlier or the 'strip-eol' option that my
patch adds to the SHELL command (assuming the patch is accepted). I
left a commented-out example of the latter in the rule source.

~ray

prebuild.jam:
----------------------------------------------------------------------------------------------------
import notfile ;
import project ;

rule prebuild ( target : command : options ? )
{
     #local res = [ SHELL $(command) : exit-status : strip-eol ] ;
     local res = [ SHELL $(command) : exit-status ] ;
     if $(res[2]) != 0
     {
         if ! "no-echo" in $(options)
         {
             ECHO $(res[1]) ;
         }
         notfile $(target) : @prebuild.noop ;
         actions quietly noop { }
     }
     else
     {
         alias $(target) ;
     }
     local t = [ project.current ] ;
     $(t).mark-target-as-explicit $(target) ;
}

IMPORT $(__name__) : prebuild : : prebuild ;
----------------------------------------------------------------------------------------------------


Boost-Build list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk