Chinaunix首页 | 论坛 | 博客
  • 博客访问: 521012
  • 博文数量: 257
  • 博客积分: 1666
  • 博客等级: 上尉
  • 技术积分: 1535
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-02 23:02
文章分类

全部博文(257)

文章存档

2013年(2)

2012年(255)

分类: Delphi

2012-06-28 09:49:25

1.关于编译和链接。
编译就是生成.o文件,编译只会检查变量和函数是否被声明,如果没有声明就会警告。链接是找寻函数的实现,如果灭有找到就会报错,是将大量的.o文件合成可执行文件。为了链接方便会将大量的.o文件打包,在windows中叫.lib文件,linux下叫.a文件。
 
2.makefile编译规则
target ... : prerequisites ...
command
例子:8个C文件和3个头文件。
edit : main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
cc -o edit main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
main.o : main.c defs.h
cc -c main.c
kbd.o : kbd.c defs.h command.h
cc -c kbd.c
command.o : command.c defs.h command.h
cc -c command.c
display.o : display.c defs.h buffer.h
cc -c display.c
insert.o : insert.c defs.h buffer.h
cc -c insert.c
search.o : search.c defs.h buffer.h
cc -c search.c
files.o : files.c defs.h buffer.h command.h
utils.o : utils.c defs.h
cc -c utils.c
clean :
rm edit main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
(1)prerequisites中如果有一个以上的文件比target文件要新的话,command所定义的命令就会被执行。这就是Makefile的规则。也就是Makefile中最核心的内容。依赖关系的实质上就是说明了目标文件是由哪些文件生成的,换言之,目标文件是哪些文件更新的。make会比较targets文件和prerequisites文件的修改日期,如果prerequisites文件的日期要比targets文件的日期要新,或者target不存在的话,那么,make就会执行后续定义的命令
(2)在例子中clean不是一个文件,其冒号后什么也没有,make就不会自动去找文件的依赖性,也就不会自动执行其后所定义的命令。要执行其后的命令,就要在make命令后明显得指出这个lable的名字。这样的方法非常有用,我们可以在一个makefile中定义不用的编译或是和编译无关的命令,比如程序的打包,程序的备份,等等。
 
3.make是如何工作的
(1)make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
(2)如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“edit”这个文件,并把这个文件作为最终的目标文件。
(3)如果edit文件不存在,或是edit所依赖的后面的 .o 文件的文件修改时间要比edit这个文件新,那么,他就会执行后面所定义的命令来生成edit这个文件。
(4)如果edit所依赖的.o文件也存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件。(这有点像一个堆栈的过程)
(5)当然,你的C文件和H文件是存在的啦,于是make会生成 .o 文件,然后再用 .o 文件生命make的终极任务,也就是执行文件edit了。
 
4.makefile中使用变量
如:在makefile开头加入objects = main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o,这样在makefile中就可以通过$(objects)来引用。
 
5.makefile自动推导
只要make看到一个[.o]文件,它就会自动的把[.c]文件加在依赖关系中,如果make找到一个whatever.o,那么whatever.c,就会是whatever.o的依赖文件。并且 cc -c whatever.c 也会被推导出来
 
6.makefile命令一定要以tab键开头,include <文件名>命令一定不要以tab键开头.
include文件时,make会在当前目录下首先寻找,如果当前目录下没有找到,那么,make还会在下面的几个目录下找:
(1)、如果make执行时,有“-I”或“--include-dir”参数,那么make就会在这个参数
所指定的目录下去寻找。
(2)、如果目录/include(一般是:/usr/local/bin或/usr/include)存在的话,make也会去找。如果有文件没有找到的话,make会生成一条警告信息,但不会马上出现致命错误。它会继续载入其它的文件,一旦完成makefile的读取,make会再重试这些没有找到,或是不能读取的文件,如果还是不行,make才会出现一条致命信息。如果你想让make不理那些无法读取的文件,而继续执行,你可以在include前加一个减号“-”。
如: -include
其表示,无论include过程中出现什么错误,都不要报错继续执行。和其它版本make兼 容的相关命令是sinclude,其作用和这一个是一样的。
 
7.文件搜获
(1)VPATH变量指定搜索路径;
(2)vpath关键字指定特定类型的文件的搜索路径
makefile中支持3种通配符:*”,“?”和“[...]
 
8.伪目标
加.PHONY可声明伪目标。伪目标放在首位,可以作为默认目标,同时把要生成的文件放在伪目标冒号后面,则make时会执行伪目标的规则。
 
9.多目标
bigoutput littleoutput : text.g
generate text.g -$(subst output,,$@) > $@
上述规则等价于:
bigoutput : text.g
generate text.g -big > bigoutput
littleoutput : text.g
generate text.g -little > littleoutput
其中subst标示函数名,output为参数,$标示执行subst函数,@标示依次取出每个目标。
 
