Detailed Explanation of Makefile in Linux



👆Click the blue text "Linux Armory" at the top, then select "Set as Star" at the top right
Don’t miss out on great articles, see valuable content first.

Detailed Explanation of Makefile in Linux

👆FollowLinux Armory, and receive hardcore Linux learning materials and code

Makefile is a tool used for building and managing projects, especially suitable for C/C++ projects. It defines the dependencies between various files in the project and specifies how to compile and link these files. Below is a simple example of a Makefile, along with a detailed explanation of its key parts:

1. Makefile Example

# Makefile Example

# Compiler
CC = gcc

# Compilation options
CFLAGS = -Wall -g

# Target file
TARGET = myprogram

# Source files
SRCS = main.c func1.c func2.c

# Intermediate files
OBJS = $(SRCS:.c=.o)

# Default target
all: $(TARGET)

# Target file generation rule
$(TARGET): $(OBJS)
	$(CC) $(CFLAGS) -o $@ $^

# Intermediate file generation rule
%.o: %.c
	$(CC) $(CFLAGS) -c -o $@ $<

# Clean rule
clean:
	rm -f $(TARGET) $(OBJS)

2. Makefile Explanation

  • CC: Variable for the compiler, using gcc here.

  • CFLAGS: Variable for compilation options, setting -Wall (show all warnings) and -g (generate debug information).

  • TARGET: Variable for the target file, defining the name of the final executable file.

  • SRCS: Variable for source files, listing all source files here.

  • OBJS: Variable for intermediate files, replacing the suffix of source files from .c to .o.

  • all: Default target, this will be built when executing the make command.

  • $(TARGET): Generation rule for the target file, telling Make how to generate the final executable file.

  • $(OBJS): Generation rule for intermediate files, telling Make how to generate intermediate target files.

  • %.o: %.c: Generic rule, telling Make how to compile .c files into corresponding .o files.

  • clean: Clean rule, executing make clean will delete the generated executable and intermediate target files.

3. Using Makefile

In the project directory, execute the following commands:

  • Build the project: make or make all.

  • Clean the project: make clean.

4. Notes

  • Whitespace Issue: Makefile uses the Tab key instead of spaces to indent rules.

  • File Dependencies: The core of Makefile is the dependencies between files, ensuring that each target depends on the correct files.

  • Variable References: Use $@ to represent the target, $^ to represent all dependent files, and $<code> to represent the first dependent file.

  • Wildcards: Use % wildcard to represent a class of files, for example, %.o: %.c.

Makefile is a very powerful tool that can be used to manage complex project structures. The above example is a simple entry-level Makefile, while actual projects may contain more configurations and rules.

5. Makefile Rules

Makefile typically contains rules that describe how to generate one or more target files. The basic format of each rule is as follows:

target: dependencies
	command
  • target: The name of the target file, which can be an executable file, an intermediate file, or a label.

  • dependencies: A list of files that the target file depends on, which are needed to generate the target file.

  • command: The command to generate the target file, describing how to generate the target file from the dependent files.

Here is a simple example:

main: main.o utils.o
	gcc -o main main.o utils.o

main.o: main.c
	gcc -c main.c

utils.o: utils.c
	gcc -c utils.c

In this example, main is the target file, which depends on main.o and utils.o. The command to generate main file is gcc -o main main.o utils.o. Similarly, main.o depends on main.c, and utils.o depends on utils.c.

6. Automatic Variables

Makefile has some special variables called automatic variables, which are used in the commands of rules to represent specific information. Some commonly used automatic variables are:

  • $@: Represents the name of the target file.

  • $<code>: Represents the name of the first dependent file in the rule.

  • $^: Represents the names of all dependent files in the rule, separated by spaces.

Here is an example of using automatic variables:

main: main.o utils.o
	gcc -o $@ $^

This rule is equivalent to the previous rule, using automatic variables to represent the target file and all dependent files.

7. Generic Rules

If there are multiple similar target files, generic rules can be used. Generic rules use the wildcard % to match part of the file name.

