Linux | Red Hat Certified | IT Technology | Operations Engineer
👇1000 people technical exchange QQ group, note 【public number】 for faster access
1. Basic Structure of Makefile
The Makefile contains a series of “rules”, with the basic structure of each rule as follows:
target…: prerequisites… <tab> command
Target(target): usually the name of the file to be generated, or the name of the action to be performed, such as “clean”.
Prerequisites(prerequisites): the files or intermediate targets required to generate the target.
Command(command): commands executed to generate the target from the prerequisites. The command must start with a Tab character, not spaces.
Example (some items like $@, $^, .PHONY will be explained later).:
test:test.ccg++ -o $@ $^.PHONY:cleanclean:rm -f test
Note:
In Linux, .cpp is equivalent to .cc and .cxx
g++ is a compiler for C++ syntax, while gcc is a compiler for C syntax.
Before Use:
After using make, an executable file test is created:
After using make clean, the executable file test is deleted:
2. Working Principle of Makefile
Dependency Check: Before generating the target, make checks whether the dependencies in the rule exist. If not, it looks for rules to generate the missing dependency files.
Update Check: If the dependencies exist, make checks whether the timestamps of the dependencies are newer than the target’s timestamp. If the dependency’s timestamp is updated, it executes the command to update the target.
Command Execution: If the target needs updating, the commands in the rule are executed.
3. Common Commands and Options in Makefile
make command
Function: By default, it executes the first target in the Makefile.
Example:
Makefile:
test1:test1.ccg++ -o test1 test1.cctest2:test2.ccg++ -o test2 test2.cc
It executes g++ -o test1 test1.cc but will not execute g++ -o test2 test2.cc; if you want to execute both, it will be explained later.
Only the executable file test1 will be created, and test2 will not be created.
make clean
Function: Usually used to clean up intermediate files and the final generated target files during the compilation process.
make -f file
Function: Specifies a non-standard name for the Makefile, not using the default names: Makefile or makefile.
Example:
Assuming you have a Makefile named alt_makefile, you can use it with the following command:
make -f alt_makefile
When using the -f option, make will not look for Makefile, makefile, or GNUmakefile files in the current directory unless you explicitly specify them with -f.
You can specify multiple -f options to include multiple Makefile files. Make will read these files in the specified order and merge their rules. If the same rule is defined in multiple files, the later files will override the definitions from earlier files.
In some complex projects, there may be multiple Makefile files, each used for different build targets or environments. The -f option allows you to flexibly choose which Makefile file to use.
make -C dir
Function: Changes the working directory to dir before reading the Makefile.
Example:
Assuming your project structure is as follows, and you want to build the project in the src directory:
project/ ├── Makefile └── src/ ├── Makefile └── ... (source files)
You can run the following command in the project root directory (project) to execute the Makefile in the src directory:
make -C src
make -n
Function: Prints the commands to be executed but does not execute them.
Example:
Only shows the execution content but does not execute, no executable file test is created.
make -s
Function: Executes the command but does not display the executed commands.
Example:
Does not display the execution content, but the command is executed, and the executable file test is created.
4. Variables in Makefile: $(VariableName) $@, $<, $^
Variables can be used in Makefile to simplify rule writing. Variables can be defined and used anywhere in the Makefile, and when referencing a variable, it must be in the form of $(VariableName).
Assignment: = and :=
When using = for assignment, Makefile performs lazy evaluation. This means the value of the variable is not immediately determined but recalculated based on the current value each time the variable is referenced.
When using := for assignment, Makefile performs immediate evaluation. This means the value of the variable is determined immediately at assignment and will not change thereafter (unless other mechanisms like the override directive are used).
$(VariableName)
Custom variable: For example, G=g++, defining a variable G with the value g++.
Example:
G=g++test:test.cc $(G) -o test test.cc
Equivalent to
test:test.cc g++ -o test test.cc
$@, $<, $^
Automatic variables: For example, $@ represents the target in the rule, $< represents the first prerequisite file, and $^ represents all prerequisite files.
Example 1:
test:test.cc g++ -o $@ $^
Equivalent to:
test:test.cc g++ -o test test.cc
Example 2:
test:test1.o test2.o test3.o g++ -o $@ $^
Equivalent to
test:test1.o test2.o test3.o g++ -o test test1.o test2.o test3.o
Example 3:
test:test.cc g++ -o $@ $<
Equivalent to
test:test.cc g++ -o test test.cc
5. Use of %
Pattern rules allow the use of % wildcard to match filenames, thus defining the same compilation rules for a group of files. For example:
CC=gcc%.o: %.c $(CC) -c $< -o $@
This rule indicates that for all .c files, use $(CC) -c command to compile them into corresponding .o files.
6. Use of .PHONY
Phony targets are those that do not actually generate files, such as “clean”. To avoid conflicts with files of the same name, you can declare phony targets using .PHONY:
Cleaning example
Makefile code:
.PHONY: clean clean: rm -f $(shell find -name "*.o")
PHONY: clean: This line declares that clean is a phony target. This means that whenever you run make clean, make will execute the commands under the clean target without checking whether a file named clean exists or is up to date. This is particularly useful for commands that do not generate files (like cleanup commands).
clean: This is the start of the clean phony target. It is followed by the commands to be executed under that target.
rm -f $(shell find -name “*.o”): This is the command to be executed under the clean target. This command uses a combination of shell functions and the find command to search for and delete all files with the .o extension in the current directory and its subdirectories (usually object files generated during the compilation process).
$(shell find -name “*.o”): The shell function executes the command inside the parentheses in the shell before executing commands in the Makefile (in this case find -name “*.o”). This command searches the current directory and all its subdirectories for files ending with .o and returns their full paths. These paths are then received by the rm -f command for deletion.
rm -f: This command is used to delete files, and the -f option means “force”, which will not report an error even if the files do not exist.
Multiple different .cc files forming multiple different executable files example (taking two as an example)
Makefile code:
all:test1 test2test1:test1.ccg++ -o test1 test1.cctest2:test2.ccg++ -o test2 test2.ccclean:rm -f test1 test2.PHONY: all clean
7. Common Functions in Makefile: wildcard and patsubst
Makefile provides many built-in functions, such as wildcard, patsubst, etc., for matching, replacing file names, and other operations.
wildcard
$(wildcard pattern): Finds all files in the current directory that match the pattern.
For example:
SRC=$(wildcard *.cc)
Finds all files with the .cc suffix in the current directory and assigns them to SRC. For example, if the current directory has main.cc and test.cc, then SRC=main.cc test.cc
Note: wildcard can only find files in the current directory. If the files you want to find are in a directory within the current directory, it cannot find them. In this case, you should use: SOURCES := $(shell find src -name “*.cc”)
patsubst
$(patsubst pattern,replacement,text): Replaces parts of text that match the pattern with replacement.
For example:
# Define a variable containing some filenames FILES = foo.c bar.c baz.h # Use patsubst to replace .c file extensions with .o OBJECTS = $(patsubst %.c,%.o,$(FILES))
8. Common Examples of Makefile
A test.cc file forms the corresponding test executable file
test:test.ccg++ -o $@ $^.PHONY:cleanclean: rm -f test
Effect:
Input make to create the executable file test
Input make clean to delete the executable file test
Multiple .cc files forming corresponding executable files (taking two as an example)
all:test1 test2test1:test1.ccg++ -o test1 test1.cctest2:test2.ccg++ -o test2 test2.ccclean:rm -f test1 test2.PHONY: all clean
Course consultation add: HCIE666CCIE
↑ Or scan the QR code above ↑
What technical points and content do you want to see?
You can leave a message below to tell Xiaomeng!