
1What is Makefile
In the previous study of compiling C programs, we learned that compiling a program is relatively simple. However, if we need to compile multiple files or files in different folders, we need to generate different library files and determine the compilation order of these files, which often requires many complex command lines and can be cumbersome for future project maintenance.
Now, imagine if we need to compile a project like the Linux kernel with tens of thousands of files; would we need to input one command at a time? That would be a nightmare.
At this point, if we could standardize all the compilation rules in a file and execute the corresponding compilation instructions by parsing that file, it would greatly simplify the complexity of the instructions and reduce the errors that arise during the compilation process.
Based on the above requirements, Makefile was created. Our compilation and processing rules are placed in the Makefile, and the Makefile tool parses the commands in the Makefile to guide the entire project’s compilation process.
Of course, the commands in the Makefile have certain specifications, which is also a key point we will discuss today. Once the file is written, executing a single ‘make’ command in the Linux command line will automatically compile the entire project, improving development efficiency and facilitating future maintenance.
Different manufacturers’ make might vary slightly, and there are some differences in syntax, but the basic ideas are similar, mainly focusing on target dependencies. Here, we will explain using the most widely used GNU Make.
2Basic Rules of Makefile
The above shows the core rules of Makefile, which are somewhat similar to a chef cooking. The goal is to make a good dish, and the dependencies are various ingredients and kitchen tools. However, having these dependencies is not enough; the chef also needs excellent cooking skills to make a good dish.
These dependencies may not exist at the moment and need to be created on-site or prepared by other chefs. Therefore, this dependency becomes the target of other rules, which will also have their own dependencies and commands, forming a recursive dependency structure within the Makefile.
-
Makefile does not concern itself with how the commands are executed; it merely executes the defined commands, yielding the same effect as directly inputting command lines.
-
Makefile is essentially a dependency file. After executing this file, it will recursively search for dependency files and execute the corresponding commands, ultimately generating the first target.
3Simple Use of Makefile
Below, I will briefly demonstrate Makefile with previous code:
The above image shows the makefile. To generate the Test file, three *.o files are needed, and each of the three .o files depends on the corresponding *.c files. With the corresponding gcc commands, this forms a basic makefile.
Note: Lines 2/4/6/8 are all tab characters.
Next, we will use the make command to compile and generate the test target file.
By executingthe make command, we can complete all compilation tasks in one go.If we need to change the compilation process next time, we can simply modify the rules in the corresponding makefile.
Those familiar with the IDE environment in Windows know that in Windows, the development tools can compile everything with just one click. Does this mean the development tools in Windows are more powerful?
Actually, that’s not the case. When we build corresponding project files in Windows, the graphical interface quietly generates a similar makefile. So, when we click compile, it is akin to executing make in the command line; they are essentially similar, with the only difference being that we are more accustomed to using Windows.
This is merely a demonstration of some basic operations; the more complex aspects involve commands that can utilize wildcards and shell commands, which can add a certain level of complexity. In fact, makefile itself is not very difficult.
1Specifying the Use of Makefile
When using the make command in the command line, the makefile will search for the corresponding makefile in the default path for project management. We generally name the corresponding makefile as Makefile or makefile, etc. If the name does not match, the corresponding makefile may not be found, for example:
makefile filename
Makefile filename
MAKEFILE filename – Compilation failed
From the above experimental observations, we can see that make will look for the default makefile name. If it cannot find the specified file name, it will report an error.
However, if there are multiple makefile files in a directory, we usually distinguish them by different names. How can we specify the corresponding makefile for recognition and parsing? We can use the make -f option, as shown in the following image:
2Commenting Text
During development, if you need to comment out certain lines in the makefile, you can use the # symbol at the beginning of the line:
The above is a complete example of compiling target files in a makefile, which outputs the correct result. Then, I used the # symbol to comment out the first two lines, as shown in the following image:
After executing the make command, according to the rules of the makefile, it will default to compiling the Test1.o target file:
This way we obtained the correct result, indicating that the comment was effective.
3Suppressing Echo Text
In the makefile usage process, the corresponding processing information is echoed by default, which helps developers better understand the makefile processing. However, if the echoed information is too large, it can hinder developer analysis. Therefore, editors can use @ to suppress the echo of the relevant information, as shown in the following image:
Add @ after the command tab key
We can see that using make no longer displays the command line information as in the previous makefile.
4Using Phony Targets
In makefile files, sometimes we need to execute targets that do not require any dependency commands, which are called phony targets.
The above is the corresponding makefile, where a phony target clean is added, which can be executed directly using make clean.
Executing make clean indeed performed the clean operation.
5Using Variables
In makefile, to reduce code duplication, the concept of variables is used to simplify writing. For example, the following makefile can be modified as follows:
Using $(obj) to replace all target files means that if you need to add other target files later, you only need to modify the variable obj.
Meanwhile, the system also has other default automatic variables, which can greatly simplify the makefile, making it easier to design and maintain later, such as:
-
$^ represents all dependency files
-
$@ represents the generated target file
-
$< represents the first dependency file
-
etc.
The basic knowledge of makefile will stop here for now. In fact, most engineering projects are not entirely written from scratch but involve a lot of modifications, so when encountering specific questions, searching for answers may be more efficient.

Summary of Learning ARM from Scratch

0. What are Cortex, ARMv8, ARM architecture, ARM instruction set, and SoC? A comprehensive overview of basic concepts【Popular Science】

1. Learning ARM from Scratch – Installing Keil MDK uVision Integrated Development Environment

2. Learning ARM from Scratch – CPU Principles, Explanation Based on ARM SoC

3. Learning ARM from Scratch – ARM Modes, Registers, Pipelines
Recommended Reading
To join the group, please add WeChat account for embedded entry-level advancement.
Click “Read the Original” for more shares. Welcome to share, bookmark, like, and view.