Boost logo

Boost-Build :

Subject: [Boost-build] Conditional unit test execution
From: A. Schamp (schamp_at_[hidden])
Date: 2014-02-04 08:07:51


We are using Boost.Build to build our software for two platforms, Linux x86
(32-bit) and PPC (32-bit). We have a cross compiler set up for our PPC
build, and so run both builds on our x86 platform using different toolset=
declarations. Additionally, for our PPC build, we specify
architecture=power.

This works great for building our software, but we also have a suite of
unit tests that are part of our main target, which we want to execute
automatically on native platforms.

We have some wrappers set up, they look like this (but they don't quite
work):

    feature.feature test-output : user report : incidental optional ;

    # a helper rule to wrap the build stuff common to all boost.test test
cases
    rule run-test ( target : source : requirements * : properties * )
    {
        if <toolset>gcc-ppc
        {
            link $(source) boost_unit_test_framework $(requirements) :
<define>BOOST_TEST_NO_MAIN <define>BOOST_TEST_MODULE=$(source:B) :
$(target) ;
        }
        else
        {
            run $(source) boost_unit_test_framework $(requirements) :
$(properties) : : <define>BOOST_TEST_NO_MAIN
<define>BOOST_TEST_MODULE=$(source:B) : $(target) : ;
        }
    }

    # pass this rule a list of *.test.cpp files, and it will build and run
    # each one as an individual unit test executable,
    # pass library requirements, if any, as the second parameter
    rule tss-test ( sources + : requirements * : properties * )
    {
        local TEST_TARGETS = ;
        for local t in $(sources)
        {
            if <test-output>report in $(properties)
            {
                local target = $(t:B).report ;
                run-test $(target) : $(t) : $(requirements) : $(properties)
--log_format=XML --log_level=all --log_sink=bin/$(target).xml ;
                TEST_TARGETS += $(target) ;

            }
            else
            {
                local target = $(t:B) ;
                run-test $(target) : $(t) : $(requirements) :
$(properties) --log_format=HRF --log_level=warning
--log_sink=bin/$(target).log ;
                TEST_TARGETS += $(target) ;
            }
        }
        return $(TEST_TARGETS) ;
    }

We use the 'test-output' feature to control whether unit test results are
printed in a human readable format or in XML format for Jenkins. The
$(sources) argument to tss-test contains a list of source files, each of
which is a Boost.Test suite that is to be built and run on its own.

What we need is some way to differentiate whether we're building with the
native compiler (toolset=gcc, and so, can run the unit tests and capture
the output) or with the cross-compiler (toolset=gcc-ppc architecture=power,
so we can verify that the tests link, but so that we don't try to run them).

Obviously, the if <toolset>gcc-ppc check in run test doesn't work -- it
always returns true (the value of the string literal). What we can't
figure out is how we can check the value of that toolset variable in a way
that will let us use the 'link' rule in one case and the 'run' rule in the
other case. We've tried using conditional properties (eg:
<architecture>power:<build>no), but can't figure out how to evaluate the
conditional and check it when invoking the rule.

The only idea we have at this point is to create a wrapper script that will
somehow know to execute the test only if it's a natively-built executable,
but this seems inelegant, we'd like to find a way to express it in the
jamfiles directly.

Is there something we're missing? Is the value of <toolset> available
programatically, so we can check it at some point when creating these rules?

We love Boost.Build, and are hoping to make it work for us without a host
of workarounds.

Thank you in advance,
Andrew



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