Making an XML bill of materials in GNU Make

[article]
Summary:

In this article I present a simple technique that causes GNU Make to create a XML file containing a "bill of materials" or BoM.  The BoM contains the names of all the files built by the Makefile and is nested to show the prerequisites of target.

A difficult question to answer with standard GNU Make output is: "What got built and why?"

In this article I present a simple technique that causes GNU Make to create a XML file containing a "bill of materials" or BoM.  The BoM contains the names of all the files built by the Makefile and is nested to show the prerequisites of target.

An Example

Let's start with an example Makefile and its related BoM and work backwards to how the BoM XML file was generated.   Take for example, the following simple Makefile:

all: foo bar

    @echo Making $@

foo: baz

    @echo Making $@

bar:

    @echo Making $@

baz:

    @echo Making $@

It makes all from foo and bar.  In turn foo is made from baz.  Running this in GNU Make gives the following output:

Making baz

Making foo

Making bar

Making all

From the output it's impossible to tell the actual tree-ordering of the build, or which files depend on which.  In this case, the Makefile is very small and it's relatively easy to trace by hand; in any real Makefile hand tracing is almost impossible.

Later I'll show you the code that can translate the above Makefile into an XML document like this:

<rule target="all">

  <prereq>

    <rule target="foo">

      <prereq>

        <rule target="baz" />

      </prereq>

    </rule>

    <rule target="bar" />

  </prereq>

</rule>

In that document each rule run by the Makefile has a <rule> tag added with a target attribute giving the name of the target that the rule built.   

If the rule had any prerequisites then within the <rule>/</rule> pair there's a list of prerequisite rules enclosed in <prereq>/</prereq>.   

In the example above you can see the structure of the Makefile reflected in the nesting of the tags.  Loading that XML document into an XML editor (or simply into a web browser like Firefox) allows you to expand and contract the tree at will to explore the structure of the Makefile.

How it works

To create the output above the example is Makefile is modified to include a special 'bom' Makefile using the standard include bom method.  With that included its possible to generate the XML output by running GNU Make with a command line such as make bom-all.

The bom-all instructs GNU Make to build the build of materials starting with the all target.  It's just as if you'd typed make all but now an XML document will be created.

By default the XML document has the same name as the Makefile with .xml appended.  If the example Makefile above was in example.mk then the XML document created will be called example.mk.xml.

Here's the contents of the bom Makefile to include (I've added line numbers to make it easy to refer to parts of this Makefile below):

 1 PARENT_MAKEFILE := $(word $(words $(MAKEFILE_LIST)),x $(MAKEFILE_LIST))

 2 bom-file := $(PARENT_MAKEFILE).xml

 3

 4 bom-old-shell := $(SHELL)

 5 SHELL = $(bom-run)$(bom-old-shell)

 6

 7 bom-%: %

 8     @$(shell rm -f $(bom-file))$(call bom-dump,$*)

 9

10 bom-write = $(shell echo '$1' >> $(bom-file))

11
bom-dump = $(if $(bom-prereq-$1),$(call bom-write,<rule
target="$1">)$(call bom-write,<prereq>)$(foreach
p,$(bom-prereq-$1),$(call bom-dump,$p))$(call
bom-write,</prereq>)$(call bom-write,</rule>),$(call
bom-write,<rule target="$1" />))

12

13 bom-run = $(if $@,$(eval bom-prereq-$@ := $^))

The first two lines figure out the correct name for the XML file.  This is done by extracting the name of the Makefile that included bom into PARENT_MAKEFILE, appending .xml and storing the resulting name in bom-file.

Lines 3 and 4 use a trick I've talked about a number of times: my SHELL hack.  Briefly, GNU Make will expand the value of $(SHELL) for every rule that's

About the author

AgileConnection is one of the growing communities of the TechWell network.

Featuring fresh, insightful stories, TechWell.com is the place to go for what is happening in software development and delivery.  Join the conversation now!