Make & Makefile
Make & Makefile
Make & Makefile
Introduction
What is a Makefile?
- A text file containing rules that define how a Make works.
What is a Make?
- Utility to maintain, update, and regenerate groups of programs
What is a rule?
- A rule tells Make both when and how to make a file
Advantages:
- Automatically rebuild a program whenever one of the source files is
modified.
- It only recompiles the files that were affected by changes, thus saving
compiling time.
Makefile Syntax
Target Rule:
target1 target2 target3 : prerequisite1 prerequisite2(dependencies)
command1
command2
command3
A target is usually name of the field that make creates; examples are
executable or object files.
A prerequisite is one or more files used as input to create targets.
A command is an action that make carries to create or update a target file
when any of the prerequisites are changed.
Each command to be executed in a rule is interpreted by a shell.
General example
Cake: eggs,milk,sugar,mix,icing
mix && bake && ice
Icing: powdered sugar,water
mix sugar + water
A simple Makefile
Example 1
Example 2
Makefile with Variables
Makefile with Automatic Variables
$(UI_JAR): $(UI_CLASSES)
$(create-jar)
Rules for expanding variables
When make runs, it performs its job in two phases:
In the first phase, make reads the makefile and variables are assigned and
expanded and the dependency graph is created.
In the second phase, make analyzes the dependency graph and
determines the targets that need to be updated, then executes command
scripts to perform the required updates. So when command scripts are
being executed, all variable processing has already completed.
For variable assignments, the lefthand side of the assignment is always
expanded immediately when make reads the line during its first phase.
For macro definitions (those using define), the macro variable name is
immediately expanded and the body of the macro is deferred until used.
For rules, the targets and prerequisites are always immediately expanded
while the commands are always deferred.
Target-specific variables
gui.o: gui.h
$(COMPILE.c) -DUSE_NEW_MALLOC=1 $(OUTPUT_OPTION) $<
The general syntax for target-specific variables is:
target...: variable = value
target...: variable := value
target...: variable += value
target...: variable ?= value
The variable assignment is not actually performed until the processing of
the target begins.
Make p (or) --print-data-base
Example:
gui.o: CPPFLAGS += -DUSE_NEW_MALLOC=1
gui.o: gui.h
When the gui.o target is finished, CPPFLAGS will revert to its original value.
Pattern-specific Variables
Syntax:
pattern ... : variable-assignment
If a target matches more than one pattern, the matching pattern-specific
variables with longer stems are interpreted first.
%.o: %.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
lib/%.o: CFLAGS := -fPIC -g
%.o: CFLAGS := -g
all: foo.o lib/bar.o
Override directive
Environment Variables
Conditional directive
Syntax:
if-condition
text if the condition is true
endif
or
if-condition
text if the condition is true
else
text if the condition is false
endif
The if-condition can be one of:
ifdef variable-name ------ dont use $()
ifndef variable-name
ifeq test ------ a b
ifneq test ------ (a,b)
Include directive
Syntax: include filenames
When make processes an include directive, it suspends reading of the
containing makefile and reads from each listed file in turn. When that is
finished, make resumes reading the makefile in which the directive
appears.
Built-in functions
Syntax: $(function-name arg1[, argn])
String functions
$(filter pattern...,text)
Example:
words := he the hen other the%
get-the:
@echo he matches: $(filter he, $(words))
@echo %he matches: $(filter %he, $(words))
@echo he% matches: $(filter he%, $(words))
@echo %he% matches: $(filter %he%, $(words))
$(filter-out pattern...,text)
Example:
all_source := count_words.c counter.c lexer.l counter.h lexer.h
to_compile := $(filter-out %.h, $(all_source))
$(findstring string,text)
Example:
find-tree:
# PWD = $(PWD)
# $(findstring /test/book/admin,$(PWD))
# $(findstring /test/book/bin,$(PWD))
# $(findstring /test/book/out,$(PWD))
$(subst search-string,replace-string,text)
This is a simple, nonwildcard, search and replace.
Example:
sources := count_words.c counter.c lexer.c
objects := $(subst .c,.o, $(sources))
$(patsubst search-pattern,replace-pattern,text)
This is the wildcard version of search and replace.
strip-trailing-slash = $(patsubst %/,%,$(directory-path))
The syntax of a substitution reference is:
$(variable:search=replace)
$(words text)
This returns the number of words in text.
Example: CURRENT_PATH := $(subst /, ,$(HOME))
words:
@echo My HOME path has $(words $(CURRENT_PATH)) directories.
$(word n,text)
This returns the nth word in text.
current := $(word $(words $(MAKEFILE_LIST)), $(MAKEFILE_LIST))
$(firstword text)
version_list := $(subst ., ,$(MAKE_VERSION))
major_version := $(firstword $(version_list))
$(wordlist start,end,text) :This returns the words in text from start to end,
inclusive.
$(sort list)
The sort function sorts its list argument and removes duplicates.
$(shell command)
stdout := $(shell echo normal message)
stderr := $(shell echo error message 1>&2)
shell-value:
# $(stdout)
# $(stderr)
Filename Functions
$(wildcard pattern...) :accepts a list of patterns and performs expansion
on each one.
sources := $(wildcard *.c *.h)
dot-emacs-exists := $(wildcard ~/.emacs)
$(dir list...): returns the directory portion of each word in list. If the file
name contains no slash, the directory part is the string `./'.
$(dir src/foo.c hacks) produces the result `src/ ./'
source-dirs := $(sort \
$(dir \
$(shell find . -name '*.c')))
$(notdir name...): returns the filename portion of a file path.
$(OUT)/myfile.out: $(SRC)/source1.in $(SRC)/source2.in
cd $(dir $@); \
generate-myfile $^ > $(notdir $@)
$(suffix name...): returns the suffix of each word in its argument.
# $(call same-suffix, file-list)
same-suffix = $(filter 1 $(words $(sort $(suffix $1))))
$(basename name...): returns the filename without its suffix.
$(basename src/foo.c src-1.0/bar hacks) produces src/foo src-1.0/bar
hacks.
$(addsuffix suffix,name...): appends the given suffix text to each word in
name.
$(addsuffix .c,foo bar) produces the result `foo.c bar.c'.
$(addprefix prefix,name...): complement of addsuffix.
$(addprefix src/,foo bar) produces the result `src/foo src/bar'.
$(join prefix-list,suffix-list):
$(join a b,.c .o) produces `a.c b.o'
Flow Control
$(if condition,then-part,else-part)
$(if $(filter $(MAKE_VERSION),3.80),,\
$(error This makefile requires GNU make version 3.80.))
$(error text): used for printing fatal error messages. After the function prints
its message, make terminates with an exit status of 2.
$(foreach variable,list,body)
Example:
letters := $(foreach letter,a b c d,$(letter))
show-words:
# letters has $(words $(letters)) words: '$(letters)'
$ make
# letters has 4 words: 'a b c d'
$(strip text): removes all leading and trailing whitespace from text and
replaces all internal whitespace with a single space.
$(origin variable): returns a string describing the origin of a variable.
The possible return values of origin are:
undefined,default,environment,environmentoverride,file,commandline,ov
erride,automatic.
$(warning text): The warning function is similar to the error function
except that it does not cause make to exit.
Example:
$(if $(wildcard $(JAVAC)),, \
$(warning The java compiler variable, JAVAC ($(JAVAC)), \
is not properly set.))
$(eval )