Chinaunix首页 | 论坛 | 博客
  • 博客访问: 173218
  • 博文数量: 101
  • 博客积分: 509
  • 博客等级: 下士
  • 技术积分: 680
  • 用 户 组: 普通用户
  • 注册时间: 2009-07-08 21:55
文章分类

全部博文(101)

文章存档

2013年(6)

2012年(79)

2011年(16)

分类:

2011-07-06 22:14:32

原创文章转载请声明转载自http://blog.sina.com.cn/s/blog_60cbc1700100o0sv.html

既然谈及make,那我们先聊聊make的工作过程吧

在默认的方式下,也就是我们只输入 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 了。

       这就是整个 make 的依赖性,make 会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make 就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make 根本不理。make 只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦。

上述文字呢转载自陈皜的文章,下面我将给出一个比较通用的makefile并对此讨论一些问题

CROSS = arm-elf-
CC = $(CROSS)gcc
CFLAGS = -Wall -I./include -elf2flt
LDFLAGS = -lm

PKG = src

SRCS = $(wildcard $(PKG)/inc/*.c) $(wildcard $(PKG)/*.c)
OBJS = $(patsubst %.c,%.o,$(SRCS))

%.o:%.c
$(CC) -c -o $@ $^ $(CFLAGS)

.PHONY:main
main:$(OBJS)
-$(CC) -o $@ $(CFLAGS) $^ $(LDFLAGS) $(LDFLAGS)

.PHONY:all
all:
-make main

.PHONY:install
install:
-cp main ./myfile

clean:
-rm main
-rm $(PKG)/inc/*.o
-rm $(PKG)/*.o
-rm main.gdb

之前呢在网上看到一个程序之后改的,下面做一些讨论
       1、如果使用OBJS = $(SRCS: .c = .o),注意.c的两边至少得有一个空格,至于为什么,如果你知道请你告诉我,因为我觉得太诡异了。
             使用这句后的运行结果是,并不生成中间的.o。很明显,这并没有达到程序员原来的目的,很多教你写makefile的书籍中呢也说其实调用make替换字符串函数patsubst与这个是一样的,只不过是“简化版”罢了,对于这个问题呢,我也不知道为什么,本来想通过看gun make的源码,但是那也得好几兆,比linux-0.11内核还大。所以如果你知道为什么,请告诉我吧。

       2、%.o:%.c
             $(CC) -c -o $@ $^ $(CFLAGS)
             把这两句删除掉,你会发现,你的中间文件依然可以生成。不生成还好,它竟然生成了,这就是我题目的那句话了。世界上最另程序员头疼的也许并不是整版整版的bug,而是没有bug却运行的不得心意!当然这个问题也困惑了我很久,然后偶然的机会,我发现生成的提示中那些奇怪的空格,通过对简单的尝试,发现了问题的所在。
             (下面文字转载自陈皓的《跟我写makefile》)
             在隐含规则中的命令中,基本上都是使用了一些预先设置的变量。你可以在你的makefile 中改变这些变量的值,或是在 make 的命令行中传入这些值,或是在你的环境变量中设置这些值,无论怎么样,只要设置了这些特定的变量,那么其就会对隐含规则起作用。
            当然,你也可以利用 make 的“-R”或“--no–builtin-variables”参数来取消你所定义的
变量对隐含规则的作用。
            例如,第一条隐含规则——编译 C 程序的隐含规则的命令是“$(CC) –c $(CFLAGS)$(CPPFLAGS)”。Make 默认的编译命令是“cc”,如果你把变量“$(CC)”重定义成“gcc”,把变量“$(CFLAGS)”重定义成“-g”,那么,隐含规则中的命令全部会以“gcc –c -g$(CPPFLAGS)”的样子来执行了。我们可以把隐含规则中使用的变量分成两种:一种是命令相关的,如“CC”;一种是参数相的关,如“CFLAGS”。

            那么作为一个程序员,请不要把这两句话让make来帮你做,依赖系统或者工具只会降低它的移植性。而这两句代码,你想放在哪里都可以,哪怕是最开头(我已经试过了)。可是如果是make的话应该默认执行第一条语句或者依赖呀,这里不矛盾么?
           因为,模式规则中"%"的展开发生在变量和函数的展开之后,变量和函数的展开发生在 make 载入 Makefile 时,而模式规则中的"%"则发生在运行时。所以,你还没载入变量和函数,我去哪里给你展开呀。那么似乎,对于make部分的隐式规则有了进一步的了解,其实隐式规则还有很多,我的路任重而道远!
阅读(835) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~