Make my Make with Eclipse and MCU10

I mentioned in Go Reference that MCU10 and eclipse come with a comfortable infrastructure: you add, remove, rename source files and set compiler options: managed make will take care and creates the make files for you. Make files are such a great thing because they allow you do to pretty much everything.

Classic CodeWarrior uses a different approach without make files. Exporting the project as make file did not really work, so make files were not something you could have used easily in classic. With the eclipse based MCU10 make files are the heart of the build system. In most cases using the managed make system is perfectly fine. But for a bare metal enthusiast it makes sense to use my own make file instead.

With a make file I can program my build. As with any programming language, it takes some time to master it. To learn more about make files have a look at GNU make documentation.

In the steps below, I’m going to create a make project for the Freescale HCS08 in the eclipse based CodeWarrior for MCU10.2. In contrast to the managed make, I will create my own make file and will have full control.

I start with using the File > New > Other menu:

New C Project

New C Project

I enable Show All Wizards and select the C Project (which is otherwise hidden), pressing Next.

The first time I create a C/C++ make project, a dialog will ask me to enable Generic C/C++ GNU Development. I’m OK with this.

Confirm Enablement for C/C++ GNU Development

Confirm Enablement for C/C++ GNU Development

Next I specify the project name, select an Empty Project under Makefile project with — Other Toolchain — and press Finish:

C Project Dialog for Makefile project

C Project Dialog for Makefile project

Now I have an empty project with nothing in it :-). Well, this is not completely true, as eclipse has created the .cproject and .project files in my project folder containing the project information.

What is missing in my project is to specify which make utility I want to use. CodeWarrior for MCU10.2 comes with the mingw32-make. For details about this implementation of make see the http://www.mingw.org/ web site. I want to use following command for make in my project settings:

${system:ECLIPSE_HOME}/../gnu/bin/mingw32-make -j6

Using Project > Properties I can specify the above as my Build Command:

Project Builder Settings to use make file

Project Builder Settings to use make file

For my S08 make file project I need 4 files:

  1. The startup file start08.c. I copy it from another project or use the one from <installation>\MCU\lib\hc08c\src\start08.c
  2. The linker file for my microcontroller. I use one from another project or one from the templates in <installation>\MCU\lib\hc08c\prm
  3. At least one source file, e.g. main.c with the main() function.
  4. And last but not least the makefile. I can create that makefile with the menu File > New General > File
Make File Project

Make File Project

I add a simple endless loop to my main.c:

void main(void) {
Ā  for(;;) {
Ā Ā  Ā /* not doing anything for now */
Ā  }
}

Next, I start add variables in my makefile:

ProjDirPathĀ Ā Ā Ā Ā Ā Ā Ā  := C:/tmp/make_wsp/myProject
CWInstallDirPathĀ Ā Ā  := C:/Freescale/CW MCU v10.2
GnuInstallDirPathĀ Ā  := $(CWInstallDirPath)/gnu/bin
LL := "$(CWInstallDirPath)/MCU/prog/linker"
LLFLAGS :=
CC := "$(CWInstallDirPath)/MCU/prog/chc08"
CCFLAGS := -I"$(CWInstallDirPath)/MCU/lib/hc08c/include"

The variables point to my project directory (ProjDirPath), my CodeWarrior installation path (CWInstallDirPath) and the path where my gnu tools are located (GnuInstallDirPath). The variables LL and CC point to my linker and compiler, and CCFLAGS and LLFLAGS contain my compiler and linker options.

Next I add a rules to the make file. Rules in make files are in the form of

target: dependency list
<tab>commands

In make file language, this says: “To build the target on the left hand side, the dependency list on the right hand side has to be built first. To create the target, the command(s) preceded by tabs have to be executed.”

With this in mind, I can write my rules as:

all: project.abs
Ā Ā  Ā @echo 'all done!'

project.abs: project.prm main.o start08.o
Ā Ā  Ā $(LL) $(LLFLAGS) project.prm \
Ā Ā  Ā -Add(main.o) \
Ā Ā  Ā -Add(start08.o) \
Ā Ā  Ā -O"project.abs"

start08.o: start08.c
Ā Ā  Ā $(CC) $(CCFLAGS) start08.c

main.o: main.c
Ā Ā  Ā $(CC) $(CCFLAGS) main.c

If I select now my project and do a Project > Build Project, I get in the Console View:

**** Build of configuration Default for project myProject ****

