Driving Embedded Firmware C
Project on CruiseControl
Timo Punkka ( tpunkka at users.sourceforge.net )
ngWare
Continuous integration
and automated
unit tests are long known good programming practices. Agile
methods put a strong emphasis on disciplined use of these practices.
CruiseControl
is an open source continuous integration server software.
Embedded Unit (embUnit)
is an unit test framework targeted for embedded
firmware C projects. This article describes how to set up a buid system
with automated build, continuous integration, and automated
unit tests for embedded firmware C project.
Download
and install CruiseControl.
This example uses the folder structure
familiar from Lasse Koskela's "Driving
on CruiseControl" articles. If
you also choose to do so, change the 'Destination Folder'
setting as
shown below.
Remember
to have your JAVA_HOME variable set, for example in CygWin:
$ export JAVA_HOME="c:\j2sdk1.4.2_13"
The current
distribution (2.5) has a server and Ant
coming with it, so it is a
breeze to launch even for hardcore firmware programmer.
Go to CruiseControl root and run the .bat file.
.
$ /cruisecontrol.bat
Browse to http://localhost:8080 to see how CruiseControl presents the
build results from Java project example, connectfour. The demo project
is
not managed with version control so your changes will not trigger a
new build.
Automated
Build, Version Control, and Continuous Integration
We
are ready move to the C zone and actually do automated
continuous integration. First we need something to integrate.
We will
somewhat reuse the sample files from Embedded Unit
distribution. However we also want a main file and an automated build
script for it. This example
uses GNU Make for automated build.
You can
find the whole example project and files needed to configure
CruiseControl here (zip'ed).
This example expects that you have extracted the zip to
C:\
You are able to build the example project with GNU Make:
$ cd /c/embunit_cruisecontrol/project
$ make -f project.mak -B
Note that in order to build for
embedded target, you need your target compiler installed in your build
server as well.
(Example uses gcc to build for
PC architecture)
Next we want our project to be version controlled so that CruiseControl
can actually do the continuous integration. To do that, we need to
create a version repository, import our code into the repository, and
then checkout a new working copy of the source into our CruiseControl
work area and another copy for development under version control.
$ make -f project.mak clean
$ export CVSROOT=/c/CIA/RepositoryServer
$ cvs -d /c/CIA/RepositoryServer init
$ cvs import -m "First C project" project sts init
CruiseControl's config.xml is where the magic happens, so replace the
demo version with the one given below. You have it in your extracted
folder embunit_cruisecontrol/cruisecontrol/config, with name
config1.xml (if you use this, you have to rename it
to exclude the '1'). Replace the demo version in CruiseControl root
with this one. It is propably a good idea to move the old versio away
by renaming it, and not to overwrite it. For details about the
config.xml see "Driving
on CruiseControl" and CruiseControl
Configuration Reference.
The main difference when moving to use GNU Make instead of Java and Ant
in CruiseControl demo, is the use of generic exec builder.You
can see an example of its attributes in the example.
Run cruisecontrol.bat again, find your way to
http://localhost:8080, and see your project being under cruisecontrol.
Click the project link to see the results from the first build.
Now let's see for the first time what all this is needed for. Browse to
development copy of our poject at Developer1/project. Make a change to
one file, for example main.c and commit the changes to version control.
You should need to wait maximum of 15 minutes (schedule interval
defined in config.xml) to see a new build triggered for your changes.
And it worked! You can see the results in the browser. The
report
contains the commit message from the version control system.
Unit
Tests
In the previous example we had a simple build under automated
continuous integration. Yet we had the the text "No Tests Run, This
project doesn't have any tests" in the results. Let's do something
about this. Embedded Unit can generate results in XML output format.
CruiseControl
can be configured to merge these results into its build report.
So we want the testframe to report the results in XML so that we can
use
them in CruiseControl. This is explained in Embedded Unit
Documentation, but below is a modified AllTests.c file, which runs the
tests via XML outputter if we give '-X' in command line when executing
the tests. Otherwise it uses the simple outputter. This comes handy
when you want to quickly run your tests when developing (hopefully in
TDD), and CruiseControl can run the same tests with '-X' option.
I have modified the makefile which
is used to build the tests a little bit from the current
EmbUnit
examples to include the textUI library. It also uses the EMB_UNIT_DIR
environment variable in defining the include and library sources. Other
than that I wanted to keep the example makefile as it is.
The main make file, project.mak,
defines a special target for CruiseControl. It will compile the target,
the
unit tests (by executing the above makefile),
then execute the unit tests and pass the unit test XML
results into file testResults/TEST-alltests.xml.
We are almost done, but not quite. CruiseControl has XSL transformers
to format the appearance of these
reports. The transformers included in distribution are created for Ant
and JUnit. So it does not know anything about how embUnit reports
tests. You can find the transformers for Embedded Unit in the
exctracted folder, testdetails.xsl and unittests.xsl.
Replace the files circled in the picture below with these new
ones.
OK, Let's launch CruiseControl again. Browse to http://localhost:8080
and force a new build for your project. Let's see the results. You can
now see the results of the unit tests as well. If you want more
details, you can click the Tests Results -button on top of the page.
Let's make one test to fail to show how CruiseControl indicates this.
We just change the expected value of counter after the initialization
to be 1 instead of 0. Not the best example, but it is the first
assertion in counterTest.c. Commit the modified code into repository
(normally you would never commit broken code into repository. Never.)
and wait for CI server to integrate. Now the main build results page
has a red bar and details of failed test. Test Results screen shows the
name of the failing test in red, and details can be found by clicking
Failed>> -link.
counterTest.c
LINE 18: TEST_ASSERT_EQUAL_INT(0,
Counter_value(counterRef));
LINE 18: TEST_ASSERT_EQUAL_INT(1,
Counter_value(counterRef));
Beyond
Publishers:
Telling Others About It
The importance of continuous integration server is highlighted when
multiple developers are working on shared code. It is convenient to
somehow tell others about each change. CruiseControl has a mechanism
called Publisher to configure additional reporting mechanisms. In this
example we will look at html email publisher Lets add this
section to our config.xml. After each build, success or failure,
developer1 will get a html email report.
Sometimes it is a good idea to archive results of each build
automatically. For this we can use another Publisher,
artifactspublisher. We add one more section to our config file. This
copies the defined file project.exe to our logs/project folder. It
actually creates a subfolder with timestamp as a name, and uses this to
archive current version of target, project.exe. Very convenient.
If the team is working in open workspace it is a good idea to add
something simpler and more visible to indicate build results than just
emails. Lava
lamps are the classic. Below are some links to what people have been
doing.