10.静态模式
objects = foo.o bar.o
all: $(objects)
$(objects): %.o: %.c
$(CC) -c $(CFLAGS) $< -o $@
注释:$(objects): %.o: %.c中的%.o标示我们的$(objects)都是以.o结尾的,%c标示将$(objects)中所有的.o换成.c结尾作为依赖文件。
 
补充:$(filter %.o,$(files))标示从$(file)中过滤出以.o结尾的所有文件。
 
11.自动生成依赖性
(1)$<:所有的依赖文件;
(2)$@:所有的目标文件;
(3)$(cc) -M可以生成依赖关系
 
12书写命令
(1)命令前加@不会显示命令而是显示命令执行的结果,如@echo;
(2)make -n,make --just-print,只是显示命令不会执行命令;
  make -s 或make --silent全面禁止命令的显示;
(3)命令执行。
如果你要让上一条命令的结果应用在下一条命令时,你应该使用分号分隔这两条命令。比如你的第一条命令是cd命令,你希望第二条命令得在cd之后的基础上运行,那么你就不能把这两条命令写在两行上,而应该把这两条命令写在一行上,用分号分隔。
(4)make如果规则出错一般会终止规则的执行。但是如果在规则前加“-”前缀则无论失败与否都认为成功。给make加上“-i”或是“--ignore-errors”参数,那么,Makefile中所有命令都会忽略错误。而如果一个规则是以“.IGNORE”作为目标的,那么这个规则中的所有命令将会忽略错误。这些是不同级别的防止命令出错的方法,你可以根据你的不同喜欢设置。
(5)嵌套执行MAKEFILE
subsystem:
cd subdir && $(MAKE)
注释:进入subdir然后执行makefile;
上层makefile可以用export variable来传递参数到下级子目录中;
SHELL和MAKEFLAGS是全局环境变量会传递到所有的makefile中;
“-C”,“-f”,“-h”“-o”和“-W”不会传递到下层;
 
13定义命令包
define run-yacc
yacc $(firstword $^)
mv y.tab.c $@
endef
以上定义了命令包,名为run-yacc,注意不要与变量名重名。
foo.c : foo.y
$(run-yacc)
$^就是foo.y,$@就是foo.c
 
14.使用变量
变量的命名字可以包含字符、数字,下划线(可以是数字开头),但不应该含有“:”、“#”、“=”或是空字符(空格、回车等)。变量是大小写敏感的。$<”、“$@是自动化变量。
(1)变量在声明时需要给予初值,而在使用时,需要给在变量名前加上“$”符号,但最好用小括号“()”或是大括号“{}”把变量给包括起来。如果你要使用真实的“$”字符,那么你需要用“$$”来表示。
(2)使用:=来定义变量,这样前面的变量不会使用后面变量的值;
     MAKELEVEL:标示嵌套调用时当前的调用层数;
     空格变量的定义方法:空变量+#注释;
     FOO ?= bar:如果FOO没有定义则定义为bar,否则不受影响;
 (3)变量高级用法
    用法1:foo := a.o b.o c.o
        bar := $(foo:.o=.c)将$foo中所有以.o结尾的换成以.c结尾。则$bar=a.c b.c c.c
       也可以:foo := a.o b.o c.o
             bar := $(foo:%.o=%.c)这依赖于目标模式中有相同的%
    用法2:把变量的值再当成变量
           x = y
           y = z
           a := $($(x))
 (4)追加变量值
objects = main.o foo.o bar.o utils.o
objects += another.o等价于
objects = main.o foo.o bar.o utils.o
objects := $(objects) another.o
(5)override 指示符
如果有变量是通常make的命令行参数设置的,那么Makefile中对这个变量的赋值会被忽略。
override =
override :=
当然,你还可以追加:
override +=
也可以定义多行:
override define foo
bar
endef
(6)多行变量
define two-lines
echo foo
echo $(bar)
endef
注意:命令必须以tab键开头,否则make不会认为是命令;
(7)环境变量
make运行时的系统环境变量可以在make开始运行时被载入到Makefile文件中,但是如果Makefile中已定义了这个变量,或是这个变量由make命令行带入,那么系统的环境变量的值将被覆盖。(如果make指定了“-e”参数,那么,系统环境变量将覆盖Makefile中定义的变量)。
当make嵌套调用时(参见前面的“嵌套调用”章节),上层Makefile中定义的变量会以系统环境变量的方式传递到下层的Makefile中。当然,默认情况下,只有通过命令行设置的变量会被传递。而定义在文件中的变量,如果要向下层Makefile传递,则需要使用exprot关键字来声明
(8)目标变量
prog : CFLAGS = -g
prog : prog.o foo.o bar.o
$(CC) $(CFLAGS) prog.o foo.o bar.o
在这个示例中,不管全局的$(CFLAGS)的值是什么,在prog目标,以及其所引发的所有规则中(prog.o foo.o bar.o的规则),$(CFLAGS)的值都是“-g”
(9)模式变量
%.o : CFLAGS = -O
 
    
 
 


 
 
 
 
 
阅读(1297) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~