一、交叉编译Hello程序
注意Ubuntu编译的程序能在ARM开发板上运行,需要在Ubuntu上安装交叉编译工具。因为Ubuntu上X86的内核,而开发板上是ARM的内核。
二、hello程序的引申
三、GCC编译过程
过程:电工——纸带打孔(机器码)——英文助记符(汇编码)——高级语言(c\c++)
一般情况下,我们常说的编译包括:预处理、编译(代码错误是在此阶段发现的)、汇编三部分,有时候又包括:预处理、编译、汇编、链接四部分。
四、GCC常用选项
./ 表示在当前目录
1、gcc - c -o
上面方框是将预处理、编译、汇编都做了,然后链接,下面方框一、二步是只做预处理、编译、汇编,到第三步在做链接。
2、在编译的时候加上- v 他会列出去查找编译时候的步骤,如:gcc -c -o main.o main.c -v
3、头文件<>,表示在工具链里默认的指定的路径中查找头文件;如果想在指定的路径中查找,可以使用-I选项,表示如下
gcc -c -o man.o main.c -v -I ./
4、制作、使用静态库
5、制作 、使用动态库
6、常用的编译方法
-L 的意思是链接的库在哪里;
-lsub 是对动态库libsub.so的缩写
注意:
直接编译-lsub会出现错误,所以需要-L指定链接的库在哪里,然后-l指定库里面的哪个文件。
7、
运行test(其中用到库的.o文件是静态库) 能够运行,但运行test2(其中用到库的.o文件是动态库)会报错。如上面6.常用的编译方法中,虽然在test2中用-L、-l指定了链接的库,但是这不是运行时的库,运行和链接是两个不同的概念,因区别对待。怎么在运行时,将库导入到指定的路径,可以用如下方法:
“导出修改这个环境变量”。这个操作会在原来的库中查找这个库,找不到再到指定的路径中查找这个库。
8、总结
9、不一定需要编译,可以使用如下方法查找头文件、库的路径。
五、Makefile的引入及规则
1、Makefile怎么组织管理的文件
如:gcc -o test a.c b.c
缺点:因为要对每个文件都要处理一次,当文件非常多时,会带来很严重的效率问题吧。
处理方法是:分开编译 如:
gcc -c -o a.o a.c
gcc -c -o b.o b.c
gcc -o test a.o b.o
2、判断哪个文件被修改
根据时间来判断哪个文件被修改,比方说如果a.c的时间比a.o的时间新,那么该文件被修改;a.o、b.o的时间比test新的话,应该重新生成test。
3、Makefile的最基本语法是规则
具体的:
第一次执行make的时候,以上三条命令都会执行;但是当修改a.c的时候,只会执行与a.c相关的两条命令。
4、想深入学习可以参考下面的“参考文档”
六、Makefile的语法
1、通配符
例如:
test:a.o b.o c.o
gcc -o test $^
%.o : %.c
gcc -c -o $@ $
2、假象目标
下面这种直接编辑clean的操作是不正确的,如下面图2所示,当创建一个clean 的文件时,就不会执行“clean”的操作。因为Makefile的规则是:当“目标文件”不存在,或某个依赖文件比目标文件“新",则执行“命令”。而创建了名为clean的文件,且无依赖,所以不会执行“clean”的操作。
办法:将clean定义为假象目标,这样就不会判断名为clean的文件是否存在
3、变量(即时变量、延时变量,export)
简单变量(即时变量):
A := xxx #A的值即可确定,在定义时即确定
B = xxx #B的值使用到时才确定
实验1:
现象:
实验2:
现象:
原因:变量C放在前面还是后面定义,对于变量B本身没有影响,在执行make命令的时候,会把整个Makefile读进去进行分析。
实验3:
现象:
实验4:
现象:
实验5
通过命令行存入变量D
总结:赋值方法如下:
六、Makefile的函数
实验1:
现象:
解释:变量A等于a b c,对于里面的每一个用空格隔开的值,分别执行$(f).o。
实验2:
现象:
实验3:
现象:
实验4:
现象:
实验5:
现象:
解释:从文件files2中,将.c替换成.d。
总结:
七、Makefile实例
1、
因为这里有一个“tab”键,是一个空命令,导致 没办法生成新的c.o,删掉tab就OK了。
2、gcc生成依赖
参考链接:
gcc -M c.c //打印出依赖
gcc -M -MF c.d c.c //把依赖写入文件c.d
gcc -c -o c.o c.c -MD -MF c.d //编译c.o,并把依赖写入c.d
3.更多可以看文件《Makefile实例》:如 CFLAGS等的用法
八、Makefile的使用
源码和参考文件在《05_general_Makefile》中
怎么使用这套Makefile:
1.把顶层Makefile, Makefile.build放入程序的顶层目录,
在各自子目录创建一个空白的Makefile
2.确定编译哪些源文件
修改顶层目录和各自子目录Makefile的obj-y :
obj-y += xxx.o
obj-y += yyy/
这表示要编译当前目录下的xxx.c, 要编译当前目录下的yyy子目录。(注意:不包括“include”里面的头文件)
3. 确定编译选项、链接选项
修改顶层目录Makefile的CFLAGS,这是编译所有.c文件时都要用的编译选项;(用于查找头文件)
修改顶层目录Makefile的LDFLAGS,这是链接最后的应用程序时的链接选项;
修改各自子目录下的Makefile:
"EXTRA_CFLAGS", 它给当前目录下的所有文件(不含其下的子目录)设置额外的编译选项, 可以不设置
现象:
编译:
"CFLAGS_xxx.o", 它给当前目录下的xxx.c设置它自己的编译选项, 可以不设置
现象:
编译:
执行./test,之后的现象
4. 使用哪个编译器?
修改顶层目录Makefile的CROSS_COMPILE, 用来指定工具链的前缀(比如arm-linux-)。(注意:不同的编译器,他的前缀可能不同)
5. 确定应用程序的名字:
修改顶层目录Makefile的TARGET, 这是用来指定编译出来的程序的名字
6. 执行"make"来编译,执行"make clean"来清除,执行"make distclean"来彻底清除
九、通用Makefile的解析
细节参考:视频第四篇《3-7同意Makefile的解析》