EBC Exercise 07b make with variables
Part B – Using Built-in and User-Defined Variables
In this part, we will add some user-defined variables and built-in variables to simplify and help the makefile more readable. You will also have a chance to build a “test’ rule to help debug your makefile. This continues Part A which is here.
- Add CC (user-defined variable) to your makefile.
Right now, our arm makefile is “hard coded”. Over the next few steps, we’ll attempt to make it more generic. Variables make your code more readable and maintainable over time. With a large, complex makefile, you will only want to change variables in one spot vs. changing them everywhere in the code.
Add the following variable in the section of your makefile labeled “user-defined vars”:
CC := $(LINUXarm_GCC)
CC specifies the path and name of the compiler being used. Notice that CC is based on another variable named LINUXarm_GCC. Where does this name come from? It comes from an include file named path.mak. Open path.mak and view its contents. Notice the use of LINUXarm_GCC variable and what it is set to.
Whenever you use a variable (like CC) in a rule, you must place it inside $( ) for make to recognize it – for example, $(CC). After adding this variable, use it in the two rules (.x and .o). For example, the command for the .x rule changes from:
gcc –g app.o –o app.arm
$(CC) -g app.o –o app.arm
- Apply this same concept to the .o rule.
- Add include for path.mak.
In the “include” area of the makefile, add the following statement:
- Test your makefile: clean, make and then run the executable.
- Add CFLAGS and LINKER_FLAGS variables to your makefile.
Add the following variables in the section of your makefile labeled “user-defined vars”:
CFLAGS := -g LINKER_FLAGS := -lstdc++
CFLAGS specifies the compiler options – in this case, -g (symbolic debug). LINKER_FLAGS will tell the linker to include this standard library during build. (The example option –lstd++ specifies the linker should include the standard C++ libraries.)
Use these new variables in the .x and .o rules in your makefile.
- Test your makefile.
- Add built-in variables to your .o rule.
Make contains some built in variables for targets ($@), dependencies ($^ or $<) and wildcards (%). Modify the .o rule to use these built-in variables.
The .o rule changes from:
app.o : app.c $(CC) $(CFLAGS) –c app.c –o app.o
%.o : %.c $(CC) $(CFLAGS) –c _____ -o _____
Because we only have ONE dependency, use the $< to indicate the first dependency only. Later on, if we add more dependencies, we might have to change this built-in symbol. % is a special type of make substitution for targets and dependencies. The %.o rule will not run unless a “filename.o” is a dependency to another rule (and, in our case, app.o is a dependency to the .x rule – so it works).
- Add built-in variables to your .x rule.
The .x rule changes from:
app.arm: app.o $(CC) $(CFLAGS) app.o -o app.arm
app.arm: app.o $(CC) $(CFLAGS) $(LINKER_FLAGS) _____ -o _____
- Don’t forget to add the additional LINKER_FLAGS to the .x rule.
- Test makefile.
- Add a comment to your .x rule.
Comments can be printed to standard I/O by using the echo command. In the .x rule, add a second command line as follows:
@echo; echo $@ successfully created; echo
The @echo command tells make to echo “nothing” and don’t echo the word “echo”. So, effectively, this is a line return (just like the echo at the end of the line). Because built-in variables are valid for the entire rule, we can use the $@ to indicate the target name.
Test makefile and observe the echo commands. Did they work? As usual, you might need to run “make clean” before “make” so that make builds the executable.
- Add “test” rule to help debug your makefile.
Near the bottom of makefile, you’ll see a commented area named “basic debug for makefile”. Add the following .PHONY rule beneath the comments:
.PHONY : test test: @echo CC = $(CC)
This will echo the path and name of the compiler used. Try it. Does it work? You can also add other echo statements for CFLAGS and LINUXarm_GCC. This is a handy method to debug your makefile.
Close your makefile when finished.