博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
linux驱动学习(二) Makefile高级【转】
阅读量:6159 次
发布时间:2019-06-21

本文共 5596 字,大约阅读时间需要 18 分钟。

转自:

版权声明:本文为博主原创文章,未经博主允许不得转载。在我前一篇写的【 linux驱动学习(一)Makefile基础】中,Makefile写的中规中矩,其实Makefile写法很灵活,可以写得很简洁,而且减少出错的可能,现在就把之前写的Makefile改进一下。[plain] view plain copy    main: main.o hello.o word.o          gcc main.o hello.o word.o -o main            main.o:main.h hello.h word.h      hello.o:hello.h      word.o:word.h            clean:          echo "cleanning project"          -rm main *.o          echo "clean completed"            .PHONY:clean  这是不是比以前简单多了,但是main.o hello.o word.o这三个目标的编译命令都没有,怎么会编译呢,执行make试试看[plain] view plain copy    
make cc -c -o main.o main.c cc -c -o hello.o hello.c cc -c -o word.o word.c gcc main.o hello.o word.o -o main
cc是什么呢,执行下which cc[plain] view plain copy [plain] view plain copy
which cc /usr/bin/cc 事实上cc指向的也是gcc其实,这是Makefile的内建隐含规则,然后make时,调用这些隐含规则。[plain] view plain copy # default OUTPUT_OPTION = -o $@ # default CC = cc # default COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c %.o: %.c # commands to execute (built-in): $(COMPILE.c) $(OUTPUT_OPTION) $< 以上是内建规则中关于隐含规则的部分‘#’为注释符,跟‘//’一样‘CC’为Makefile变量'$@'与‘$<’为特殊变量,'$@'的取值为规则的目标,‘$<’取值为规则的第一个条件。%.o: %.c是一种特殊的规则,称为模式规则(Pattern Rule)。CFLAG CPPFLAG TARGET_ARCH未定义,展开为空,现在来分析一下,隐含规则是怎样解析Makefile的。首先,OUTPUT_OPTION是一个变量,[plain] view plain copy OUTPUT_OPTION = -o $@ 这边变量展开为:“-o main.o”其次,展开COMPILE变量[plain] view plain copy # default COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c 为:“cc -c”。中间有四个空格。然后[plain] view plain copy %.o: %.c 这就相当于 main.o:main.c最后[plain] view plain copy $(COMPILE.c) $(OUTPUT_OPTION) $< 注意开头的空白为tab键,8个字符,这是Makefile规定的,gcc命令等必须tab开头识别展开为:[plain] view plain copy cc -c -o main.o main.c 完整的:[java] view plain copy main.o:main.h hello.h word.h main.o:main.c cc -c -o main.o main.c 这就隐含的包含了各个条件的编译注意:上面之所以可以写成两行,是应为条件并不是一定要写在一行,可以分开写,但只能存在一条命令:比如下列:[plain] view plain copy main.o: main.c main.h hello.h word.h gcc -c main.c 可以写成:[java] view plain copy main.o:main.h hello.h word.h main.o:main.c gcc -c main.c 写规则的目的是让make建立依赖关系图,不管怎么写,只要把所有的依赖关系都描述清楚了就行。****************************Makefile 变量**************************[plain] view plain copy var = $(gho) gho = yu all: @echo $(var) make all时,输出 yu[plain] view plain copy
make all yu 这就是Makefile中的变量,与TCL脚本的变量很类似之所以输出yu 而非 gho,是因为‘=’不用立即展开,若果在第一等号前加‘:’,试试。[plain] view plain copy
var := $(gho)      gho = yu            all:              @echo $(var)
      
      
  这样make all 后输出为空,这是因为var:=$(gho),遇到‘:’将立即展开,gho此时又为定义,因此输出空,若gho=yu放在前面,则依然输出yu还有一个比较有用的赋值运算符是?=,例如var ?= $(gho)的意思是:如果var没有定义过,那么?=相当于=,定义var的值是$(gho),但不立即展开;如果先前已经定义了var,则什么也不做,不会给var重新赋值。+=运算符可以给变量追加值[plain] view plain copy    var = main.o      var += $(gho)      gho = hello.o word.o  这是var的值为 main.o hello.o word.o常用的特殊变量有四个,出去之前用的$@与$<,还有$? 和$^    $@,表示规则中的目标。    $<,表示规则中的第一个条件。    $?,表示规则中所有比目标新的条件,组成一个列表,以空格分隔。    $^,表示规则中的所有条件,组成一个列表,以空格分隔。因此[plain] view plain copy    main: main.o hello.o word.o          gcc main.o hello.o word.o -o main  可以改写为:[plain] view plain copy    main: main.o hello.o word.o          gcc $^ -o $@  这样的好处是,即使以后又往条件里加了新的目标,编译命令也不需要修改,既省事,又减少出错。$?也很有用,有时候希望只对更新过的条件进行操作。之前我们看到make的隐含规则数据库中用到了很多变量,有些变量没有定义(例如CFLAGS),有些变量定义了缺省值(例如CC),我们写Makefile时可以重新定义这些变量的值,也可以在缺省值的基础上追加。以下列举一些常用的变量。AR    静态库打包命令的名字,缺省值是ar。ARFLAGS    静态库打包命令的选项,缺省值是rv。AS    汇编器的名字,缺省值是as。ASFLAGS    汇编器的选项,没有定义。CC    C编译器的名字,缺省值是cc。CFLAGS    C编译器的选项,没有定义。CXX    C++编译器的名字,缺省值是g++。CXXFLAGS    C++编译器的选项,没有定义。CPP    C预处理器的名字,缺省值是$(CC) -E。CPPFLAGS    C预处理器的选项,没有定义。LD    链接器的名字,缺省值是ld。LDFLAGS    链接器的选项,没有定义。TARGET_ARCH    和目标平台相关的命令行选项,没有定义。OUTPUT_OPTION    输出的命令行选项,缺省值是-o $@。LINK.o    把.o文件链接在一起的命令行,缺省值是$(CC) $(LDFLAGS) $(TARGET_ARCH)。LINK.c    把.c文件链接在一起的命令行,缺省值是$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)。LINK.cc    把.cc文件(C++源文件)链接在一起的命令行,缺省值是$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)。COMPILE.c    编译.c文件的命令行,缺省值是$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c。COMPILE.cc    编译.cc文件的命令行,缺省值是$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c。RM    删除命令的名字,缺省值是rm -f。***************************自动处理头文件的依赖关系*************************[plain] view plain copy    all:main      main: main.o hello.o word.o          gcc main.o hello.o word.o -o main            main.o:main.h hello.h word.h      hello.o:hello.h      word.o:word.h            clean:          echo "cleanning project"          -rm main *.o          echo "clean completed"            .PHONY:clean  现在Makefile写成上面的形式,默认make all,这样有个确定,写Makefile时要查个每个源文件,确定其包含的头文件,很容易出错,为了解决这个问题,可用用gcc -M查看源文件的依赖关系,-M选项会把系统头文件也找出来,如果不需要,可以用-MM选项。[plain] view plain copy    
