Wednesday, August 27, 2025

Memo of Makefile - Learn how to build effeciently


Automatic Variables 

$@: an automatic variable that contains the target name
$?: all prerequisites newer than the target
$^: all prerequisites
$<: the first prerequisite

Implicit Rules

Compiling a C program

$(CC)  -c $(CPPFLAGS) $(CFLAGS) $^ -o $@

Static Pattern Rules

objects = foo.o bar.o all.o
all: $(objects)
$(CC) $^ -o all

# Syntax - targets ...: target-pattern: prereq-patterns ...
# In the case of the first target, foo.o, the target-pattern matches foo.o and sets the "stem" to be "foo".
# It then replaces the '%' in prereq-patterns with that stem
$(objects): %.o: %.c
$(CC) -c $^ -o $@

all.c:
echo "int main() { return 0; }" > all.c

# Note: all.c does not use this rule because Make prioritizes more specific matches when there is more than one match.
%.c:
touch $@

clean:
rm -f *.c *.o all

String Substitution

$(patsubst pattern,replacement,text)

subst is the equivalet function. 

Below is a shorthand form:

$(text:pattern=replacement)

The foreach function

The foreach function looks like this: $(foreach var,list,text). It converts one list of words (separated by spaces) to another. var is set to each word in list, and text is expanded for each word.
This appends an exclamation after each word:
foo := who are you
# For each "word" in foo, output that same word with an exclamation after
bar := $(foreach wrd,$(foo),$(wrd)!)

all:
# Output is "who! are! you!"
@echo $(bar)

The call function

First "define" the function just by creating a variable, but use the parameters $(0), $(1), etc. Then call the function with the special call builtin function. The syntax is $(call variable,param,param). $(0) is the variable, while $(1), $(2), etc. are the params. 

The shell function

It calls the shell, but it replaces newlines with spaces!

all: 
@echo $(shell ls -la) # Very ugly because the newlines are gone!

The filter function

The filter function is used to select certain elements from a list that match a specific pattern. For example, this will select all elements in obj_files that end with .o.

 obj_files = foo.result bar.o lose.o
filtered_files = $(filter %.o,$(obj_files))

all:
@echo $(filtered_files)

The eval function

    The eval function is very special: it allows you to define new makefile constructs that are not constant; which are the result of evaluating other variables and functions. The argument to the eval function is expanded, then the results of that expansion are parsed as makefile syntax. The expanded results can define new make variables, targets, implicit or explicit rules, etc.
    The result of the eval function is always the empty string; thus, it can be placed virtually anywhere in a makefile without causing syntax errors. 
    It’s important to realize that the eval argument is expanded twice; first by the eval function, then the results of that expansion are expanded again when they are parsed as makefile syntax. This means you may need to provide extra levels of escaping for “$” characters when using eval. The value function (see The value Function) can sometimes be useful in these situations, to circumvent unwanted expansions.


Reference Links

[1] Learn Makefiles 

No comments:

Post a Comment