从头开始编写项目Makefile(八):型号规则
【版权声明:转载请保留源:blog.csdn.net/gentleliu。Mail:shallnew at 163 dot com】
上创建的文件夹谈及。没有生产目标文件到相应的文件夹,在这里,我们给与相应的文件夹中的目标文件。的目标文件会直接生成到相应文件夹。我们先给库文件目标和可运行文件目标加上路径。例如以下:
lib : $(OBJDIR) $(LIBDIR)/$(SRC_LIB) bin : $(OBJDIR) $(BINDIR)/$(SRC_BIN) $(OBJDIR) :
>---@echo " MKDIR $(notdir $@)..."
>---@mkdir -p $@ ifneq ($(SRC_BIN),)
$(BINDIR)/$(SRC_BIN) : $(SRC_OBJ)
>---$(CC) -o $@ $^ $(LDFLAGS)
endif ifneq ($(SRC_LIB),)
$(LIBDIR)/$(SRC_LIB) : $(SRC_OBJ)
>---$(AR) rcs $@ $^
>---cp $@ $(SRC_BASE)/libs
endif
此时再运行make,完毕后查看build文件夹树:
build/
└── unix_dbg
├── bin
│ └── target_bin
├── lib
│ ├── libipc.a
│ └── libtools.a
└── obj
├── ipc
├── main
└── tools
能够看到,生成的目标是在相应文件夹下。
我们乘胜追击,把.o文件也将其改动了。我们之前的每一个模块Makefile大致是这样写的:
SRC_BASE = ../.. CFLAGS +=
CPPFLAGS += -I. -I./inc -I$(SRC_BASE)/include # SRC_OBJ = $(patsubst %.c, %.o, $(wildcard *.c))
SRC_FILES = $(wildcard src/*.c)
SRC_OBJ = $(SRC_FILES:.c=.o)
SRC_LIB = xx.a include $(SRC_BASE)/Makefile.rule
当中SRC_OBJ在此处给出,然后再在Makefile.rule中使用,此处的.o文件会在.c文件同样文件夹下生成。所以我们如今须要将.o文件加上路径。因为取得路径是在Makefile.rule里面,所以我们能够统一在Makefile.rule里面给变量SRC_OBJ赋值。大致例如以下:
SRC_OBJ = $(patsubst %.c, $(OBJDIR)/%.o, $(notdir $(SRC_FILES)))
这里用到函数patsubst、notdir,关于函数会在后面讲到。这样.o文件作为目标生成之后就会生成到对应文件夹里面了。
此时再编译:
# make
make[1]: Entering directory `/home/Myprojects/example_make/version-2.9/src/ipc'
make[1]: *** No rule to make target `../../build/unix_dbg/obj/ipc/ipc.o', needed by `../../build/unix_dbg/lib/libipc.a'. Stop.
make[1]: Leaving directory `/home/Myprojects/example_make/version-2.9/src/ipc'
make: *** [ipc] Error 2
#
发现出错了。而且是在生成目标文件ipc.o时没有成功,查看build文件夹树也没有生成.o文件。为什么会生成失败呢?
我们没有给出生成.o目标的规则,之前能够生成是由于make有通过隐含规则来自己主动推导的能力(这个之前有讲到,链接过去)。在我们没有改动之前,生成.o通过隐含规则来完毕:
%.o: %.c
# commands to execute (built-in):
>---$(COMPILE.c) $(OUTPUT_OPTION) $<
由于全部的.o目标符合该规则,所以会自己主动推导生成.o文件。我们如今在..o前面加上路径后没有符合生成.o的隐含模式规则了,所以就没有生成该文件,导致编译出错。那怎么办呢?没有隐含模式规则,我们能够自己写符合生成该目标的模式规则。
模式规则类似于普通规则。仅仅是在模式规则中。目标文件是一个带有模式字符“%”的文件,使用模式来匹配目标文件。在目标文件名称中“%”匹配的部分称为“茎”。使用模式规则时,目标文件匹配之后得到“茎”,依赖依据“茎”产生相应的依赖文件,这个依赖文件必须是存在的或者可被创建的。
所以。我们添加一条模式规则例如以下:
$(OBJDIR)/%.o : %.c
>---$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
该模式规则中目标文件是$(OBJDIR)/%.o。那么如今有了符合生成我们须要的.o文件的规则了,编译一下:
# make
make[1]: Entering directory `/home/Myprojects/example_make/version-2.9/src/ipc'
make[1]: *** No rule to make target `../../build/unix_dbg/obj/ipc/ipc.o', needed by `../../build/unix_dbg/lib/libipc.a'. Stop.
make[1]: Leaving directory `/home/Myprojects/example_make/version-2.9/src/ipc'
make: *** [ipc] Error 2
#
发现还是不正确,不是已经添加了模式规则了吗。为何还是没有生成.o文件。
我们这里先说说静态模式规则:
一个规则中能够有多个目标,规则所定义的命令对全部的目标有效。一个具有多目标的规则相当于多个规则。 规则的命令对不同的目标的运行效果不同, 由于在规则的命令中可能使用了自己主动化变量 “$@” 。
多目标规则意味着全部的目标具有同样的依赖文件。
多目标通经常使用在下面两种情况:尽管在多目标的规则中, 能够依据不同的目标使用不同的命令 (在命令行中使用自己主动化变量 “$@” )。可是, 多目标的规则并不能做到依据目标文件自己主动改变依赖文件 (像上边样例中使用自己主动化变量“$@”改变规则的命令一样) 。
须要实现这个目的是,要用到make的静态模式。
静态模式规则是这样一个规则:规则存在多个目标。 而且不同的目标能够依据目标文件的名字来自己主动构造出依赖文件。静态模式规则比多目标规则更通用。 它不须要多个目标具有同样的依赖。
可是静态模式规则中的依赖文件必须是相类似的而不是全然同样
的。
静态模式规则语法例如以下:
<targets ...>: <target-pattern>: <prereq-patterns ...>
<commands>
....
比方以下是一个静态模式规则:
objects = foo.o bar.o all: $(objects) $(objects): %.o: %.c
$(CC) -c $(CFLAGS) $< -o $@
该规则描写叙述了全部的.o文件的依赖文件为相应的.c文件,对于目标“foo.o” ,取其茎“foo”替代相应的依赖模式“%.c”中的模式字符“%”之后可得到目标的依赖文件“foo.c”。
这就是目标“foo.o”的依赖关系“foo.o: foo.c”。规则的命令行描写叙述了怎样完毕由“foo.c”编译生成目标“foo.o” 。
命令行中“$<”和“$@”是自己主动化变量,“$<” 表示规则中的第一个依赖文件, “$@” 表示规则中的目标文件。上边的这个规则描写叙述了下面两个详细的规则:
foo.o : foo.c
>---$(CC) -c $(CFLAGS) foo.c -o foo.o
bar.o : bar.c
>---$(CC) -c $(CFLAGS) bar.c -o bar.o
(注:该演示样例与其相关描写叙述摘抄于互联网,描写叙述非常不错,预计比我讲的具体)
那静态模式规则和普通的模式规则(非静态模式规则)有什么去差别呢?两者都是用目标模式和依赖模式来构建目标的规则中的文件依赖关系,两者不同的地方是 make 在运行时使用它们的时机。
静态模式规则仅仅能用在规则中明白指出的那些文件的重建过程中。不能用在除此之外的不论什么文件的重建过程中。而且它对指定的每个目标来说是唯一的。
假设一个目标存在于两个规则,而且这两个规则都定义了命令, make 运行时就会提示错误。
非静态模式规则可被用在不论什么和它相匹配的目标上。当一个目标文件同一时候符合多个目标模式时,make将会把第一个目标匹配的模式规则作为重建它的规则。
那有没有想过假设我们指定了模式规则后,那还有隐含规则呢。那怎么选择运行哪一个模式规则呢?Makefile中明白指定的模式规则会覆盖隐含模式规则。就是说假设在Makefile中出现了一个对目标文件合适可用的模式规则,那么make就不会再为这个目标文件寻找其他隐含规则,而直接使用在Makefile中出现的这个规则。在使用时。明白规则永远优先于隐含规则。
我们继续说之前的那个问题。我们定义了模式规则后还是没有生成.o文件,我们如今将其改为静态规则再试试就看,例如以下:
$(SRC_OBJ) : $(OBJDIR)/%.o : %.c
>---$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
运行后:
# make
make[1]: Entering directory `/home/Myprojects/example_make/version-2.9/src/ipc'
make[1]: *** No rule to make target `ipc.c', needed by `../../build/unix_dbg/obj/ipc/ipc.o'. Stop.
make[1]: Leaving directory `/home/Myprojects/example_make/version-2.9/src/ipc'
make: *** [ipc] Error 2
#
发现提示没有文件ipc.c。这说明没有生成.o的原因是没有.c文件,我非常好奇的是为何使用非静态模式为何不提示呢?(还没搞懂,再研究研究,知道的能够给个提示哈~~)
缺少依赖文件。为何没有*.c文件,细致想想我们的.o文件没有和.c文件在同一文件夹。在我们project中,将源码和二进制文件(.o 文件和可运行文件)安排在不同的文件夹来进行区分管理。这样的情况下,我们能够使用 make 提供的文件夹搜索依赖文件功能。该功能在下一节讲述,这一节说的够多了,有点累了。可惜终于还是没有给出一个可用的Makefile,在下一节将得到。
版权声明:本文博主原创文章。博客,未经同意不得转载。假设你认为你的实际物品,请点击以下“最佳”。
从头开始编写项目Makefile(八):型号规则的更多相关文章
- 从头开始写项目Makefile(十):make内嵌函数及make命令显示【转】
转自:http://blog.csdn.net/shallnet/article/details/38314473#comments 版权声明:本文为博主原创文章,未经博主允许不得转载.如果您觉得文章 ...
- 从头开始编写一个Orchard网上商店模块(3) - 创建Orchard.Webshop模块项目
原文地址:http://skywalkersoftwaredevelopment.net/blog/writing-an-orchard-webshop-module-from-scratch-par ...
- 从头开始编写一个Orchard网上商店模块(6) - 创建购物车服务和控制器
原文地址: http://skywalkersoftwaredevelopment.net/blog/writing-an-orchard-webshop-module-from-scratch-pa ...
- 从头开始编写一个Orchard网上商店模块(5) - 创建和渲染ProductCatalog的内容类型
原文地址: http://skywalkersoftwaredevelopment.net/blog/writing-an-orchard-webshop-module-from-scratch-pa ...
- 从头开始编写一个Orchard网上商店模块(4) - 创建ProductPart
原文地址:http://skywalkersoftwaredevelopment.net/blog/writing-an-orchard-webshop-module-from-scratch-par ...
- 从头开始编写一个Orchard网上商店模块(2) - 配置您的Orchard开发环境
原文地址:http://skywalkersoftwaredevelopment.net/blog/writing-an-orchard-webshop-module-from-scratch-par ...
- Drools文档(八) 规则语言参考
规则语言参考 概述 Drools有一个"本地"的规则语言.这种格式在标点符号上非常轻,并且通过"扩展器"支持自然语言和领域特定的语言,使语言能够变形到您的问题领 ...
- Drools 7.4.1.Final参考手册(八) 规则语言参考
规则语言参考 概述 Drools有一个“本地”的规则语言.这种格式在标点符号上非常轻,并且通过“扩展器”支持自然语言和领域特定的语言,使语言能够变形到您的问题领域.本章主要与本机规则格式一致.用于表示 ...
- 转:从头开始编写基于隐含马尔可夫模型HMM的中文分词器
http://blog.csdn.net/guixunlong/article/details/8925990 从头开始编写基于隐含马尔可夫模型HMM的中文分词器之一 - 资源篇 首先感谢52nlp的 ...
随机推荐
- Oracle定时执行存储过程(转)
定时执行存储过程在平时开发中经常会用到,年前的时候自己也做了一个,由于时间关系一直没能记录,现记录下来. 首先用一个完整的例子来实现定时执行存储过程. 任务目标:每小时向test表中插入一 ...
- 整理自百度知道提问的几道Java编程题
蚂蚁爬杆 问题描述: 有一根27厘米的细木杆,在第3厘米.7厘米.11厘米.17厘米.23厘米这五个位置上各有一只蚂蚁.木杆很细,不能同时通过一只蚂蚁.开始时,蚂蚁的头朝左还是朝右是任意的,它们只会朝 ...
- hdu 3309 Roll The Cube ( bfs )
Roll The Cube Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) To ...
- A Game of Thrones(12) - Eddard
The summons(['sʌm(ə)nz]召唤:传票) came in the hour before the dawn, when the world was still and grey. A ...
- 完整导出IntelliJ IDEA的快捷键
工欲善其事,必先利其器. 常常和代码打交道的人,熟练使用IDE快捷键那是必须的,由于快捷键能够把你从各种罗嗦事中解放出来.比方,假设没有快捷键,你就须要常常性的暂停快速执行的大脑,右手凭记忆摸到鼠标, ...
- JarSearch
个人做的小工具分享给大家~~. 支持从压缩文件搜索文件,特别是根据部分类文件名在jar里查找文件,比较方便,效率也还不错. 也支持从目录查找 http://pan.baidu.com/s/1feYaM ...
- AE+SceneControl源代码共享
近来的,博友发私信或邮件交换,第一次使用前SceneControl代做一点project股票,做的很粗糙.我们希望对大家有帮助,欢迎留言交流哈萨克斯坦. 除了主开.保存.数据加载.询价,几个功能主要是 ...
- net MVC 的八个扩展点
net MVC 的八个扩展点 MVC模型以低耦合.可重用.可维护性高等众多优点已逐渐代替了WebForm模型.能够灵活使用MVC提供的扩展点可以达到事半功倍的效果,另一方面Asp.net MVC优秀的 ...
- 运行一个android程序,直接访问某个网站
package android.com.youtube; import android.app.Activity; import android.content.Intent; import andr ...
- python之字符串的分割和拼接
关于string的split 和 join 方法 对导入os模块进行os.path.splie()/os.path.join() 貌似是处理机制不一样,但是功能上一样. 1.string.split( ...