系列文章目录
一、Linux嵌入式学习之Ubuntu入门(一)基本命令、软件安装及文件结构
二、Linux嵌入式学习之Ubuntu入门(二)磁盘文件介绍及分区、格式化等
三、Linux嵌入式学习之Ubuntu入门(三)用户、用户组及文件权限
文章目录
- 系列文章目录
- 什么是Makefile
- 什么是GCC
- Makefile文件规范
- 简单例子中的规范写法
- Makefile变量写法
- Makefile其他符号
- 打印输出
- “=”
- “:=”
- “+=”
- “?=”
- Makefile模式规则
- Makefile自动化变量
- Makefile伪目标
- Makefile条件判断
- ifeq与ifneq
- ifdef与ifndef
- Makefile函数
什么是Makefile
在Linux下,借助例如gcc编译器编译时,如果有很多的文件:
1、如果工程没有编译过,那么工程中的所有.c 文件都要被编译并且链接成可执行程序。
2、如果工程中只有个别 C 文件被修改了,那么只编译这些被修改的 C 文件即可。
3、如果工程的头文件被修改了,那么我们需要编译所有引用这个头文件的 C 文件,并且链接成可执行文件。
什么是GCC
gcc [选项] [文件名字]
主要选项如下:
-c: 只编译不链接为可执行文件,编译器将输入的.c 文件编译为.o 的目标文件。
-o: <输出文件名>用来指定编译结束以后的输出文件名,如果不使用这个选项的话 GCC 默认编译出来的可执行文件名字为 a.out。
-g: 添加调试信息,如果要使用调试工具(如 GDB)的话就必须加入此选项,此选项指示编译的时候生成调试所需的符号信息。
-O: 对程序进行优化编译,如果使用此选项的话整个源代码在编译、链接的的时候都会进行优化,这样产生的可执行文件执行效率就高。
-O2: 比-O 更幅度更大的优化,生成的可执行效率更高,但是整个编译过程会很慢。
在程序中,int main(int argc, char *argv[])是什么意思:
很多程序都是带参数运行的,如:del readme.txt,此时,运行的程序就是del.exe,而readme.txt就是它的参数,
argc = 1,(1个参数)
argv[0] = “readme.txt”(接收的字符串);
假设一个程序的main函数不带任何参数,那么很显然,它仍可以运行,只是,不接收参数。
Makefile文件规范
1.所有行首需要空出来的地方一定要使用“TAB”键!不要使用空格键!
2.make 命令会在当前目录下查找是否存在“Makefile”这个文件(小写也可以)
简单例子中的规范写法
makefile中,一般将第一行作为默认目标,所以clean不会执行,可以使用nake clean执行。(clean是伪目标)
同时make过程中,会自动输出这些命令,如果前面加上@,这些命令就不会输出。
Makefile变量写法
Makefile其他符号
打印输出
echo:相当printf
“=”
赋值符号:这里输出的就是
name = jia
curname = $(name)
name = jiahj
print:
@echo curname: $(curname)
这里输出结果是:curname:jiahj
使用的是最新赋值的变量
“:=”
name = jia
curname := $(name)
name = jiahj
print:
@echo curname: $(curname)
这里输出结果是:curname:jia
使用的前面定义好的
“+=”
变量追加符号
objects = main.o inpiut.o
objects += calcu.o
变量 objects 变成了“main.o input.o calcu.o”
“?=”
curname ?= jia
变量如果前面没有被赋值,那么该变量就是jia
Makefile模式规则
用%表示任意长度的非空字符串,例如:“%.c”就是所有的.c文件
Makefile自动化变量
上面的那个makefile例子可以变成下面形式:
objects = main.o input.o calcu.o
main: $(objects)
gcc -o main $(objects)
%.o : %.c
gcc -c $<
clean:
rm *.o
rm main
Makefile伪目标
像之前执行的make clean一样,当该目录下有一个clean文件的时候,就无法执行makefile的clean目标了
PHONY : clean
用如上命令将clean声明成伪目标就可以了
Makefile条件判断
语法:
ifeq与ifneq
下面几种写法都可以
ifeq判断参数1与2是否相等,相等则为真。ifneq反之
ifdef与ifndef
变量名的值为非空即为真,否则为假。ifndef反之
Makefile函数
用法:
参数之间用逗号,函数名与参数之间用空格
函数名 | 含义 |
---|---|
$(subst < x1>,< x2>,< text>) | 将字符串< text>中的< x1>内容替换为< x2>,函数返回被替换以后的字符串 |
$(patsubst < pattern>,< replacement>,< text>) | 查找字符串< text>中的单词是否符合模式< pattern>,如果匹配就用< replacement>来替换掉,函数返回值就是替换后的字符串 |
$(dir <names…>) | 从文件名序列< names>中提取出目录部分,返回值是文件名序列< names>的目录部分 |
$(notdir <names…>) | 去除文件中的目录部分,也就是提取文件名, |
$(foreach < var>, < list>,< text>) | 把参数< list>;中的单词逐一取出放到参数< var>;所指定的变量中,然后再执行< text>;所包含的表达式。 |
$(wildcard PATTERN…) | 通配符“%”只能用在规则中,只有在规则中它才会展开,如果在变量定义和函数使用时,这个时候就要用到函数 wildcard |
例子:
1.
$(patsubst %.c,%.o,a.c b.c c.c)
将字符串“a.c b.c c.c”中的所有符合“%.c”的字符串,替换为“%.o”,替换完成以后的字符串为“a.o b.o c.o”。
$(dir </src/a.c>)
提取文件“/src/a.c”的目录部分,也就是“/src”。
$(notdir </src/a.c>)
提取文件“/src/a.c”中的非目录部分,也就是文件名“a.c”。
names := a b c d
files := $(foreach n,$(names),$(n).o)
$ (name)中的单词会被挨个取出,并存到变量“n”中,“ $ (n).o”每次根据“$ (n)”计算出一个值,这些值以空格分隔,最后作为foreach函数的返回,所以,$(files)的值是“a.o b.o c.o d.o”。
5.
$(wildcard *.c)
获取当前目录下所有的.c 文件,类似“%”。