%.o: %.c
	gcc -c $<

This rule indicates that for any .o file, it depends on the corresponding .c file, and the generation rule is gcc -c $<code>.

8. Variables

Variables can be defined in Makefile to store strings, file names, compilation options, and other information. The format for defining variables is as follows:

VAR_NAME = value

Example of using variables:

CC = gcc
CFLAGS = -Wall -O2

main: main.o utils.o
	$(CC) -o $@ $^ $(CFLAGS)

In this example, CC and CFLAGS are both variables, storing the compiler and compilation options, respectively. When used in the command of the rule, $(CC) and $(CFLAGS) replace specific values.

9. Include Directive

Makefile can include other Makefiles using the include directive. This can split the Makefile into multiple modules for better maintainability.

include common.mk

main: main.o utils.o
	$(CC) -o $@ $^ $(CFLAGS)

10. PHONY Targets

Sometimes, we need to define some targets that do not produce actual files, such as cleaning temporary files or executing specific tasks. To tell Make that these targets are not file names, we can use .PHONY targets.

.PHONY: clean

clean:
	rm -f *.o main

In this example, clean is a PHONY target used to delete temporary files.

When building a software project, the make tool can automate the compilation process, ensuring that only files that have changed are recompiled. make uses a file named Makefile, which contains a series of rules and instructions describing the dependencies between files and how to generate target files. Below is a simple structure and basic elements of a Makefile:

11. Basic Structure

Makefile consists of a series of rules and variables. Each rule describes how to generate one or more target files. The basic structure is as follows:

# Comments start with '#'
# Variable definitions
CC = gcc
CFLAGS = -Wall

# The first rule is the default rule
all: target1 target2

# Rule: Target files depend on files
# [tab] Instructions (commands to generate target files)
target1: dependency1 dependency2
	$(CC) $(CFLAGS) -o target1 dependency1 dependency2

target2: dependency3 dependency4
	$(CC) $(CFLAGS) -o target2 dependency3 dependency4

12. Variables

In Makefile, variables can be used to store and reference values. In the above example, CC and CFLAGS are variables that store the compiler and compilation options, respectively.

13. Rules

Rules consist of the following parts:

  • Target: Describes the name of the generated file. Multiple targets can be specified, separated by spaces.
  • Dependencies: Describes the list of files that the target file depends on. If the content of the dependent files changes, the target file will be regenerated.
  • Commands: Describes the commands to generate the target file. Commands must be preceded by a tab character (\t).

14. Default Rules

The first rule is usually the default rule, which is executed by default when the make command is run. In the above example, the default rule is all: target1 target2.

15. Wildcards

Makefile supports wildcards to match file lists. Common wildcards include * (matches any character) and % (matches any sequence of characters).

# Match all files ending with .c
sources = $(wildcard *.c)

16. Automatically Generate Dependencies

Using the -M option allows the compiler to automatically generate dependencies. This is helpful for tracking dependencies between header files.

# Automatically generate dependencies
%.d: %.c
	$(CC) -M $< > $@

17. Include Directive

Using the include directive allows other Makefile files to be included in the current Makefile.

# Include other Makefile files
include other.mk

18. Example

Below is a simple Makefile example for a C language project:

CC = gcc
CFLAGS = -Wall
LDFLAGS =

SRCDIR = src
OBJDIR = obj
BINDIR = bin

