【文档说明】C语言gcc强化训练2课件.ppt,共(81)页,595.001 KB,由小橙橙上传
转载请保留链接:https://www.ichengzhen.cn/view-44471.html
以下为本文档部分文字说明:
www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心嵌入式LinuxGCC培训主讲老师:欧阳坚www.embedtrain.orgwww.mobiletrain.org千锋
3G嵌入式移动互联网技术研发中心GCC是什么?•GCC:GNUCompilerCollection;•GCC支持多种硬件平台和操作系统,能编译多种语言(C,C++,Java,Ada95,ObjectiveC,.etc);•GCC与G++的关系:–GCC用于编译多种语言编写的
程序,主要是C;–G++用于编译C++程序,以GCC为基础,编译过程中加入了C++的支持库,参数与GCC基本一致;–可以利用GCC编译C++程序,但是需要在参数中加入引用的C++库,比如libstdc++(如gcc-oout–lstdc++main.cc)。www.embedtrain.orgww
w.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心可执行程序的生成过程–预处理(Preprocessing):分析各种预处理命令,如#define,#include,#if等;–编译(Co
mpilation):根据输入文件产生汇编语言的程序;–汇编(Assembly):将汇编语言输入,产生扩展名为.o的目标文件;–链接(Linking):以.o目标文件,库文件作为输入,生成可执行文件;源程序文件(.h,.c
,.cc,.etc)经预处理的文件(.i,.ii)汇编语言文件(.s)目标文件(.o)可执行程序(.out)www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心GCC支持的文件类型•C文件.–
cC源代码–.hC头文件•C++文件–file.hh,file.hC++头文件–file.C,file.cc,file.cxx等C++源文件•预处理后的文件–file.i预处理后的C源文件–file.ii预处
理后的C++源文件•编译后的文件–.o目标代码(obj)–.s汇编代码文件–file.a目标文件库www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心GCC编译选项命令行:gccoptionsinfile…•-E不生成文件,只输出预
处理结果(输出终端)•-S只预处理和编译,把文件编译成为汇编代码greet.s•-c预处理,编译和汇编,生成.o的obj文件(greet.o)•-ofile输出名为file的可执行文件名(缺省为a.out)•-O-O2优化编译•-g:产生可用于调试的输出•-Wall提示更多警告信息•-Wstric
t-prototypes如果函数的声明或定义没有指出参数类型,编译器就发出警告.•-Wl,option将option作为选项传递给linker,option逗号分割,如:-Wl,-soname,libmymath.so.1ww
w.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心与库和路径相关选项•-Idir在dir这个目录寻找被include的文件•-Ldir在dir这个目录寻找被-l的库•-lname链接库文件名为libname.a或libn
ame.so的库•-fpic或-fPIC产生位置无关的目标代码,以构造共享库(sharedlibrary)•-static禁止与共享库链接,若没有,则优先选择共享库链接•-shared产生共享库,在创建共享函数库时使用www.embedtrain
.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心示例www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心与宏相关的选项•-Dmacro:相当于在源程序中使用•#definemacro1•
-Dmacro=value•-Umacro:取消宏的定义www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式
移动互联网技术研发中心3.GCC编译过程www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心3.1GCC编译过程典型的编译过程test.c–预处理test.i–编译test.s–汇编test.
o–连接test$cattest.c(查看程序源代码)#include<stdio.h>intmain(intargc,char*argv[]){printf("helloworld\n");retur
n0;}$gcc–otesttest.c(编译连接程序)$./test(执行test程序)www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心3.2预处理预编译命
令:$gcc-otest.i-Etest.c或者$cpp-otest.itest.c这里cpp不是值cplusplus,而是theCPreprocessor)执行结果:生成预处理后的文件test.i,该文件包含了test.c
需要的所有的类型和函数申明。原理:读取c源程序,对伪指令和特殊符号进行处理。包括宏,条件编译,包含的头文件,以及一些特殊符号。基本上是一个替换的过程。www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心Hel
lo.c#include<stdio.h>intmain(void){printf(“hello\n”);}预处理命令gcc–Ehello.cgcc–Ehello.c–ohello.i注释这一行看看预处理的结果注意#include的作用和用途-E表示做预处理-o表示预处理的输出存
于hello.i文件中,而不是屏幕上www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心#define用法#include<stdio.h>#defineAA100intm
ain(void){AABBprintf(“hello\n”);}预处理命令gcc–Ehello.c–DBB=hellogcc–Ehello.c–DBB=“printf(\”hello\”);”gcc–Ehello.c–DBB(等效于-DBB=1
)注释这一行看看预处理的结果-D表示在命令行中传入宏定义-DBB=后面是一个宏的定义,可以加双引号。www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心#define带参数#include<stdio.h>#defineAA(a
,b)a=bintmain(void){AA(inta,1);BB;printf(“hello\n”);}预处理命令gcc–Ehello.c–DBB=hellogcc–Ehello.c–DBB=“printf(\”hello\”);”注释这一行看看预处理的结果-D
表示在命令行中传入宏定义-DBB=后面是一个宏的定义,可以加双引号。展开就成了:inta=1;AA宏带两个参数www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心•#ifdef#ifdefined#if!defined•#i
fndef•#elifdefined#elif!defined•#else•#if•#elif•#endif•-E–D”AA=100”www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心#define带参数
#include<stdio.h>#ifdefAAaa#elifdefinedBBbb#elifdefinedCCcc#elseother#endifintmain(void){printf(“hello\n”);}#ifdefAA等效于#ifdefinedAA表
示当定义了宏AA表示除此之外的情况表示否则定义了宏CC的情况www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心gcc–Ehello.c–DAA=1aaintmain(void){
printf(“hello\n”);}www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心gcc–Ehello.c–DBB=1bbintmain(void){printf(“hello\n”)
;}www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心gcc–Ehello.c–DCC=1ccintmain(void){printf(“hello\n”);}www.embedtrain.or
gwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心gcc–Ehello.cotherintmain(void){printf(“hello\n”);}www.embedtrain.orgww
w.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心#if使用www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心#define带参数#include<stdio.h>#ifAAaa#
elifBBbb#elifCCcc#elseother#endifintmain(void){printf(“hello\n”);}#ifAA表示AA非零的情况也就是AA除了0其它数字都为真表示除此之外的情况#elifBB表示BB非零的情况#elif表示否则如果www.
embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心gcc–Ehello.c–DAA=1aaintmain(void){printf(“hello\n”);}gcc–Ehello.c–DAA=0
otherintmain(void){printf(“hello\n”);}www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心gcc–Ehello.c–DBB=1bbintmain(void)
{printf(“hello\n”);}gcc–Ehello.c–DBB=0otherintmain(void){printf(“hello\n”);}www.embedtrain.orgwww.mobiletrain.org千
锋3G嵌入式移动互联网技术研发中心gcc–Ehello.c–DCC=1ccintmain(void){printf(“hello\n”);}gcc–Ehello.c–DCC=0otherintmain
(void){printf(“hello\n”);}www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心gcc–Ehello.cotherintmain(void){printf(“hello\n”);}
www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心#的用法•在函数式宏定义中,•#运算符用于创建字符串,#运算符后面应该跟一个形参(中间可以有空格或Tab),例如:•#defineSTR(s)#s•char*p=STR(helloworl
d)•结果变成:char*p=“helloworld”www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心##的用法•在宏定义中可以用##运算符把前后两个预处理Token连接成一个预处理Token,
和#运算符不同,##运算符不仅限于函数式宏定义,变量式宏定义也可以用。例如:•#defineFOO(a)foo##a•inta=FOO(bar);•intb=FOO();•预处理之后变成:•inta=foobar;•intb=foo;www.embedtrain.orgww
w.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心预处理头文件xxx.h•#ifndefHEADER_FILENAME•#defineHEADER_FILENAME•/*bodyofheader*/•
#endif•当xxx.h被多次包含的时候。www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心有三个头文件和一个C文件•common.hfile2.hfile3.h•main.cwww.embedtrain.orgwww.mo
biletrain.org千锋3G嵌入式移动互联网技术研发中心common.h#ifndef__COMMON_H__#define__COMMON_H__1staticinttest(void){printf(“hello\n”);}#endif如果没有写上红色部
分的,是什么情况。www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心file1.h•file1.h文件内容如下•#include“common.h”•file2.h文件内容如下•#include“commo
n.h”www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心main.c•main.c内容如下•//#include<stdio.h>•#include“file1.h”•#include“file2.h”•intmain(vo
id){•test();•}www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心•gcc–Emain.c•gcc–omainmain.c•./main•#…•#..www.embedtrain
.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心•#include<stdio.h>•#include<string.h>•#include“common.h”•#include“file1.h”www.embedtrain.org
www.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心3.3编译及优化编译命令:$gcc-otest.s-St
est.i(-S编译选项)$gcc-otest.s-Stest.i(-S编译选项)$cc1-otest.stest.i(cc1为C语言真正编译器)结果:生成汇编文件test.s,test.s中包含了AT&T的x86汇编代码。作用:通过词法和语法分析,确认
所有指令符合语法规则(否则报编译错),之后翻译成对应的中间码,在linux中被称为RTL(RegisterTransferLanguage),通常是平台无关的,这个过程也被称为编译前端。编译后端对RTL树进行裁减
,优化,得到在目标机上可执行的汇编代码。gcc采用as作为其汇编器,所以汇编码是AT&T格式的,而不是Intel格式,所以在用gcc编译嵌入式汇编时,也要采用AT&T格式。www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中
心3.4汇编汇编命令:$gcc-otest.o-ctest.s$as-otest.otest.s执行结果:生成目标机器指令文件test.o(可以通过objdump查看汇编指令)原理:把汇编语言代码翻译成目标机器
指令,用filetest.o可以看到test.o是一个relocatable的ELF文件,通常包含.text.rodata代码段和数据段。可用readelf-rtest.o查看需要relocation的部分。www.embedtrain.org
www.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心3.5链接执行命令:$gcc-otesttest.o执行结果:生成可执行文件test(可用objdump查看)原理:将在一个文
件中引用的符号同在另外一个文件中该符号的定义链接起来,使得所有的这些目标文件链接成为一个能被操作系统加载到内存的执行体。(如果有不到的符号定义,或者重复定义等,会报链接错)。用filetest可以看到test是一个executab
le的ELF文件。www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心3.6执行执行过程$./testwww.embedtrain.orgwww.mob
iletrain.org千锋3G嵌入式移动互联网技术研发中心GCC常用编译选项www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心预编译选项•-DMACRO定义“MACRO”宏为字符串“1”•-DMACRO=DE
F定义“MACRO”宏为字符串“DEF”•-UMACRO取消对“MACRO”宏的定义•-E只运行C预编译器cppwww.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联
网技术研发中心编译选项•-c只编译并生成object文件•-S只预处理和编译,把文件编译成为汇编代码greet.s•-g生成可被gdb使用的标准调试信息•-ggdb生成只被gdb使用的扩展调试信息•-mXXX针对“XXX”CPU进行优化,如“XXX”可
以是486、586等•-oFILE生成指定的输出文件名“FILE”•-O0不进行代码优化•-O或-O1进行一般的代码优化,减少执行代码大小和执行的时间•-O2比-O1进行更多的代码优化,一般在内核编译中
会使用•-O3比-O2更进一步优化•-w不生成任何警告信息•-Wall生成所有级别的警告信息•-Werror把所有的警告当成错误,并中止编译过程www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入
式移动互联网技术研发中心搜索目录(头文件和库文件)•-IDIRECTORY除缺省情况外,指定其它头文件搜索路径“DIRECTORY”•-LDIRECTORY除缺省情况外,指定其它函数库搜索路径“DIRECTORY”•-lLIBRARY
确定链接时需要的其它函数库“LIBRARY”www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心•-shared生成支持动态共享库的执行文件•-static不支持动态共享库,把函数库中内容静态链接到执行文件中•-MM输出
源文件的依赖关系•-fPIC产生位置无关代码(英文缩写为PIC),一般创建共享库时需要www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心www.embedtrain.orgwww.mo
biletrain.org千锋3G嵌入式移动互联网技术研发中心静态库与动态库•创建函数库–分类:•静态库:在编译过程中将库函数代码直接加入到生成的可执行程序中,程序运行过程中不需要利用库函数。•共享库:编译时,只是在生成的可执行程序中简单指
定需要使用的库函数信息,程序运行过程中需要利用库函数。•动态库:共享库的一种变化形式,目前大都采用共享库的方式。–命名:•静态库:前缀lib+库名+.a(libm.a,libstdc++.a等)•共享库:前缀lib+库名+
.so+版本号(libm.so.6,libc.so.6)www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心创建静态库–静态函数库是一组目标文件(*.o)的集合–创建步骤:gcc-ctest1.ctest2.c(生成test1.o,tes
t2.o)ar-crlibtest.atest1.otest2.o(生成函数库libtest.a)–ar函数说明:用途:创建和修改库函数,或从库函数提取目标文件举例:ar-rslib-namelist-o
f-files(将列表中的目标文件加入到库中,并产生索引文件)ar-dslib-namelist-of-files(将列表中列出的目标文件从库中删除,并产生索引文件)ar-xlib-namelist-of-files(不修改库文件,从库中提取列
表中列出的目标文件)www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心创建静态库示例--源码创建静态库的方法:arcaculation.c#include<stdio.h>intmain(void){in
tx=5;inty=3;printf("x+y=%3d\n",add(x,y));printf("x-y=%3d\n",minus(x,y));printf("x*y=%3d\n",multiply(x,y));pri
ntf("x%y=%3d\n",mod(x,y));return1;}add_minus.cintadd(intx,inty){intresult;result=x+y;returnresult;}intminus(intx,inty){intresult;result=x-y
;returnresult;}multiply_mod.cintmultiply(intx,inty){intresult;result=x*y;returnresult;}intmod(intx,inty){intresult;resu
lt=x%y;returnresult;}www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心创建静态库示例--操作命令www.embedtrain.
orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心一个容易忽略的顺序问题静态库不能先于原程序链接,这是因为开始时还没有任何未定义的符号,库中的内容不会被链入,所以应该注意将静态库的使用(-l选项)都写在最后。www.embedtrain
.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心创建、使用共享库示例[vick@nec]$gcc-fPIC-cadd_minus.c[vick@nec]$gcc-fpic-cmultiply_mod.c[vick@ne
c]$gcc-shared-fpic-olibalg.soadd_minus.omultiply_mod.o[vick@nec]$gcc-ocacul-lalgcaculation.c/usr/bin/ld:cannotfind-lalgco
llect2:ldreturned1exitstatus[vick@nec]$gcc-ocacul-L.-lalgcaculation.c[vick@nec]$./cacul./cacul:errorwhileloadingsharedlibraries:libalg.so:cann
otopensharedobjectfile:Nosuchfileordirectorywww.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心创建共
享库步骤•创建共享库gcc-c-fPICtest1.cgcc-c-fPICtest2.cgcc-shared-fPIC-olibtest.sotest1.otest2.o•编译使用了共享库的程序gcc-oma
in–Ldir-ltestmain.cwww.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心共享库系统自动动态加载问题•1.拷贝动态库文件到/lib或/usr/lib去$cplibalg.so/usr/libor$cplibalg.so/li
b•2.改变环境变量LD_LIBRARY_PATH$LD_LIBRARY_PATH=$PWD$exportLD_LIBRARY_PATHwww.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心应用程序自身完成动态加载可
以在自己的程序中使用dlopen()。该函数将打开一个新库,并把它装入内存。dlopen()在dlfcn.h中定义,并在dl库中实现。www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心检查库依赖关系•函数库之间的相互引用•ldd的使用:
用于查看库函数之间的依赖性[vick@necgcc-lab]$cd/usr/lib[vick@neclib]$lddlibtiff.solibjpeg.so.62=>/usr/lib/libjpeg.so.62(0x4004c000)li
bz.so.1=>/usr/lib/libz.so.1(0x4006b000)libc.so.6=>/lib/i686/libc.so.6(0x40079000)/lib/ld-linux.so.2=>/lib/ld-linux.so.2(0
x80000000)www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心应用程序自身完成动态加载示例#include<stdio.h>#includ
e<dlfcn.h>intmain(void){intx=5;inty=3;void*handle;int(*dl_add)(int,int);int(*dl_mod)(int,int);handle=dlopen("/usr/li
b/libalg.so",RTLD_LAZY);dl_add=dlsym(handle,"add");dl_mod=dlsym(handle,"mod");printf("x+y=%3d\n",dl_add(x,y));printf("x%y=%
3d\n",dl_mod(x,y));dlclose(handle);return1;}www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心总
结:动态共享库的好处•1.动态共享库是共享的,节省了物理开销。•2.库版本更新容易,运行时调用,库更新后不用重新链接。•3.允许用户在运行时再确定调用哪个库。使得在程序中添加或者删除一个模块时,都不需要在编译时指定库。✍注意,如果动态共享库无法加载,可能是路径的问题,或是依赖的问题。www.
embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心aroption•optionc–
Createafile•optiond–Deleteafilefromthearchive•optionp–Printalistoffilesinthearchive•optionq–Appendfilestothearchive•optio
nr–Insertnewfilesinthearchivebyreplacingifafilealreadyexistsinthearchive•optiont–Displayingcontentsofanarchive•optionx–Extractingfilesfroma
narchivewww.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心ranlibUtilityThe“ranlib”commandisusedtocreateindexentriesinsidea
narchivefile.示例:$ranlibstatic-lib-name等价于$ar–sstatic-lib-namewww.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心nmUtility
usedtolistsymbolsusedinanobjectfile.示例:$nm-slibcommon.a$nm-sa.out另外:–aoptionwiththenmcommandalsoshowsthedebugsymbols.www.embedtrain.orgww
w.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心objdumpUtility•-f–DisplayingHeaderInformation•-h–DisplayingSectionHeaders•-d–DisassemblingaFil
e•-a–DisplayingInformationaboutLibraryFileswww.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心sizeUtilityThesizeutilitydisplayssizesofe
achsectioninanobjectfile.示例:[root@boota]#sizea.outtextdatabssdechexfilename10152322412714f7a.outwww.embedtrain.orgw
ww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心stringsUtilityThestringsutilitydisplaysprintablestringsinanobjectfi
le.Bydefaultitdisplaysstringsonlyininitializedandloadedsectionsoftheobjectfile.www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技
术研发中心lddUtilityThelddutilityisveryusefulinfindingoutthedependenciesofanexecutableonsharedlibraries.示例:[root@boota]#ldda.outlibc.so.6=>/lib/i
686/libc.so.6(0x4002c000)/lib/ld-linux.so.2=>/lib/ld-linux.so.2(0x40000000)[root@boota]#www.embedtrain.orgwww.mobiletrain.org
千锋3G嵌入式移动互联网技术研发中心www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心make和Makefile的关系•make和Makefile的关系就像演员和剧本的关系•make是系统的一个程序
(/usr/bin/make)•Makefile是规则的文件•make就是去解析Makefile的文件来执行相关的命令•Makefile有三种命名形式:•Makefile,makefile,GNUMakefileww
w.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心3.7一个简单的Makefile格式all:hello@echo“Begintobuildhello“hello:echo“Displayhe
llo”clean:xxxxrm-rf*.ohello注意@符号的用途,@表示后面的命令不要显示出来第一个target第二个target第三个target红色的xxxx表示键盘上的Tab键,而不是空白,任何命令必须以Tab键开始。www.embe
dtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心•make(在上述Makefile中,make和makeall操作一样,因为all是第一个target)•makea
ll•makehello•makecleanwww.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心3.7一个简单的Makefile格式myname=Saifall
:helloecho“mynameis:$(myname)”echo“Begintobuildhello“hello:echo“Displayhello”clean:rm-rf*.ohello变量myname使用$()表示www.embedtrain.or
gwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心一个简单的C程序(hello.c和foo1.c)#include<stdio.h>/*hello.c*/externintfoo1(void);intmain(void){foo1();}#include
<stdio.h>/*foo1.c*/intfoo1(void){printf(“printfoo1\n”);}www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心3.7通常的Makefile格式all:hello@echo"Fin
ishtobuildhello“hello:hello.ofoo1.ogcc-ohellohello.ofoo1.ohello.o:hello.cgcc-c-ohellohello.cfoo1.o:foo1.cgcc-c-ofoo1.
ofoo1.cclean:rm-rf*.ohellowww.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心使用shell脚本来表示脚本1build.sh#!/bin/shgcc
-c-ohellohello.cgcc-c-ofoo1.ofoo1.cgcc-ohellohello.ofoo1.o@echo"Finishtobuildhello“脚本2clean.sh#!/bin/shrm-rf*.ohellowww.embedtrain.orgww
w.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心为什么需要Makefile?•假设一个工程中有一个hello.c文件,有foo1.c,foo2.c…foo9999.c一万个文件,每一个文件编译的时间是10秒。•那么编译所有的文件的时间是:•1
0000*10s=27.78小时•如果使用脚本来编译www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心3.7Makefile格式all:hello@echo"Finishtobuildhello“hello:h
ello.ofoo.ogcc-o$@$^hello.o:hello.cgcc-c-o$@$<foo.o:foo.cgcc-c-o$@$<clean:rm-rf*.ohellowww.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联
网技术研发中心3.7Makefile格式all:hello@echo"Finishtobuildhello“hello:hello.ofoo.ogcc-o$@$^hello.o:hello.cgcc-c-o$@$<foo.o:foo.cgcc-c-o$@$<clean:rm-rf*
.ohellowww.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心3.8Makefile规则•Makefile的规则•target...:prerequisites...•command•.
..•...•target也就是一个目标文件,可以是ObjectFile,也可以是执行文件。还可以是一个标签(Label),对于标签这种特性,在后续的“伪目标”章节中会有叙述。•prerequisites就
是,要生成那个target所需要的文件或是目标。•command也就是make需要执行的命令。(任意的Shell命令)•这是一个文件的依赖关系,也就是说,target这一个或多个的目标文件依赖于prerequisite
s中的文件,其生成规则定义在command中。说白一点就是说,prerequisites中如果有一个以上的文件比target文件要新的话,command所定义的命令就会被执行。这就是Makefile的规则。也就是
Makefile中最核心的内容。www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心3.9自动化变量而命令中的“$<表示依赖目标中的第一个目标名字$@表示目标集$^所有
的依赖目标的集合。以空格分隔。如果在依赖目标中有多个重复的,那个这个变量会去除重复的依赖目标,只保留一份。www.embedtrain.orgwww.mobiletrain.org千锋3G嵌入式移动互联网技术研发中心Than
kyou