利用Makfile给多文件、多目录C源码建立工程-600学习网
600学习网终身会员188,所有资源无秘无压缩-购买会员
0.前言
粉丝们留言了。如果你想知道如何使用Makefile为多个文件和多级目录创建一个项目,你必须安排它!
有关Makefile的介绍姓参考文章,请先参阅本文:
Makefile入门
为了给你一个更直观的感觉,我将在我之前写的一个小项目的基础上修改这篇文章。
项目的详细设计和规范如下:
从0开始编写电话号码管理系统的C入门项目[适合初学者]
1. 文件
好了,我们开始吧!
我们将把项目的所有函数放在以函数名命名的c文件中,以及相应名称的子目录中。
例如,函数allfree()存储在allfree/allfree中。c
最终目录结构如下图所示:
peng@ubuntu:/mnt/hgfs/code/phone$tree。。├── 全免费的│ ├── 全部免费.c│ └── 生成文件├── 创造│ ├── 创建.c│ └── 生成文件├── 删去│ ├── 删除.c│ └── 生成文件├── 陈列│ ├── 显示.c│ └── 生成文件├── 包括│ ├── 生成文件│ └── 电话.h├── 初始化│ ├── 初始值c│ └── 生成文件├── 登录│ ├── 登录.c│ └── 生成文件├── 主要的│ ├── 主.c│ └── 生成文件├── 生成文件├── 菜单│ ├── 生成文件│ └── 菜单.c├── 脚本│ └── 生成文件└── 搜索├── 生成文件└── search.c11目录,22个文件
查看编译结果:
peng@ubuntu:/mnt/hgfs/code/phone$makemake[1]:正在进入目录';/mnt/hgfs/code/phone/allfree';make[1]:无需为';所有';。make[1]:正在离开目录';/mnt/hgfs/code/phone/allfree';make[1]:正在进入目录';/mnt/hgfs/code/phone/create';make[1]:无需为';所有';。make[1]:正在离开目录';/mnt/hgfs/code/phone/create';make[1]:正在进入目录';/mnt/hgfs/code/phone/delete';make[1]:无需为';所有';。make[1]:正在离开目录';/mnt/hgfs/code/phone/delete';make[1]:正在进入目录';/mnt/hgfs/code/phone/display';make[1]:无需为';所有';。make[1]:正在离开目录';/mnt/hgfs/code/phone/display';make[1]:正在进入目录';/mnt/hgfs/code/phone/init';make[1]:无需为';所有';。make[1]:正在离开目录';/mnt/hgfs/code/phone/init';make[1]:正在进入目录';/mnt/hgfs/code/phone/login';make[1]:无需为';所有';。make[1]:正在离开目录';/mnt/hgfs/code/phone/login';make[1]:正在进入目录';/mnt/hgfs/code/phone/menu';make[1]:无需为';所有';。make[1]:正在离开目录';/mnt/hgfs/code/phone/menu';make[1]:正在进入目录';/mnt/hgfs/code/phone/search';make[1]:无需为';所有';。make[1]:正在离开目录';/mnt/hgfs/code/phone/search';make[1]:正在进入目录';/mnt/hgfs/code/phone/main';make[1]:无需为';所有';。make[1]:正在离开目录';/mnt/hgfs/code/phone/main';gcc-Wall-O3-o phone allfree.o create.o delete.o display.o init.o login.o menu.o search.o main.o-lpthreadphone make done!
运行结果如下:
2. [0]Makefile公共基础知识的符号'@';ལ$&# 39; &# 39;$$&# 39; &# 39;-&# 39; &# 39;- n';'@';的说明;通常,makefile会在执行之前将其执行的命令行输出到屏幕。如果在命令行中添加@,make将不会回显该命令。例如:@echo–编译模块–//Screen output–编译模块–echo-编译模块–//否@Screen output echo—编译模块–';-&##39;
通常删除。如果遇到不存在或已创建的文件,如果要忽略此错误并继续执行,可以在命令前面添加-,
-rm目录;-mkdir aaadir;
' $ &# 39; 美元符号$主要扩展在打开的makefile中定义的变量
' $$ &# 39;$$ 该符号主要扩展在打开的makefile中定义的shell变量
[1] 通配符
注意:列出当前目录中所有符合模式”pattern”格式并用空格分隔的文件名。”PATTERN”使用shell识别的通配符,包括”?”(单个字符).”*”(多个字符)等示例:
$(通配符*.c)
返回值是所有值的列表。c当前目录中的源文件。
[2] 巴萨斯特
注:替换以结尾的单词。字符串“x.c.c bar.c”中的c,字符以结尾。o. 示例:
$(patsubst%.c,%.o,x.c.c bar.c)
函数的返回结果为
x. c.o棒.o[3]不直接
说明:从文件名中删除路径信息的示例:
src=(notdir./SRC/a.c)
删除文件a.c.的路径信息。使用(notdir./src/a.c)删除文件a.c.的路径信息,使用(notdir./src.a.c)移除文件a.c.。使用(src)获取没有路径的文件名,即a.c。
[4] 包括头文件路径
使用-I+头文件路径指定编译器头文件的路径示例:
INCLUDES=-I./inc$(CC)-c$(includess)$(SRC)[5]添加后缀
函数名称:后缀函数addsuffix。语法:
$(添加后缀后缀,名称…)
功能功能:在”NAMES…”中的每个文件名中添加后缀”suffix”。参数”NAMES…”是一个以空格分隔的文件名序列,并且在该序列中的每个文件名的末尾附加”SUFFIX”。返回值:由一个空格分隔的文件名序列,并添加后缀”suffix”。功能描述:示例:
$(addsuffix.c,foo bar)
返回值为
福。c巴。c[6]包含另一个文件:include
在Makefile中使用include关键字可以包含其他Makefiles,很像C中的#includ,并且包含的文件将准确地放置在当前文件的包含位置。例如命令
包含文件.dep
即文件。dep文件在当前Makefile中展开,即文件的内容。dep文件包含在当前Makefile中
include之前可以有一些空字符,但不能以[Tab]键开头。
[7] foreach公司
foreach函数与其他函数非常不同。因为此函数的语法用于循环:
美元(每个
此函数意味着逐个取出参数中的单词,并将它们放入参数指定的变量中,然后执行包含的表达式。
每次都会返回一个字符串。在循环期间,由返回的每个字符串将由空格分隔。最后,当整个循环结束时,由每个返回字符串组成的整个字符串(用空格分隔)将成为foreach函数的返回值。
因此,最好使用变量名,它可以是表达式。通常,此参数用于按顺序枚举单词。
给出一个例子:
名称:=a b c数据文件:=$(foreach n,$(name),$(n).o)
在上面的例子中,$(name)中的单词将逐个取出并存储在变量”n”中。”$(n).o”将根据”$(n)”每次计算一个值。这些值由空格分隔,最后由foreach函数返回。因此,$(files)的值为”a.o b.o c.o d.o”。
注意,foreach中的参数是一个临时局部变量。执行foreach函数后,参数的变量将不起作用,其作用域仅在foreach功能中。
[8] 呼叫
“call”函数是唯一可以创建自定义参数函数的引用函数。此函数可用于引用用户定义的函数。我们可以将变量定义为一个复杂的表达式,并使用”call”函数根据不同的参数对其进行扩展,以获得不同的结果。
函数语法:
$(调用变量,param1,param2,…)
在函数中,”variable”是变量名,而不是变量引用。因此,”call”函数中的”variable”通常不包含”$”(当然,除非变量名是计算变量名)。当变量”variable”是make中嵌入的函数名(例如”if”.”foreach”.”strip”等)时,应注意使用”param”参数,因为不适当或不正确的参数将导致函数的返回值不可预测。函数中的多个”参数”由逗号分隔。变量不能定义为直接展开!只能定义为递归展开。
功能示例:
reverse=$(2)$(1)foo=$(调用reverse,a,b)all:@echo”foo=$foo”
执行结果:
foo=巴
也就是说,a替换(2)
3. 编译详细信息
在根目录中执行make命令后,详细步骤如下:
Include scripts/Makefile:将文件替换到当前位置,并使用默认目标all。这个目标依赖于脚本/Makefile中定义的$(target)$(target),即phone,而$(Targe)依赖于mmmm。此目标将执行@$(foreach n,$(Modules),$(call Modules_make,$(n))
模块是所有目录名的集合。foreach将遍历字符串$(Modules)中的每个单词,将每个单词分配给n,并执行语句:
调用模块_ make.$(n)模块_,
$(MAKE)具有默认名称MAKE-C:输入子目录并执行MAKE$(1):在步骤4中是$(n),即每个目录的名称
步骤4中的最后一条语句是进入每个目录并在每个目录中执行Makefile
输入一个子目录并执行Makefile,默认目标为all,具体取决于ObjsObjs:=$(patsubst%.c,%.o,$(Source))
Patsubst替换以结尾的单词。字符串$source中的c,字符以结尾。o)
来源:=$(通配符..c)
通配符将列出所有内容。当前目录中的c文件
因此,第6步是编译所有。子目录中的c文件来生成。o具有相应文件名的文件
$(CC)$(CFLAGS)-o$(目标)$(所有对象)$(Libs)
这些变量在文件脚本/Makefile:$(CC)被gcc替换,编译器$(CFLAGS)被公式化,-Wall-O3被-o$(Target)替换,这是编译时的优化级别。生成可执行的phone$(AllObjs):
AllObjs:=$(addsuffix.o,$(模块))
Addsuffix将追加。o到$(Modules)中的所有单词,即所有。o我们之前在子目录中编译的文件$(Libs):替换为-lpthread,即所需的动态库
根据此步骤,您可以在执行make clean时分析执行步骤
600学习网 » 利用Makfile给多文件、多目录C源码建立工程-600学习网