Channels ▼

Al Williams

Dr. Dobb's Bloggers

Making Build Scripts

September 10, 2013

Last time I talked about the basic structure of a makefile. If you just have a file or two, it is easy enough to just write a basic file. However, a complex project gets burdensome after awhile. I usually start with a generic template that has grown with inputs from several Internet sources, and try to come up with a generic makefile for a particular platform. Then, in theory, I should be able to just modify a few variables at the front of a copy of the file and be ready to go.

The common makefile I use has a few predefined targets:

  • all
  • clean
  • program

In addition, I will usually have targets for specific output formats I want to convert the resulting build into (e.g., hex, elf, or coff).

The key, of course, is variables. For example:

TARGET = demo
SRC = $(TARGET).c
SRC += aap4uart.c app4adc.c app4lcd.c app4delay.c

I will usually divide the file in three sections: Things you change for each project, things you might change (but probably won't), and things you should probably not change unless you are trying to move things over to another platform.

Examples of things you might not change very often would be the port to find the programmer on (e.g., /dev/ttyUSB2) and the type of programmer. The option for the processor type would be another good example.

You can also hide cross build platform difference with variables. For example:

REMOVE = rm –f
COPY = cp

Here's a typical default rule from one of my files:

all: begin $(TARGET).elf $(TARGET).hex end

The begin and end targets let you do operations before and after the build. You might want to do something with version control, logging, or something as simple as:

begin:
@echo Starting Build
@$(CC) --version
end:
	@echo Build complete

If you are like me and don't like the built in rules, you can build your own without having to copy them for each target. For example:

%.o : %.c
	@echo Compiling $<
	$(CC) –c $(ALL_CFLAGS) $< -o $@

This tells make that .c files make .o files and gives the steps for building. $< is, of course, the .c file name (in this case) and $@ is the .o file name.

Of course, building an embedded program is only part of the battle. You have to get it to the target machine, too. There are several options. If you are using a microcontroller with some kind of programmer (like a JTAG programmer), you might want to define a target to do the download that depends on the image file:

jtagburn : $(TARGET).hex
	jtag –p /dev/ttyUSB2 –I $(TARGET).hex –p1550

Sometimes you have multiple ways you might program, so I usually define the PROGRAMMER variable near the top (in the "sometimes changed" section) and set it to the target (like jtagburn). Then I have single rule down at the bottom:

program : $(PROGRAMMER)

That way "make program" burns the device using the selected programmer. Don't forget to set the program target as a .PHONY target.

If the target runs Linux or another "big" operating system, you have more choices. You can use scp, for example, to copy files over to the embedded filesystem. You can also use sshfs to "mount" the remote filesystem locally and then just use normal commands like cp (or, you can have the build tools just write to the remote filesystem, although that could turn into a performance issue).

Ultimately, you could use ssh to run remote commands (either the native compiler on the target, or run make on the target but use ssh to execute remote tools on a host computer). I haven't found a good reason to do either of those, but it is possible.

Make is not the latest build tool, but it is certainly versatile, portable, and very useful, particularly for normal embedded-system projects. Like most powerful tools, it can seem a little arcane at first, but with minimal effort you can master enough make to write a basic template makefile for your application. After that, it can be very simple to start a new project.

Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 


Dr. Dobb's TV