ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

【Linux】 Makefile 详解

【Linux】 Makefile 详解 Makefile文章目录Makefile1.初次实现1.1 没创建之前1.2使用makefileMakefile的格式创建第一个makefile实现cleanclean的语法1.3 把make和clean调个位置—— 验证「默认目标」规则1.4 .PHONY ——让目标总是被执行尝试多敲几次make关键点给 myproc 也加上 .PHONY关键点有关ACM时间有关touch改时间2.第二版Makefilegcc 对照表3.第三版Makefile3.1定义变量3.2新的Makefile总代码4.最终版Makefile关键点1.初次实现1.1 没创建之前mkdir lesson9 cd lesson9 vim myproc.c # 写入上面 代码:wq 保存退出进 vim 后写i进插入模式写完ESC再:wq保存退出#includestdio.hintmain(){printf(hello bit!\n);return0;}这时候只要一串gcc -o myproc myproc.c就能让它进行编译然后再来这一行./myproc就能够直接运行可是感觉这样有点麻烦所以我们实现Makefile1.2使用makefileMakefile的格式目标文件:依赖文件列表Tab依赖方法 #前面必须是tab创建第一个makefile创建vimMakefile# 新建并打开 Makefile写入myproc:myproc.c gcc -o myproc myproc.c退出写入之后运行makegcc-omyproc myproc.clsMakefile myproc myproc.c实现clean重新打开 MakefilevimMakefile# 重新打开 Makefile接着往下写写入Makefilemyproc:myproc.c gcc -o myproc myproc.c .PHONY:clean # 修饰符声明 clean 是伪目标 clean: # clean 也要有依赖关系但依赖文件列表可以为空 rm -f myproc # 依赖方法删掉编译产物流程make# 自动执行gcc编译生成myprocgcc-omyproc myproc.cmakeclean# 执行rm删掉myprocrm-fmyproclsMakefile myproc.cclean的语法一般Makefile的格式目标文件:依赖文件列表Tab依赖方法 #前面必须是tab点说明clean的语法结构和myproc一模一样也是一组依赖关系 依赖方法。区别只是它的方法不形成文件而是删文件依赖列表为空clean:后面什么都不写也合法 —— 它不依赖任何文件为什么make clean要带个名字make默认只做第一个目标见块 4clean是第二个得显式点名1.3 把make和clean调个位置—— 验证「默认目标」规则vimMakefile调换后的Makefile.PHONY:clean clean: rm -f myproc myproc:myproc.c gcc -o myproc myproc.c展示makerm-fmyprocmakemyproc gcc-omyproc myproc.c点说明默认目标make从上往下扫描 makefile把第一个目标当默认目标.PHONY这种以点开头的特殊目标会被跳过只做第一个第一个目标做完了第二个不会跟着做除非你显式点名make 目标名结论所以默认把可执行程序写在最前面。1.4 .PHONY ——让目标总是被执行尝试多敲几次make# 先清理干净再连续敲四次 make一次都别落makecleanrm-fmyprocmakegcc-omyproc myproc.cmakemake:myprocis up to date.makemake:myprocis up to date.makemake:myprocis up to date.关键点点说明现象第 1 次真编第 2 ~ 4 次只回一句make: myproc is up to date.up to date什么意思make 认为目标文件已经是最新的没必要重新生成给 myproc 也加上 .PHONY打开Makefile在myproc:那一组的上面加一行修饰符然后make四次vimMakefile .PHONY:myproc# 加这一行修饰下面的目标myproc:myproc.c gcc-omyproc myproc.c .PHONY:clean clean:rm-fmyprocmakegcc-omyproc myproc.cmakegcc-omyproc myproc.cmakegcc-omyproc myproc.cmakegcc-omyproc myproc.c关键点问题答案结论.PHONY 让 make 忽略源文件和可执行目标的M 时间对比从而让目标总是被执行.PHONY是什么makefile 里的一种修饰符被它修饰的目标叫伪目标作用目标总是被执行—— 也就是对应的依赖方法每次都跑本质是什么make 调用gcc时忽略新旧时间对比不给可执行程序加一旦加了就再也享受不到源文件没改就不重编的好处多文件大项目会把时间全浪费在重复编译上给clean加清理每次都应该做彻底后面清理可能做很多事要保证它纯粹、干净不会留下奇奇怪怪的中间产物有关ACM时间缩写全称含义触发场景AAccess 访问时间文件内容被读取的时间cat、vim 打开、程序读文件只看内容不修改MModify 修改时间文件内容数据被改动的时间echo、vim 保存写入文件里面文字变了CChange 状态变更时间文件属性 / 元信息被改动的时间chmod 改权限、chown 改所有者、mv 改名、硬链接增减inode 属性变文件内容不变查看时间状态的指令statmyproc.c# 看源文件的三条时间statmyproc.c# 看源文件的三条时间File:myproc.cSize:359Blocks:8IO Block:4096regularfileDevice: fd01h/64769d Inode:1321125Links:1Access:(0664/-rw-rw-r--)Uid:(1000/ whb)Gid:(1000/ whb)Access:2024-10-2318:51:20.000000000 0800 Modify:2024-10-2318:51:20.000000000 0800 Change:2024-10-2318:51:20.000000000 0800statmyproc# 看可执行文件的三条时间File:myprocSize:8440Blocks:24IO Block:4096regularfileDevice: fd01h/64769d Inode:1321126Links:1Access:(0775/-rwxrwxr-x)Uid:(1000/ whb)Gid:(1000/ whb)Access:2024-10-2319:04:18.051190859 0800 Modify:2024-10-2319:04:18.051190859 0800 Change:2024-10-2319:04:18.051190859 0800有关touch改时间make识别重复的原理通过modify时间touch已存在文件会改时间touch完了之后又能make用法效果touch 不存在的文件新建一个空文件touch 已存在的文件把它的三条时间全部统一更新为现在核心作用change file timestamptouch -a 文件只改access 时间touch -m 文件只改modify 时间touch -c 文件不常用 —— M 时间一改属性一般也跟着改了2.第二版Makefile之前的Makefile是一个简化版的版本myproc:myproc.c gcc -o myproc myproc.c详细版的是这样的myproc: myproc.o # 最终目标依赖目标文件 gcc myproc.o -o myproc # 链接把 .o 变成可执行 myproc.o: myproc.s # .o 依赖汇编文件 gcc -c myproc.s -o myproc.o # 汇编把 .s 变成 .o myproc.s: myproc.i # .s 依赖预处理文件 gcc -S myproc.i -o myproc.s # 编译把 .i 变成 .s myproc.i: myproc.c # .i 依赖源文件 gcc -E myproc.c -o myproc.i # 预处理把 .c 变成 .i .PHONY:clean clean: rm -f *.i *.s *.o myprocgcc对照表阶段命令输入 → 输出干什么预处理gcc -E myproc.c -o myproc.i.c→.i宏替换、去注释、条件编译、头文件展开编译gcc -S myproc.i -o myproc.s.i→.s检查语法翻译成汇编汇编gcc -c myproc.s -o myproc.o.s→.o汇编代码 → 二进制目标文件链接gcc myproc.o -o myproc.o→ 可执行和标准 C 库libc.so.6链接3.第三版Makefile3.1定义变量先vim进文件里然后在前面添加BINproc.exe CCgcc SRCmyproc.c FLAGS-o RMrm -f对应关系写法意思BINproc.exe以后用$(BIN)就替换成proc.exeCCgcc以后用$(CC)就替换成gccSRCmyproc.c以后用$(SRC)就替换成myproc.cFLAGS-o以后用$(FLAGS)就替换成-oRMrm -f以后用$(RM)就替换成rm -fproc.exe:myproc.c ↑ ↑ $ $^目标 依赖文件3.2新的Makefile总代码BINproc.exe # 目标文件名 CCgcc # 编译器 SRCmyproc.c # 源文件 FLAGS-o # 编译选项 RMrm -f # 删除命令 $(BIN):$(SRC) # 换成变量引用proc.exe:myproc.c $(CC) $(FLAGS) $ $^ # gcc -o proc.exe myproc.c echo linking ... $^ to $ # echo linking ... myproc.c to proc.exe .PHONY: clean: $(RM) $(BIN) # rm -f proc.exe echo remove ... $(BIN) # echo remove ... proc.exe .PHONY:test test: echo $(BIN) echo $(CC) echo $(SRC) echo $(FLAGS) echo $(RM)代入举例图中的代码$(BIN):$(SRC) $(CC) $(FLAGS) $ $^相当于proc.exe:myproc.c gcc -o proc.exe myproc.c4.最终版Makefile目标只有一个不管目录里有几个.cmakefile 一行都不用改。两个动作① 让 makefile自动列出当前目录的源文件② 用模式规则%.o:%.c一句话搞定所有.c→ 同名.o。BINproc.exe CCgcc # 自动列出当前目录所有 .c写法二选一一种注释掉 #SRC$(shell ls *.c) SRC$(wildcard *.c) OBJ$(SRC:.c.o) # 把 SRC 里的每个 .c 换成 .o LFLAGS-o # 链接选项 FLAGS-c # 编译选项 RMrm -f $(BIN):$(OBJ) $(CC) $(LFLAGS) $ $^ echo linking ... $^ to $ %.o:%.c # 模式规则所有 .c 展开成同名 .o $(CC) $(FLAGS) $ echo compling ... $ to $ .PHONY:clean clean: $(RM) $(OBJ) $(BIN) .PHONY:test test: echo $(SRC) echo $(OBJ)关键点语法含义老师板书原批注$(wildcard *.c)makefile内置函数默认把当前目录所有.c通配出来。板书批注“显示当前目录下所有的 .c 文件名”$(shell ls *.c)另一种写法makefile 可以执行 shell 命令。扫描到这行就执行ls *.c把结果存进SRC。两种方式自己选OBJ$(SRC:.c.o)替换语法把SRC内部每个文件名.c换成文件名.o。板书批注“SRC 内部的文件名 .c → 文件名 .o”%.o:%.c模式规则。%是通配符板书批注“把当前路径下所有的 .o/.c 依次展开”。目录里有 100 个.c就自动展开成 100 组依赖关系$表示当前正在处理的那一个.c文件一条一条交给 gcc。课件里把$误写成%以老师课上讲的$为准不回显命令实现静默编译和静默清理特殊符号速查含义$目标文件$^所有依赖文件$第一个依赖文件模式规则里就是当前那个.c命令前加它 → 不回显这条命令
返回列表