1、MakeFile学习,陈 龙,简单介绍Makefile, 简化编译时所需要下达的指令; 若在编译完成之后,修改了某个原始码档案,则 make 仅会针对被修改了的档案进行编译,其它的 object file 不会被更动; 最后可以依照相依性来更新( update )执行档。,编译和链接规则(输入make命令之后将按照以下规则工作),如果这个工程没有编译过,那么我们的所有C文件都要编译并被链接。如果这个工程的某几个C文件被修改,那么我们只编译被修改的C文件,并链接目标程序。如果这个工程的头文件被改变了,那么我们需要编译引用了这几个头文件的C文件,并链接目标程序。,通用的Makefile里包含什么,
2、在一个通用Makefile中通常包含下面内容: 1、需要由make工具创建的目标体(target),通常是目标文件或可执行文件。 2、要创建的目标体所依赖的文件(dependency_file)。 3、创建每个目标体时需要运行的命令(command)。 格式如下:target:dependency_files command目标:依赖文件1,依赖文件2命令 依赖文件后缀 依赖文件1,依赖文件2, 目标注意:命令行必须以单个的TAB字符进行缩进,不能是空格当然也可以跟 目标和依赖文件在一行,不过要以;隔开,完整Makefile里包含什么,显式规则 由Makefile的书写者明显指出,要生成的文件
3、,文件的依赖关系和生成的命令 如: foo.o : foo.c defs.h 依赖关系gcc -o foo.o foo.c 生成目标的方法(方式) 隐晦规则 make有自动推导的功能,这样我们就可以简略地书写Makefile 如: foo.o : foo.c (.o文件自己推导出同名的依赖文件.c.) 变量定义 这里面的变量一般都是字符串,他有点像c语言的宏 如:H: =foo.c gcc -o foo.o $(H) (赋值可以用: =也可以直接用 =) 文件指示 包含3部分,一个是在一个Makefie中引用另一个Makefile,就像c语言的 include一样;另一个是根据某些情况指定Ma
4、kefile中的有效部分,就像C语言 中的预编译#if一样;还有就是定义一个多行的命令。 注释 注释符用“#”如果你要在你的Makefile中使用“#”字符,可以用反斜框进行转义, 如:“#”。,书写一个简单的Makefile(适合所有文件在一个文件夹的情况),cn_work : main.o cn_work.o fun.o gcc main.o cn_work.o fun.o -o cn_work main (命令一定要用以Tab开头)cn_work.o : cn_work.c gcc -c cn_work.c -o cn_workmain.o : main.c cn_work.hgcc -
5、c main.c -o main.ofun.o : fun.c fun.hgcc -c fun.c -o fun.oclean:rm -f cn_work *.o-c参数,只编译,不连接成为可执行文件,编译器只是由输入的.c等源代码文件生成.o为后缀的目标文件,目标:在工作目录下有4个文件夹 分别是 sources(源文件) obj (中间文件)headers(头文件) bin(目标文件) sources里面有 main.c cn_work.c fun.c obj 里面最初没有文件 headers 里面有 fun.h cn_work.h 最终目标取名为 cn_work 它应存放到bin里面 开
6、始写Makefile的预备知识:gcc 的3个参数:1. -o 指定目标文件gcc sources/main.c -o bin/main2. -c 编译的时候只生产目标文件不链接gcc -c sources/main.c -o obj/main.o3. -I 主要指定头文件的搜索路径gcc -I headers -c main.c -o main.o,多目录下Makefile的写法(1),bin/cn_work : obj/main.o obj/cn_work.o obj/fun.o gcc obj/main.o obj/cn_work.o obj/fun.o -o bin/cn_work (
7、命令一定要用以Tab开头) obj/cn_work.o : sources/cn_work.c gcc -I headers -c sources/cn_work.c -o obj/cn_work.o obj/main.o : sources/main.cgcc -I headers -c sources/main.c -o file_o/main.o obj/fun.o : sources/fun.cgcc -I headers -c file_c/fun.c -o file_o/fun.o clean:rm -f bin/cn_work file_o/*.o,多目录下Makefile的写法
8、(2),用隐式规则改进: 3个符号介绍:1. $ 表示要生成的目标2. $ 表示全部的依赖文件3. $ 表示第一个依赖文件 bin/cn_work : obj/main.o obj/cn_work.o obj/fun.o gcc $ -o $ (命令一定要用以Tab开头) obj/cn_work.o : sources/cn_work.c gcc -I headers -c $ -o $ obj/main.o : sources/main.cgcc -I headers -c $ -o $ obj/fun.o : sources/fun.cgcc -I headers -c $ -o $ cl
9、ean:rm -f bin/cn_work file_o/*.o,),变量的引入和应用: CC=gcc HD=-I headers SC=-c $ OBJ=-o $ bin/cn_work : obj/main.o obj/cn_work.o obj/fun.o gcc $ -o $ (命令一定要用以Tab开头) obj/cn_work.o : sources/cn_work.c $(CC) $(HD) $(SC) $(OBJ) obj/main.o : sources/main.c$(CC) $(HD) $(SC) $(OBJ) obj/fun.o : sources/fun.c$(CC)
10、$(HD) $(SC) $(OBJ) clean:rm -f bin/cn_work file_o/*.o,当我们输入make到终端的时候,终端就会依次显示所有的执行过的命令,方便我们查看进度。 gcc -I headers -c sources/cn_work.c -o obj/cn_work.o gcc -I headers -c sources/main.c -o file_o/main.o gcc -I headers -c file_c/fun.c -o file_o/fun.o gcc obj/main.o obj/cn_work.o obj/fun.o -o bin/cn_wor
11、k clean:rm -f bin/cn_work file_o/*.o 用字符的时候,命令将不被显示出来,它和echo结合使用类似于dos下的应用。 在makefile执行时,make 带有参数“-n”或”-just-print”,那么其就只会显示命令,不执行命令。这个功能有利于我们调试Makefile,看看我们书写的命令执行起来是什么样子的或是什么顺序的。,提示信息,Page 12,目标“.PHONY”的所有的依赖被作为伪目标。伪目标时这样一个目标:当使用make命令行指定此目标时,这个目标所在规则定义的命令、无论目标文件是否存在都会被无条件执行。 gcc -I headers -c so
12、urces/cn_work.c -o obj/cn_work.o gcc -I headers -c sources/main.c -o file_o/main.o gcc -I headers -c file_c/fun.c -o file_o/fun.o gcc obj/main.o obj/cn_work.o obj/fun.o -o bin/cn_work+ .PHONY clean: (防止出现文件名为clean 的文件) clean:rm -f bin/cn_work file_o/*.,伪目标,Page 13,ifeq,else,endif ifeq ($(CC),gcc) If
13、eq表示条件语句的开始,并指定一个条件表达式,表达式包含两个参数,以逗号分隔,表达式以圆括号括起。else表示条件表达式为假的情况。endif表示一个条件语句的结束,任何一个表达式都应该以endif结束。 Ifeq的这种关键字有四个,除了ifeq之外,还有ifneq.这两个是相反着用的。 第三个是ifdef,第四个是ifndef.这个是判断ifdef 或ifndef 是否有值。如果有值则为真(另外一个就是没值为真)。 这种条件判断可以有多余的空格,但是不能以Tab键开头,因为容易被当成命令对待。而且#的应用也是安全的。,使用条件判断,Page 14,GCC c 编译成把源文件目标代码,不做连接
14、的动作。 d 在执行过程中打印出所有的调试信息 S 把源文件编译成汇编代码,不做汇编和连接的动作。 E 只把源文件进行预处理之后的结果输出来。不做编译,汇编,连接的动作。 o file 指明输出文件名是file。 g 把调试开关打开,让编译的目标文件有调试信息。 -O1 O2 O3 O0,这些开关分别控制优化的强度,-O3最强。,gcc 参数,Page 15,1、编写C程序源代码*.c2、预处理(PreProcessing) gcc -E hello.c -o hello.i 3、编译(Compiling) gcc -S hello.i -o hello.s 4、汇编(Assembling)生成目标代码*.o gcc -c hello.s -o hello.o 5、链接(Linking)生成可执行文件 gcc hello.o -o hello1 gcc -static hello.o -o hello2 hello1是动态编译,hello2是静态编译,利用file可以看出此文件statically linked(静态链接),还是dynamically linked (动态链接)。,gcc编译流程详解,