gcc -MM *.c hello.o: hello.c hello.h main.o: main.c main.h hello.h word.h word.o: word.c word.h 现在的问题是怎样将上述依赖包含在Makefile中。GNUlinux建议这样:[plain] view plain copy all:main main: main.o hello.o word.o gcc main.o hello.o word.o -o main sources = main.c hello.c word.c include $(sources:.c=.d) %.d: %.c set -e; rm -f $@; \ $(CC) -MM $(CPPFLAGS) $< > $@. ; \ sed 's,$∗\.o[ :]*,\1.o $@ : ,g' < $@. > $@; \ rm -f $@.

 

【作者】
【出处】
【博客园】
【新浪博客】
【知乎】
【我的作品---旋转倒立摆】
【我的作品---自平衡自动循迹车】
【新浪微博】 张昺华--sky
【twitter】 @sky2030_
【facebook】 张昺华 zhangbinghua
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
你可能感兴趣的文章
初级程序员面试不靠谱指南(六)
查看>>
python OpenGL 安装
查看>>
Asp.NET获取文件及其路径
查看>>
html / css学习笔记-1
查看>>
[学习笔记]标记永久化
查看>>
Android把自己应用加入到系统文件分享中
查看>>
SQL Server安装计划
查看>>
写在山理工之行之后。
查看>>
检查DISPLAY设置时Xlib出现No protocol specified错误
查看>>
如何使用Photoshop制作真实的尺子
查看>>
linux 再多的running也挡不住锁
查看>>
算法笔记--字符串hash
查看>>
strak组件(9):关键字搜索
查看>>
ReactNative 常见红屏黄屏及终端报错
查看>>
[xsy3343]程序锁
查看>>
线性模型(1) —— 多元线性回归
查看>>
PHP函数——urlencode() 函数
查看>>
Net性能分析与调试培训资料
查看>>
VB.NET 开发ColorPicker例子
查看>>
按照指定字符(@split )分割字符串,并取第@index 个
查看>>