对于一个C/C++项目,可以使用make命令进行项目的编译,将这个项目生产出一个可执行文件。

比如一个C/C++项目结构为:

1
2
3
4
5
6
7
- makefile_test
- main.cpp
- func_a.h
- func_a.cpp
- func_b.h
- func_b.cpp
- Makefile

对Makefile进行编辑

】:Makefile文件缩进需要使用Tab按钮

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# Makefile 示例

CC = g++
CXXFLAGS = -Wall -g

TARGET = main

all: $(TARGET)

$(TARGET): main.o func_a.o func_b.o
>---$(CC) $(CFLAGS) -o $(TARGET) main.o func_a.o func_b.o

main.o: main.cpp
>---$(CC) $(CFLAGS) -c main.cpp

func_a.o: func_a.cpp
>---$(CC) $(CFLAGS) -c func_a.cpp

func_b.o: func_b.cpp
>---$(CC) $(CFLAGS) -c func_b.cpp

clean:
>---rm -f *.o $(TARGET)

.PHONY: all clean
1
CC = g++

CC变量指定了编译器的名称

g++:当使用了C++程序时使用

CC可选项:g++、gcc

1
CXXFLAGS = -Wall -g

CFLAGSCXXFLAGS的区别:

  • CFLAGS用于给C语言配置
  • CXXFLAGS用于给C++语言配置

-Wall:启用所有常用的编译警告

-g:启用后,可以使用gdb或者其他调试工具进行调试

其他参数】:

-Wextra:启用额外的警告信息,进一步严格化代码

-O2-O3:优化选项,推荐-O2(吸氧或吸臭氧)

-std=c++11-std=c++17:C++ 标准版本。

1
TARGET = main

TARGET 变量通常用于指定 生成的最终可执行文件名称,也就是编译完成后所要生成的目标文件

也可以指定为其他文件格式:

  1. 可执行文件

    1
    TARGET = main
  2. 静态库

    1
    TARGET = main.a

    生成一个静态库文件

  3. 动态库

    1
    TARGET = main.so

    生成一个动态库文件

  4. 中间目标文件

    1
    TARGET = main.o

    生成一个中间目标文件

1
all: $(TARGET)

表示 all 目标依赖于 main,当 make 被执行时,make 会尝试生成 main 可执行文件。

1
2
$(TARGET): main.o func_a.o func_b.o
$(CC) $(CFLAGS) -o $(TARGET) main.o func_a.o func_b.o

Makefile 中,规则的格式如下:

1
2
target: dependencies
<TAB>command

其中:

  • target:表示要生成的目标文件(通常是一个文件名或伪目标),在这个例子中,target$(TARGET),代表要生成的目标文件(比如 main)。
  • dependencies:表示生成 target 所依赖的文件或其他目标。每当依赖文件发生改变时,make 会自动重新生成 target,在这个例子中,dependenciesmain.ofunc_a.ofunc_b.o。也就是说会执行一遍下面定义的命令make main.omake func_a.omake func_b.o生成三个文件main.o、func_a.o、func_b.o
  • command:是用 TAB 缩进的命令行,用于生成 target 的实际命令(例如编译器命令)。

command显示结果为:

1
g++ -Wall -g -o main main.o func_a.o func_b.o
  1. g++:表示使用 g++ 编译器进行链接(g++ 会自动链接 C++ 标准库)。

  2. -Wall -g:编译选项:

  • -Wall:启用所有常见的编译警告,帮助程序员发现潜在的代码问题。
  • -g:包含调试信息,方便使用 gdb 进行调试。
  1. -o main:表示输出文件名为 main,生成的可执行文件将被命名为 main

  2. main.o func_a.o func_b.o:这三个目标文件是链接时使用的中间文件,分别对应 main.cppfunc_a.cppfunc_b.cpp 编译生成的 .o 文件。

1
2
main.o: main.cpp
>---$(CC) $(CFLAGS) -c main.cpp

main.cpp编译为main.o(目标文件),但不会生成可执行文件。目的是汇总成TARGET这一个可执行文件。

func_a.o、func_b.o同理。

1
2
3
4
clean:
>---rm -f *.o $(TARGET)

.PHONY: all clean

在终端中执行make clean可以将*.oTARGET文件删除

-f当删除一个不存在的文件不会报错


.PHONY: all clean:将Makefile文件中的allclean隔离,防止与项目目录中的实际文件名产生冲突