Comment
#this is comment....
Variable Declare
MACRO = value ECE270TA = idiot
Use $(ECE270TA) or ${ECE270TA} to access the variable
:=
When using = to define a variable, make will extend the whole makefile, and determine what's the value of the variable.
When using :=, value of a variable is determined by the place in the makefile, instead of the final value after extending the whole makefile.
?=
If variable is not defined, define it. Otherwise, don't define it again.
+=
Append a new string to a defined variable
Syntax
target: dependencies <Tab>Commands
or
target: dependencies; Commands <Tab>Commands
Target
The file you want to build. Sometimes it may not be a real file, called fake object, ex. all.
If a target doesn't exist, make will execute and create it. Therefore, a fake object will always be executed.
Dependencies
Before creating a target, make will first check its dependencies.
If one of the dependencies does not exist, make will create that dependency first, then create target.
If all of them exist, make checks whether all dependencies are older than the target.
If all of them are older than the target, it means the target is up-to-date, so make doesn't create target again. Otherwise, make will execute and update the target.
Commands
Start from a <Tab>.
Every line of command will be executed in a new shell.
If you want to use a single shell to execute multiple commands, use ';' to separate commands.
Special Character
@: Don't display this line of command in terminal.
-: Even this line of command produces an error, don't stop running makefile.
Implicit rules
test.o:
is equal to the following:
test.o: gcc -c test.c
test:
is equal to the following:
test: gcc -c test.c gcc -o test test.o
With implicit rules, we even don't need to write a make file to compile a c code.
Internal Variables
%: Represent one or more characters
<Ex> %.o : %.c makes all files named 'x.o', with files 'x.c' as dependencies, provided that ‘x.c’ exist or can be made.
$?: Dependencies newer than the target
$@: The target
$<: The first dependency
$*:
$^: The names of all the dependencies, with spaces between them.
Condition
ifeq (value1, value2) #if (value1 == value2)
<Tab> commands
else
<Tab> commands
endif
ifneq (value1, value2) #if (value1 != value2)
<Tab> commands
else
<Tab> commands
endif
ifdef variable #if variable is not defined
<Tab> commands
else
<Tab> commands
endif
ifdef variable #if variable is defined
<Tab> commands
else
<Tab> commands
endif
Internal Functions
shell:
contents := $(shell cat foo)
將含有檔案foo的目錄設定為變數contents的值,是用空格(而不是換行符)分離每一行。
dirs := a b c d files := $(foreach dir,$(dirs),$(wildcard $(dir)/*))
The first repetition finds the value ‘a’ for dir, so it produces the same result as ‘$(wildcard a/*)’; the second repetition produces the result of ‘$(wildcard b/*)’; and the third, that of ‘$(wildcard c/*)’.
Enter Subdirectory
If the project contains many subdirectories, the following command can enter a subdirectory and make it.
cd subdir && make
When using "&&", if the command "cd subdir" produces an error, the shell will stop and prompt the error massage.
Each line of commands will be executed by a seperate shell.
If we use ";" instead of "&&" to seperate commands in a line, the shell will not stop when "cd subdir" produces an error.
Import File
include myrules.txt
Make Parameter
When we run make, we can define or override a variable from passing parameter
make ECE270TA="bitch"
Trace Makefile
Print Variable Value
Paste the following code in the top of makefile
ifdef TRACE t: @echo "$(TRACE) == $($(TRACE))" endif
then you can print the value of any variable
-> make t TRACE=ECE270TA
ECE270TA == idiot
Encountered Problems
- 1. a variable/struct is defined in a .c file; the .o file build from the .c file should be included; make sure the makefile really include this .o file, and is not blocked by an #ifdef… condition
- 2. a variable is defined in A.h file, and this A.h file is included by another header file B.h with a #if defined(FLAGS) condition. B.h are included by many files, and it is enclosed by a #ifndef __B.h; #def __B.h; #endif block. To make sure the vairable defined in A.h file is included, we need to define FLAGS, and include B.h. The problem is, if another file includes B.h before the FLAGS is defined, then A.h will not be included(because the if defined(FLAGS) and #ifndef __B.h; #def __B.h; #endif in B.h).