SOURCES = $(wildcard $(SRCDIR)/*.c)
OBJECTS = $(patsubst $(SRCDIR)/%.c,$(OBJDIR)/%.o,$(SOURCES))
EXECUTABLE = $(BINDIR)/my_program

all: $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS)
	$(CC) $(LDFLAGS) -o $@ $^

$(OBJDIR)/%.o: $(SRCDIR)/%.c
	$(CC) $(CFLAGS) -c -o $@ $<

clean:
	rm -rf $(OBJDIR)/*.o $(EXECUTABLE)

This Makefile describes a simple project structure, where source files are located in the src directory, target files in the obj directory, and executable files in the bin directory. This Makefile includes all (default target), clean (clean target), and other rules.

19. Functions

Makefile supports some built-in functions for handling strings, paths, etc. Common functions include $(wildcard), $(patsubst), $(foreach), etc.

# Get a list of all .c files
C_FILES = $(wildcard src/*.c)

# Replace .c files with .o files
O_FILES = $(patsubst src/%.c, obj/%.o, $(C_FILES))

# Use foreach to iterate
SOURCES = file1.c file2.c file3.c
OBJECTS = $(foreach src, $(SOURCES), obj/$(src:.c=.o))

20. Conditional Statements

Conditional statements can be used in Makefile to execute different commands based on different conditions.

# Conditional statements
ifeq ($(DEBUG),1)
	CFLAGS += -g
else
	CFLAGS += -O2
endif

21. Recursive Calls

Makefile can build sub-targets through recursive calls.

# Recursive calls
subtarget:
	$(MAKE) -C subdir

22. Example

Below is a Makefile example that includes multiple source files, header files, and library files:

CC = gcc
CFLAGS = -Wall
LDFLAGS =

SRCDIR = src
INCDIR = include
OBJDIR = obj
BINDIR = bin
LIBDIR = lib

SOURCES = $(wildcard $(SRCDIR)/*.c)
HEADERS = $(wildcard $(INCDIR)/*.h)
OBJECTS = $(patsubst $(SRCDIR)/%.c,$(OBJDIR)/%.o,$(SOURCES))
EXECUTABLE = $(BINDIR)/my_program
LIBRARY = $(LIBDIR)/libmylibrary.a

all: $(EXECUTABLE) $(LIBRARY)

$(EXECUTABLE): $(OBJECTS)
	$(CC) $(LDFLAGS) -o $@ $^

$(LIBRARY): $(OBJECTS)
	ar rcs $@ $^

$(OBJDIR)/%.o: $(SRCDIR)/%.c $(HEADERS)
	$(CC) $(CFLAGS) -I$(INCDIR) -c -o $@ $<

clean:
	rm -rf $(OBJDIR)/*.o $(EXECUTABLE) $(LIBRARY)

This Makefile describes a project containing multiple source files, including default target all, clean target clean, and two generation targets: one executable and one static library. Note that the variables and rules in this Makefile can be adjusted according to the project’s structure and needs.

23. Installation Rules

Makefile can include installation rules for installing executable files, library files, etc., to specified locations. Below is a simple installation rule example:

INSTALL_DIR = /usr/local/bin

install: $(EXECUTABLE)
	cp $(EXECUTABLE) $(INSTALL_DIR)

uninstall:
	rm -f $(INSTALL_DIR)/$(notdir $(EXECUTABLE))

In this example, the install rule copies the executable file to the specified directory ($(INSTALL_DIR)). The uninstall rule deletes the installed executable file.

↓↓Recommended Articles↓↓

👉 Detailed Methods for Creating Library Files in Linux

👉 Summary of the Most Common Command Usages in Linux (Selection)

👉 Step-by-Step Guide to Writing Linux Thread Pools

👉 Summary of Common Methods in Linux Shell Programming

👉 Essence of C++ Basic Knowledge

↓↓Recommended Collections↓↓

👉 Collection of C Language Introductory Tutorials

👉 Collection of Common Software Tools

👉 Collection of Linux Knowledge

👉 Collection of Linux Libraries Explained

Detailed Explanation of Makefile in Linux

For learning and communication, pleaseaddAssistant WeChatto join high-quality learning groups

👇Learn from others to improve yourself👇

Please clickTechnical Learning Group

FollowLinux Armory, reply in the chat interface with「1024」to get all Linux materials and code.

Technical work requires step-by-step accumulation, building a strong foundation for future success
「Do not regret wasting time, do not feel ashamed of being unproductive」

Detailed Explanation of Makefile in Linux

Make progress every day, support the author, remember to like and share!

Support the author, please extend your hand to prosperity

Share, collect👇👇👇👇👇Like, view

Support quality content with action!

Leave a Comment