C:\Freescale\CW MCU v10.2\gnu\bin\mingw32-make -j6 all
"C:/Freescale/CW MCU v10.2/MCU/prog/chc08" -I"C:/Freescale/CW MCU v10.2/MCU/lib/hc08c/include" main.c
"C:/Freescale/CW MCU v10.2/MCU/prog/chc08" -I"C:/Freescale/CW MCU v10.2/MCU/lib/hc08c/include" start08.c
start08.c
Command Line: '-I"C:/Freescale/CW MCU v10.2/MCU/lib/hc08c/include" start08.c'
C:\tmp\make_wsp\myProject\start08.c
Ā "C:/Freescale/CW MCU v10.2/MCU/lib/hc08c/include\start08.h"
Ā  "C:/Freescale/CW MCU v10.2/MCU/lib/hc08c/include\hidef.h"
Ā Ā  "C:/Freescale/CW MCU v10.2/MCU/lib/hc08c/include\stddef.h"
Ā Ā  "C:/Freescale/CW MCU v10.2/MCU/lib/hc08c/include\stdtypes.h"
Ā  "C:/Freescale/CW MCU v10.2/MCU/lib/hc08c/include\non_bank.sgm"
Ā "C:/Freescale/CW MCU v10.2/MCU/lib/hc08c/include\non_bank.sgm"
Object file: C:\tmp\make_wsp\myProject\start08.o, format ELF/DWARF 2.0
main.c
Command Line: '-I"C:/Freescale/CW MCU v10.2/MCU/lib/hc08c/include" main.c'
Code Size: 149
Global objects: 6, Data Size (RAM): 6
HC08 Compiler: *** 0 error(s), 0 warning(s), 0 information message(s) ***
HC08 Compiler: *** Processing ok ***
C:\tmp\make_wsp\myProject\main.c
Object file: C:\tmp\make_wsp\myProject\main.o, format ELF/DWARF 2.0
Code Size: 2
Global objects: 1
HC08 Compiler: *** 0 error(s), 0 warning(s), 0 information message(s) ***
HC08 Compiler: *** Processing ok ***
"C:/Freescale/CW MCU v10.2/MCU/prog/linker"Ā  project.prm \
-Add(main.o) \
-Add(start08.o) \
-O"project.abs"
project.prm
Command Line: 'project.prm -Add(main.o) -Add(start08.o) -O"project.abs"'
Linking C:\tmp\make_wsp\myProject\project.prm
Reading file 'C:\tmp\make_wsp\myProject\main.o'
Reading file 'C:\tmp\make_wsp\myProject\start08.o'
Generating Symbol table
Generating DWARF data version 2.0
Code Size: 167
Generating MAP file 'C:\tmp\make_wsp\myProject\project.map'
SmartLinker: *** 0 error(s), 0 warning(s), 0 information message(s) ***
SmartLinker: *** Processing ok ***
'all done!'

If not, then something is wrong. One common error in make files is using spaces instead of tabs at the beginning of command lines. Using the Show Whitespace Characters is very useful in this context:

Show Whitespace to show tab characters

Show Whitespace to show tab characters

Another extremely helpful tool to spot errors in make files is using the Outline View:

Outline View spotting error in make file

Outline View spotting error in make file

While things are working well for now, adding new source files requires adding new rules.Ā  Instead of:

start08.o: start08.c
Ā Ā  Ā $(CC) $(CCFLAGS) start08.c

main.o: main.c
Ā Ā  Ā $(CC) $(CCFLAGS) main.c

I can use generic rules with:

# rule how to build an object file from a C file
%.o: %.c
Ā Ā  Ā @echo 'Building file:

lt;' Ā Ā  Ā $(CC) $(CCFLAGS)

lt;

Using rules for specific files still makes sense as for files which need some special treatment.

So far I’m using the ‘all’ make target as default make target. Why not adding a new make target to clean my project?

RM := "$(GnuInstallDirPath)/rm" -f

clean:
Ā Ā  Ā $(RM) *.abs
Ā Ā  Ā $(RM) *.o
Ā Ā  Ā $(RM) *.map
Ā Ā  Ā $(RM) EDOUT

As I have now two make targets (‘all‘ and ‘clean‘), it makes sense to take advantage of the eclipse Make Target View. In that view I can add make targets using the ‘New Make Target’ button:

New Make Target

With this I can specify the ‘all’ and ‘clean’ target names:

Create new make target

Create new make target

With double clicking on a make target or using the toolbar icon it is now easy to execute a make target:

Execute a Make Target

Execute a Make Target

One thing remains: the source files and the object files are all in one folder. It would be better to use separate folders for source and object (and linked) files.

For this I add extra variables OBJ_PATH and SRC_PATH in my make file and change the options and rules to use it. Below is the extended make file:

ProjDirPathĀ Ā Ā Ā Ā Ā Ā Ā  := C:/tmp/make_wsp/myProject
CWInstallDirPathĀ Ā Ā  := C:/Freescale/CW MCU v10.2
GnuInstallDirPathĀ Ā  := $(CWInstallDirPath)/gnu/bin
OBJ_PATH := obj
SRC_PATH := src
RM := "$(GnuInstallDirPath)/rm" -f
LL := "$(CWInstallDirPath)/MCU/prog/linker"
LLFLAGS := -EnvTEXTPATH=obj
CC := "$(CWInstallDirPath)/MCU/prog/chc08"
CCFLAGS := -I"$(CWInstallDirPath)/MCU/lib/hc08c/include" -ObjN="$(OBJ_PATH)/%%n.o" -EnvTEXTPATH=obj

all: $(OBJ_PATH)/project.abs
Ā Ā  Ā @echo 'all done!'

$(OBJ_PATH)/project.abs: $(SRC_PATH)/project.prm $(OBJ_PATH)/main.o $(OBJ_PATH)/start08.o
Ā Ā  Ā @echo 'Linking file:

lt;' Ā Ā  Ā $(LL) $(LLFLAGS) $(SRC_PATH)/project.prm \ Ā Ā  Ā -Add($(OBJ_PATH)/main.o) \ Ā Ā  Ā -Add($(OBJ_PATH)/start08.o) \ Ā Ā  Ā -O"$(OBJ_PATH)/project.abs" # rule how to build an object file from a C file $(OBJ_PATH)/%.o: $(SRC_PATH)/%.c Ā Ā  Ā @echo 'Building file:

lt;' Ā Ā  Ā $(CC) $(CCFLAGS)

lt; clean: Ā Ā  Ā @echo 'Cleaning generated files...' Ā Ā  Ā $(RM) $(OBJ_PATH)/*.abs Ā Ā  Ā $(RM) $(OBJ_PATH)/*.o Ā Ā  Ā $(RM) $(OBJ_PATH)/*.map Ā Ā  Ā $(RM) EDOUT Ā Ā  Ā $(RM) err.log

Now I can use different folders for the source and the output files in my make file project:

Make File Project with Folders

Make File Project with Folders

Uff, that was some work, but now I’m having complete control over my build.

Happy Making šŸ™‚