目录
1.make
1.1 make 命令格式
2.Makefile 核心概念
2.1创建并运行 Makefile步骤
3. Makefile编写
3.1最基础Makefile
3.1.1利用默认make命令
3.1.2利用make -f 命令
3.1.2.1 利用make -f 命令实验默认make操纵
3.1.2.2利用 make [ ‐f file ] [ targets ]命令
3.1.2.3利用 make [ ‐f file ] [ targets ]命令,并实验可实验程序
3.1.3 gcc编译常用组合选项
3.1.4 make 和 make all区别
3.1.4.1 all 是默认目的
3.1.4.2 all 不是默认目的
3.1.4.3 没有界说 all 命令
3.1.4.3 逼迫设置 all 为默认目的
3.2多文件编程Makefile-基础
3.3makefile变量
3.3.1 makefile 变量概述
3.3.2 makefile 的变量分类:
3.3.3 自界说变量语法
3.3.3.1自界说变量makefile多文件编程
3.3.4体系变量
3.3.5预界说变量
3.3.5.1编译器与工具
3.3.5.2. 编译选项
3.3.5.3. 文件与目录
3.3.5.4. 隐式规则中的关键变量
3.3.5.5. 常用内置变量
3.3.5.6.程序验证
4.几种多文件编程Makefile对应关系
1.make
make是个命令,是个可实验程序,用来解析Makefile文件的命令。 终端输入:which make 查看make保存地址,在 /usr/bin/make 1.1 make 命令格式
- make [ ‐f file ] [ targets ]
复制代码 (1)[ -f file ]: make默认在工作目录中寻找名为GNUmakefile、makefile、Makefile的文件作为 makefile输入文件, -f 可以指定以上名字以外的文件作为makefile输入文件 (2)[ targets ]: 若利用make命令时没有指定目的,则make工具默认会实现makefile文件内的第一个目 标 ,然后退出,指定了make工具要实现的目的,目的可以是一个或多个(多个目的间用空 格隔开)。 2.Makefile 核心概念
作用:
自动化编译和链接程序,管理项目依靠关系,避免重复编译未修改的代码。
基本结构:
- target: dependencies
- command
- target: 生成的目标(如可执行文件、中间文件)
- dependencies: 生成目标所需的文件或目标
- command: 生成目标的命令(必须以 Tab 开头)
复制代码 2.1创建并运行 Makefile步骤
基本步骤:
- 创建文件:在项目根目录创建名为 Makefile 的文件(无后缀)。
- 编写规则:界说目的(如可实验文件)、依靠(如 .c 和 .o 文件)和命令。
- 运行命令:在终端实验 make 或 make <target>。
3. Makefile编写
make 命令格式
- make [ ‐f file ] [ targets ]
复制代码 (1)[ -f file ]: make默认在工作目录中寻找名为GNUmakefile、makefile、Makefile的文件作为 makefile输入文件, -f 可以指定以上名字以外的文件作为makefile输入文件 (2)[ targets ]: 若利用make命令时没有指定目的,则make工具默认会实现makefile文件内的第一个目 标 ,然后退出,指定了make工具要实现的目的,目的可以是一个或多个(多个目的间用空 格隔开)。 3.1最基础Makefile
3.1.1利用默认make命令
程序:
main.c
- #include <stdio.h>
- #include "main.h"
- int main(int argc, char const *argv[])
- {
- printf("main函数开始\n");
- printf("ABC = %d abc = %d\n",ABC, abc);
-
- return 0;
- }
复制代码 main.h
- #define ABC 123
- #define abc 456
复制代码 makefile
- main:main.c main.h
- gcc main.c -o main
-
- clean:
- rm main
复制代码 makefile内容解释:
main:main.c main.h //可实验文件main依靠main.c main.h
gcc main.c -o main //由mian.c 生成可实验文件main
clean:
rm main //实验 make clean 命令,删除可实验文件main
运行结果:
3.1.2利用make -f 命令
3.1.2.1 利用make -f 命令实验默认make操纵
程序:与3.1.1利用默认make命令一样。
makefile:与3.1.1利用默认make命令一样。仅名称不同。
将可实验文件main删除,Makefile复制一份,重命名为Makefile1,实验 make -f Makefile1
也可以正常实验make命令。实验结果与默认make命令结果相同。
3.1.2.2利用 make [ ‐f file ] [ targets ]命令
程序:与3.1.1利用默认make命令一样。
makefile:
- test:main.c main.h
- gcc main.c -o main
- @echo "=== test ==="
-
- clean:
- rm main
- @echo "=== clean ==="
- test1:
- @echo "=== test1 ==="; # @符号注释见下面
- #echo前使用 @:在 echo 前添加 @ 符号,可隐藏命令本身的输出,仅显示命令的执行结果
- #终端结果: === test1 ===
-
- #未使用 @:命令本身和执行结果都会显示,
- #终端结果: echo "=== test1 ==="
- # === test1 ===
- # 在 Makefile 中直接写 @echo "注释内容" # 注释内容, 注释内容会输出在终端,
- # 因为 # 必须出现在行首或通过 ; 分隔
- test2:
- @echo "=== test2 ==="; # @符号注释见上面
复制代码 (1)实验 make -f Makefile2 test1 test test2
test1 test test2 为Makefile2中的三个目的文件,实验上述命令,先运行test1内里的运行命令,在运行test运行命令,最后运行test2运行命令。
运行结果:
(2)实验 make -f Makefile2 test1 test2 clean 命令
test1 test2 clean 为Makefile2中的三个目的文件,实验上述命令,先运行test1内里的运行命令,在运行test2运行命令,最后运行clean运行命令。
运行结果:
注意:包管实验 clean命令,确保删除的文件要存在。
删除文件不存在运行结果:
3.1.2.3利用 make [ ‐f file ] [ targets ]命令,并实验可实验程序
程序:与3.1.1利用默认make命令一样。
makefile:
- test:main.c main.h
- gcc main.c -o main
- @echo "=== test ==="
-
- clean:
- rm main
- @echo "=== clean ==="
- test1:
- @echo "=== test1 ==="; # @符号注释见下面
- #echo前使用 @:在 echo 前添加 @ 符号,可隐藏命令本身的输出,仅显示命令的执行结果
- #终端结果: === test1 ===
-
- #未使用 @:命令本身和执行结果都会显示,
- #终端结果: echo "=== test1 ==="
- # === test1 ===
- # 在 Makefile 中直接写 @echo "注释内容" # 注释内容, 注释内容会输出在终端,
- # 因为 # 必须出现在行首或通过 ; 分隔
- test2:
- @echo "=== test2 ==="; # @符号注释见上面
复制代码 (1)实验 make -f Makefile2 test1 test2 test;./main 命令
实验Makefile命令后,并运行生成的可实验文件
(2)实验 make -f Makefile2 test;./main 命令
实验Makefile命令后,并运行生成的可实验文件
3.1.3 gcc编译常用组合选项
选项作用示例-o指定输出文件名gcc -c main.c -o main.o-I指定头文件搜索路径gcc -c main.c -I../include-Wall启用所有警告信息gcc -c main.c -Wall-g生成调试信息(用于 GDB)gcc -c main.c -g-O2启用优化(级别 2)gcc -c main.c -O2 3.1.4 make 和 make all区别
关键总结
场景make 行为make all 行为all 是默认目的实验 all实验 allall 不是默认目的实验第一个目的(如 build)实验 all(需存在界说)未界说 all实验第一个目的报错逼迫 .DEFAULT_GOAL=all实验 all实验 all 3.1.4.1 all 是默认目的
当 all 是默认目的时,make 和 make all 运行次序,结果相同。
程序:
main.c
- #include <stdio.h>
- int main(int argc, const char *argv[])
- {
- int x = 60;
- int y = 20;
- printf("main x= %d y= %d \n", x, y);
-
- return 0;
- }
复制代码 makefile
- # all 是第一个目标(默认目标)
- all:target
- echo " all开始"
- target:main.c
- gcc main.c -o main
- echo " main开始"
- clean:
- rm main *.o -rf
复制代码 运行结果:当 all 是默认目的时,make 和 make all 运行次序,结果相同。
(1)make all
(2)make
3.1.4.2 all 不是默认目的
all 不是默认目的,实验make all命令,会先实验 all依靠的命令。
程序:
main.c
- #include <stdio.h>
- int main(int argc, const char *argv[])
- {
- int x = 60;
- int y = 20;
- printf("main x= %d y= %d \n", x, y);
-
- return 0;
- }
复制代码 makefile
- # 若makefile命名不是 GNUmakefile、makefile、Makefile 中的一个
- # 要使用 make -f Makefile名称,执行make命令
- # all 不是第一个目标
- target:main.c
- gcc main.c -o main
- echo " main开始"
- all:clean target
- echo " all开始"
- clean:
- rm main *.o -rf
复制代码 运行结果:
(1) 初次make 编译, 实验默认目的 target,编译 gcc main.c -o main
(2)实验make all命令,会先实验 clean命令 rm main *.o -rf,在编译gcc main.c -o main
3.1.4.3 没有界说 all 命令
main.c
- #include <stdio.h>
- int main(int argc, const char *argv[])
- {
- int x = 60;
- int y = 20;
- printf("main x= %d y= %d \n", x, y);
-
- return 0;
- }
复制代码 makefile
- # 若makefile命名不是 GNUmakefile、makefile、Makefile 中的一个
- # 要使用 make -f Makefile名称,执行make命令
- target:main.c
- gcc main.c -o main
- echo " main开始"
- clean:
- rm main *.o -rf
复制代码 运行结果:make all运行报错,make正常运行。
3.1.4.3 逼迫设置 all 为默认目的
main.c
- #include <stdio.h>
- int main(int argc, const char *argv[])
- {
- int x = 60;
- int y = 20;
- printf("main x= %d y= %d \n", x, y);
-
- return 0;
- }
复制代码 makefile
- # 若makefile命名不是 GNUmakefile、makefile、Makefile 中的一个
- # 要使用 make -f Makefile名称,执行make命令
- # 显式设置 .DEFAULT_GOAL 为 all
- .DEFAULT_GOAL = all
- target:main.c
- gcc main.c -o main
- echo " main开始"
- all:clean target
- echo " all开始"
- clean:
- rm main *.o -rf
复制代码 运行结果:逼迫设置 all 为默认目的,实验make命令,先实验all依靠的语句。
3.2多文件编程Makefile-基础
main.c
- #include "head.h"
- int main(int argc, const char *argv[])
- {
- int x = 60;
- int y = 20;
- printf("%d + %d = %d\n", x, y, sum(x, y));
- printf("%d - %d = %d\n", x, y, sub(x, y));
-
- return 0;
- }
复制代码 sub.c
- #include "head.h"
- int sub(int a, int b)
- {
- return a - b;
- }
复制代码 sum.c
- #include "head.h"
- int sum(int a, int b)
- {
- return a + b;
- }
复制代码 head.h
- #ifndef _HEAD_H_
- #define _HEAD_H_
- #include <stdio.h>
- int sum(int a, int b);
- int sub(int a, int b);
- #endif
复制代码 Makefile
- main:main.o sub.o sum.o
- gcc main.o sub.o sum.o -o main
- main.o:main.c
- gcc -c main.c -o main.o
- sub.o:sub.c
- gcc -c sub.c -o sub.o
- sum.o:sum.c
- gcc -c sum.c -o sum.o
- clean:
- rm *.o main a.out -rf
-
复制代码 Makefile语句解释:
main:main.o sub.o sum.o //可实验文件main依靠于main.o sub.o sum.o
gcc main.o sub.o sum.o -o main //gcc 编译 main.o sub.o sum.o 生成可实验文件main
main.o:main.c //可实验文件main.o依靠于main.c
gcc -c main.c -o main.o //gcc 编译 main.c 生成可实验文件main.o
sub.o:sub.c //可实验文件sub.o依靠于sub.c
gcc -c sub.c -o sub.o //gcc 编译 sub.c 生成可实验文件sub.o
sum.o:sum.c //可实验文件sum.o依靠于sum.c
gcc -c sum.c -o sum.o //gcc 编译 sum.c 生成可实验文件sum.o
clean:
rm *.o main a.out -rf //实验 make clean删除可实验文件,所有.o文件 main a.out
实验次序:
可实验文件main依靠于main.o,main.o又依靠于main.c,先实验gcc -c main.c -o main.o,在实验gcc main.o sub.o sum.o -o main
运行结果:
3.3makefile变量
3.3.1 makefile 变量概述
makefile 变量雷同于 C 语言中的宏,当 makefile 被 make 工具解析时,此中的变量会被展开。 变量的作用: 保存文件名列表 保存文件目录列表 保存编译器名 保存编译参数 保存编译的输出 ... 3.3.2 makefile 的变量分类:
1 、自界说变量 在 makefile 文件中界说的变量。 make 工具传给 makefile 的变量。 2 、体系情况变量 make 工具解析 makefile 前,读取体系情况变量并设置为 makefile 的变量。 3 、预界说变量(自动变量) 3.3.3 自界说变量语法
界说变量: 变量名 = 变量值 引用变量: $( 变量名 ) 或 ${ 变量名 } makefile 的变量名 : makefile 变量名可以以数字开头 注意: 1 、变量是大小写敏感的 2 、变量一样寻常都在 makefile 的头部界说 3 、变量险些可在 makefile 的任何地方利用
常用变量:
- 定义变量:VAR = value
- 使用变量:$(VAR)
- 常用内置变量:
- CC:C 编译器(默认 cc,通常指向 gcc)。
- CFLAGS:C 编译选项(如 -Wall -O2)。
- LDFLAGS:链接选项(如 -L 指定库路径)。
- LDLIBS:链接库(如 -lm 表示数学库)。
复制代码 3.3.3.1自界说变量makefile多文件编程
程序:
main.c
- #include "head.h"
- int main(int argc, const char *argv[])
- {
- int x = 60;
- int y = 20;
- printf("%d + %d = %d\n", x, y, sum(x, y));
- printf("%d - %d = %d\n", x, y, sub(x, y));
-
- return 0;
- }
复制代码 sub.c
- #include "head.h"
- int sub(int a, int b)
- {
- return a - b;
- }
复制代码 sum.c
- #include "head.h"
- int sum(int a, int b)
- {
- return a + b;
- }
复制代码 head.h
- #ifndef _HEAD_H_
- #define _HEAD_H_
- #include <stdio.h>
- int sum(int a, int b);
- int sub(int a, int b);
- #endif
复制代码 Makefile
- CC=gcc
- obj=main
- obj1=sub
- obj2=sum
- OBJS=main.o sub.o sum.o
- $(obj):$(OBJS)
- $(CC) $(OBJS) -o $(obj)
- $(obj).o:$(obj).c
- $(CC) -c $(obj).c -o $(obj).o
- $(obj1).o:$(obj1).c
- $(CC) -c $(obj1).c -o $(obj1).o
- $(obj2).o:$(obj2).c
- $(CC) -c $(obj2).c -o $(obj2).o
- clean:
- rm *.o $(obj) a.out -rf
复制代码 Makefile语句解释:与3.2多文件编程Makefile-基础,一样,只是替换为自界说的变量
main:main.o sub.o sum.o //可实验文件main依靠于main.o sub.o sum.o
gcc main.o sub.o sum.o -o main //gcc 编译 main.o sub.o sum.o 生成可实验文件main
main.o:main.c //可实验文件main.o依靠于main.c
gcc -c main.c -o main.o //gcc 编译 main.c 生成可实验文件main.o
sub.o:sub.c //可实验文件sub.o依靠于sub.c
gcc -c sub.c -o sub.o //gcc 编译 sub.c 生成可实验文件sub.o
sum.o:sum.c //可实验文件sum.o依靠于sum.c
gcc -c sum.c -o sum.o //gcc 编译 sum.c 生成可实验文件sum.o
clean:
rm *.o main a.out -rf //实验 make clean删除可实验文件,所有.o文件 main a.out
实验次序:
可实验文件main依靠于main.o,main.o又依靠于main.c,先实验gcc -c main.c -o main.o,在实验gcc main.o sub.o sum.o -o main
运行结果:
3.3.4体系变量
make 工具会拷贝体系的情况变量并将其设置为 makefile 的变量,在 makefile 中可直接读取或修改拷贝后的变量。 程序: main.c - #include <stdio.h>
- int main(int argc, const char *argv[])
- {
- int x = 60;
- int y = 20;
- printf("x = %d y = %d \n", x, y);
-
- return 0;
- }
复制代码 Makefile
- main:main.c
- gcc main.c -o main
-
- clean:
- rm main -rf
- echo $(PWD)
- echo $(HOME)
- echo $(HOSTNAME)
- echo $(MY_SHELL_NUM)
复制代码 运行结果: (1)先在终端实验shell脚本,设置一个预设情况变量,echo 输出一下。 MY_SHELL_NUM=123 export MY_SHELL_NUM echo $MY_SHELL_NUM (2)实验 make 命令,在实验 make clean 命令,shell语句的结果输出在终端。 分别输出 PWD ,HOME,HOSTNAME,MY_SHELL_NUM这四个变量的结果 3.3.5预界说变量
- $@ 目标名
- $< 依赖文件列表中的第一个文件
- $^ 依赖文件列表中除去重复文件的部分
- AR 归档维护程序的程序名,默认值为 ar
- ARFLAGS 归档维护程序的选项
- AS 汇编程序的名称,默认值为 as
- ASFLAGS 汇编程序的选项
- CC C 编译器的名称,默认值为 cc
- CFLAGS C 编译器的选项
- CPP C 预编译器的名称,默认值为$(CC) -E
- CPPFLAGS C 预编译的选项
- CXX C++编译器的名称,默认值为 g++
- CXXFLAGS C++编译器的选项
复制代码 3.3.5.1编译器与工具
变量名默认值形貌示例用法CCccC 编译器CC = gccCXXg++C++ 编译器CXX = clang++ARar静态库打包工具AR = ar rcsASas汇编器AS = nasmLDld链接器LD = lld 3.3.5.2. 编译选项
变量名形貌默认值示例用法CFLAGSC 编译选项空CFLAGS = -O2 -WallCXXFLAGSC++ 编译选项空CXXFLAGS = -std=c++17CPPFLAGS预处理惩罚选项(C/C++通用)空CPPFLAGS = -IincludeLDFLAGS链接器选项(如库路径)空LDFLAGS = -LlibLDLIBS链接的库(如 -lm)空LDLIBS = -lpthread 3.3.5.3. 文件与目录
变量名形貌默认值示例用法MAKEFILE_LIST当前 Makefile 文件名列表自动生成用于条件判断VPATH搜索源文件的目录列表空VPATH = src:libSRC自界说源文件变量无SRC = main.c utils.cOBJ自界说目的文件变量无OBJ = $(SRC:.c=.o) 3.3.5.4. 隐式规则中的关键变量
Make 根据文件后缀自动推导编译规则,以下变量控制隐式规则行为:
变量名形貌默认命令示例覆盖COMPILE.cC 文件编译命令$(CC) $(CFLAGS) $(CPPFLAGS) -cCOMPILE.c = $(CC) -O3LINK.cC 程序链接命令$(CC) $(CFLAGS) $(LDFLAGS)LINK.c = $(CC) -flto 3.3.5.5. 常用内置变量
变量名形貌示例值MAKE当前 Make 命令路径/usr/bin/makeMAKECMDGOALS用户指定的目的列表all cleanCURDIR当前工作目录/home/user/project
3.3.5.6.程序验证
程序:
main.c
- #include "head.h"
- int main(int argc, const char *argv[])
- {
- int x = 60;
- int y = 20;
- printf("%d + %d = %d\n", x, y, sum(x, y));
- printf("%d - %d = %d\n", x, y, sub(x, y));
-
- return 0;
- }
复制代码 sub.c
- #include "head.h"
- int sub(int a, int b)
- {
- return a - b;
- }
复制代码 sum.c
- #include "head.h"
- int sum(int a, int b)
- {
- return a + b;
- }
复制代码 head.h
- #ifndef _HEAD_H_
- #define _HEAD_H_
- #include <stdio.h>
- int sum(int a, int b);
- int sub(int a, int b);
- #endif
复制代码 Makefile
- CC=gcc
- obj=main
- obj1=sub
- obj2=sum
- OBJ=main.o sub.o sum.o
- CFLAGS=-Wall -O2
- # -Wall警告相关, -O2:优化选项,兼顾编译速度和性能
- $(obj):$(OBJ)
- $(CC) $^ -o $@
- $(obj).o:$(obj).c
- $(CC) $(CFLAGS) -c $< -o $@
- $(obj1).o:$(obj1).c
- $(CC) $(CFLAGS) -c $< -o $@
- $(obj2).o:$(obj2).c
- $(CC) $(CFLAGS) -c $< -o $@
- clean:
- rm *.o $(obj) a.out -rf
-
复制代码 Makefile语句解释:
与3.3.3 自界说变量语法,一样,只是替换为预界说的变量。表达式的区别见4.几种多文件编程Makefile对应关系。
运行结果:
注:Makefile更精简表达式
Makefile1
- CC=gcc
- obj=main
- OBJ=main.o sub.o sum.o
- CFLAGS=-Wall -g
- $(obj):$(OBJ)
- $(CC) $^ -o $@
- %*.o:%*.c #使用通配符匹配,所有.c文件都去执行下面的命令
- $(CC) $(CFLAGS) -c $< -o $@
- clean:
- rm *.o $(obj) a.out -rf
复制代码 运行结果:与上述Makefile运行结果相同
(1)先在终端实验 make clean (2)终端实验 make -f Makefile1
4.几种多文件编程Makefile对应关系
多文件编程Makefile最基础、自界说变量、预界说变量对应关系。
每一行为几种方法相同结果,不同格式的变量表达式。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |