In a previous article titled “One Skill a Day: Writing Makefile for Python Projects”, we discussed Makefile. Many students have left messages on the public account backend, wanting to learn more about how to write a Makefile. Thus, we have today’s article.
If you are currently using macOS or Linux, you can enter the command man make
in the terminal to view the help documentation for the make
command, as shown in the image below:

With the make
command, you can quickly run a large number of Shell commands, thus achieving one-click code compilation, one-click code formatting, and so on.
To learn Makefile, you need to have a Linux or macOS, and you need to understand two concepts: the make
command and the Makefile
file. The Makefile
file is a text file you write yourself, named Makefile
, and its name cannot be modified in case. The make
command is built into macOS and Linux. When we execute the make
command, it automatically reads the Makefile
file to determine what actions to take.
Let’s look at a practical example. The image below shows a very simple piece of Golang code:

In the code, some commas are missing spaces, and the struct is unevenly formatted. When we want to format a .go
file, we generally execute the command in the current folder:
gofmt -w xxx.go
After running, as shown in the image below:

To execute this command, you need to press the keyboard 15 times. Moreover, if there are many .go
files in your project located in different folders, you will also need to execute the command:
find . -name "*.go" | xargs gofmt -w
Then you will have to press even more keys.
At this point, we can create a Makefile
file in the project root directory with the following content:
fmt:
find . -name "*.go" | xargs gofmt -w
As shown in the image below:

Now, when we execute the command make fmt
in the project root directory, all .go
files in the entire project will be automatically formatted.
The format of the Makefile
is as follows:
Name1:
shell command1
shell command2
shell command3
Name2:
shell command4
shell command5
shell command6
Here, Name1
and Name2
are used to execute the command make name
, and each name can have multiple Shell commands underneath. This looks a bit like Python indentation. However, it is important to note that the indentation in Makefile can only use the Tab key, not spaces.
Let’s take another example. Now, I need to compile the project to generate an executable file and copy this executable file along with data.json
into a folder called output
. Our Makefile can be written as follows:
fmt:
gofmt -w *.go
build:
rm -rf output
mkdir output
go build -o JsonReader main.go
mv JsonReader ./output/
cp data.json ./output/
Then, when we execute the command make build
, the five commands below it will be executed automatically in one go.
One more example: some programs need to run in the local Docker environment after development. However, if there is already a container with the same name running, we must first stop the container, delete it, and then run it again. But with a Makefile, this becomes a one-line command:
deploy:
docker build -t xxx:latest
docker stop json_reader
docker rm json_reader
docker run --name json_reader --network host -d xxx:latest
In addition, Makefile supports chaining multiple Shell commands under different names
. For example, if I want to format the code, compile it into an executable file, and then use Docker to deploy, our final Makefile is as shown in the image below:

At this point, I only need to execute the command make
in the project root directory without any parameters, and all Shell commands under fmt
, build
, and deploy
will be executed in order. This greatly reduces our workload.
It can be said that whether it is a Golang project, Python, or other projects, using Makefile to automate the execution of some tedious and repetitive commands is a one-time solution.