目录
一、前言
工作中需要一些嵌入式相关知识做个记录。
二、makefile
2.1 宏定义-D
-D macro=string,等价于在头文件中定义:#define macro string。例如:-D TRUE=true,等价于:#define TRUE true
-D macro,等价于在头文件中定义:#define macro 1,实际上也达到了定义:#define macro的目的。例如:-D Linux,等价于:#define LINUX 1(与#define LINUX作用类似)。
--define-macro macro=string与-D macro=string作用相同。
2.2 变量引用$()
$(var),表示对var的引用,它其实是读取makefile中的变量var,然后将其扩展开,传给shell命令
2.3 条件判断
关键字 | 功能 |
---|---|
ifeq | 判断参数是否不相等,相等为 true,不相等为 false。 |
ifneq | 判断参数是否不相等,不相等为 true,相等为 false。 |
ifdef | 判断是否有值,有值为 true,没有值为 false。 |
ifndef | 判断是否有值,没有值为 true,有值为 false。 |
libs_for_gcc= -lgnu
normal_libs=
foo:$(objects)
ifeq($(CC),gcc)
$(CC) -o foo $(objects) $(libs_for_gcc)
else
$(CC) -o foo $(objects) $(noemal_libs)
endif
2.4 makefile规则
targets : prerequisites依赖的关系
command执行的命令
或者
targets : prerequisites; command
command
- targets:规则的目标,可以是 Object File(一般称它为中间文件),也可以是可执行文件,还可以是一个标签;
- prerequisites:是我们的依赖文件,要生成 targets 需要的文件或者是目标。可以是多个,也可以是没有;
- command:make 需要执行的命令(任意的 shell 命令)。可以有多条命令,每一条命令占一行。
注意:我们的目标和依赖文件之间要使用冒号分隔开,命令的开始一定要使用Tab
键。
test:test.c
gcc -o test test.c
2.5 打印信息
$(info info text)、$(warning warning text)或者$(error error text)
2.6 赋值
= 是最基本的赋值,变量的值将会是整个makefile中最后被指定的值
:= 是覆盖之前的值,变量的值决定于它在makefile中的位置,是当前值
?= 是如果没有被赋值过就赋予等号后面的值
+= 是添加等号后面的值
2.7 内置函数
strip:函数是去除字符串空格函数
override:如果不希望命令行指定的变量值替代在Makefile中的变量定义,那么我们需要在Makefile中使用指示符“override”来对这个变量进行声明,override有保护makefile中变量值不被命令行参数修改的作用
override APP := $(strip $(APP))
basename :文件名操作函数 ,返回一一个字符串 .
之前的所有字段
$(basename src/foo.c src-1.0/bar.c /home/jack/.font.cache-1 hacks)
返回:“src/foo src-1.0/bar /home/jack/.font hacks”
notdir:去除所有的目录信息,SRC里的文件名列表将只有文件名
wildcard:通配符。
使用:SRC = $(wildcard *.c ./foo/*.c)
搜索当前目录及./foo/下所有以.c结尾的文件,生成一个以空格间隔的文件名列表,并赋值给SRC.当前目录文件只有文件名,子目录下的文件名包含路径信息,比如./foor/bar.c。
$(basename $(notdir $(wildcard $(APPL_ROOT)/*/*.mk)))
-I include 向编译器表明指定的头文件的存放路径
-L lib 向编译器表明指定的库的存放路径
-l 向编译器表明所调用的库的名字
数学库 -lm ; posix线程 -lpthread ; -ldl 动态链接库
subst:是一个替换函数,这个函数有三个参数,第一个参数是被替换字串,第二个参数是替换字串,第三个参数是替换操作作用的字串
comma:= ,
empty:=
space:= $(empty) $(empty)
foo:=a b c
bar:= $(subst $(space),$(comma),$(foo)) //结果a,b,c
dir: 从文件名序列<names>
中取出目录部分。目录部分是指最后一个反斜杠(“/”)之前的部分
2.8 二次展开
GNU make 能够为某些或者所有定义在 makefile 中的目标(target)使能依赖(prerequisite,仅适用于依赖)的二次展开(secondary expansion)。想要使能二次展开,需要在第一个需要使用该特性的依赖之前定义特殊目标 .SECONDEXPANSION。
所有变量和函数已经在 makefile 的第一次解析中展开,所以大部分情形下,二次展开没有任何作用。想要利用二次展开特性,需要转义变量或函数引用,即在第一次展开时转义引用,在二次展开时再展开变量或函数引用。
.SECONDEXPANSION:
AVAR = top
onefile: $(AVAR)
twofile: $$(AVAR)
AVAR = bottom
上例中,onefile*
的依赖会被立即展开,解析为 top
,而 twofile
的依赖会在二次展开时被完全展开,其值为 bottom
。
一般的格式是:
target:components
rule
第一行表示的是依赖关系,第二行是所需文件齐全后得出目标所用的语句。
main:main.o mytool1.o mytool2.o
gcc -o main main.o mytool1.o mytool2.o
main.o:main.c mytool1.h mytool2.h
gcc -c main.c
mytool1.o:mytool1.c mytool1.h
gcc -c mytool1.c
mytool2.o:mytool2.c mytool2.h
gcc -c mytool2.c
clean:
rm -rf *.o main
Makefile有三个非常有用的变量。分别是$@,$^,$< 代表的意义分别是:
$@ 目标文件
$^ 所有的依赖文件
$< 第一个依赖文件
这样就可以把文件简化为
main:main.o mytool1.o mytool2.o
gcc -o $@ $^
main.o:main.c mytool1.h mytool2.h
gcc -c $<
mytool1.o:mytool1.c mytool1.h
gcc -c $<
mytool2.o:mytool2.c mytool2.h
clean:
rm -rf *.o main
# 指令编译器和选项
CC=gcc
CFLAGS=-Wall -std=gnu99
# 目标文件
TARGET=test
SRCS = test.c \
./test-add/test-add.c \
./test-sub/test-sub.c
INC = -I./test-add -I./test-sub
OBJS = $(SRCS:.c=.o)
$(TARGET):$(OBJS)
# @echo TARGET:$@
# @echo OBJECTS:$^
[tab]$(CC) -o $@ $^
clean:
[tab]rm -rf $(TARGET) $(OBJS)
%.o:%.c
[tab]$(CC) $(CFLAGS) $(INC) -o $@ -c $<