1.工程
对于开发一个项目而言,远远不是一个函数或者一个文件能够完成的
因此,在进行项目开发的时候,我们需要搭建好一个项目的目录
来管理我们的文件,对文件分类
项目的目录基本框架
project_name/ 项目目录的名称,这是一个总目录,下面所有东西都在这个目录下面
一个目录就代表这一个项目
src/ 源代码目录 用来存放项目中的.c文件
inc/ 头文件目录 用来存放自己或第三方的头文件
lib/ 库文件目录 用来存放自己或第三方的库文件
READme.txt
项目的说明文 用来介绍项目或者提供项目的使用指南
ChangeLog.txt
项目日志,用来记录对项目进行的主要更改
用于内部进行归纳总结,避免同样的文件还需要花时间去调试
2.what is Makefile
Makefile是make的配置文件,make是一个智能化的自动编译的工程管理工具,
它可以决定一个工程,那些文件需要被编译,那些不要被编译,而且它还知道
如果去编译它们!!!
make这么强大,是怎么做到的呢?
Makefile会告诉make怎么去做,如何去做
3.Makefile怎么写
核心语法
TARGET:PREREQUISITES
<TAB键>RECIPE
<TAB键>RECIPE
<TAB键>.....
TARGET 目标 通常就是你生成的文件名叫什么
PREREQUISITES 依赖文件 你要生成目标文件 你需要那些文件
RECIPE 规则 你需要怎么去做 怎么去生成
1.make的变量
在makefile中用户可以定义变量 这个变量没有类型 都是当作字符串去处理
1.1如果定义变量
顶个写变量名就可以了
1.2如何引用变量
$(变量名) 引用变量的值
2.变量赋值 := = += ?=
1. := 简单赋值/直接赋值 不会向后展开 跟c语言的'='含义相同
A:=10086
B:=$(A)
A:=13800
A =>13800
B =>10086
2. = 递归赋值 向后展开赋值
A:=10086
b=$(A)
A:=13800
A=>13800
b=>13800
3.'+=' 追加赋值
A:=123
A+=456
A=>456
4.'?='条件赋值
当变量没有定义没有赋值的时候才会去赋值
A?=123 =>A没有被赋值 所以A的赋值为123
A:=456 =>A被直接赋值 456
A?=132 =》A已经赋值,所以不赋值
3.makefile的自带变量
已经有人定义好的 ,直接用的变量
make内置了一些变量
$@ 目标文件的完整名
$+ 所有依赖文件 自动以空格隔开 可能包含重复的依赖文件
$< 第一个依赖文件
$? 所有时间戳比目标文件晚的依赖文件 并以空格隔开
$^ 所有依赖文件 自动以空格隔开 不包含重复的依赖文件
4.makefile通配规则
%.o:%.c 是什么意思
%表示匹配任意长度,任意符号的字符串
5.makefile内置函数
在make中允许用户自己定义并调用函数
调用方式
$(函数名 函数参数列表)
patsubst 模式字符串替换函数
$(patsubst <from>,<to>,<text>)
将原始字符串text中的from替换为to
wildcard 搜索函数,用来搜索参数指定的文件
例如
$(wildcard 文件路径/*.c)
makefile文件结构:
#目标程序文件
#编译器
#依赖文件列表
#中间文件列表
#头文件路径
#库的路径
#链接
# $(目标文件):$(中间文件)
#生成目标文件
# $(中间文件):$(依赖文件)
#输入make clean会执行下面的命令,将相应生成的文件删除
clean:
rm $(OBJ)
rm $(TRAGET)
makefile 文件模板:(*****)
#目标程序名称
TARGET:=Album
#编译器
CC:=arm-linux-gcc
CSRCS:=$(wildcard ./src/*.c)
#中间文件列表
OBJ:=$(patsubst ./src/%.c,./obj/%.o,$(CSRCS))
#头文件路径
INC:= -I./inc
#库的路径
LIB:= -L./lib -lm
#链接
$(TARGET):$(OBJ)
$(CC) $^ $(LIB) -o $@
cp $@ ~/tftp/
#生成目标文件
./obj/%.o:./src/%.c
$(CC) -c $(INC) $? -o $@
clean:
rm $(OBJ)
rm $(TARGET)
makefile 文件模板:
#目标程序名称
TRAGET := line
#编译器
CC := arm-linux-gcc
#依赖文件列表
#CSRCS:=./src/main.c ./src/line.c
CSRCS:=$(wildcard ./src/*.c)
#CSRCS_PATH := ./src
#CSRCS :=$(CSRCS_PATH)/line.c $(CSRCS_PATH)/main.c
#中间文件列表
#OBJ:=./obj/main.o ./obj/line.o
OBJ:= $(patsubst ./src/%.c,./obj/%.o,$(CSRCS))
#OBJ_PATH := ./obj
#OBJ := $(patsubst $(CSRCS_PATH)/%.c,$(OBJ_PATH)/%.o,$(CSRCS))
#头文件路径
INC := -I ./inc
#库的路径
LIB := -L ./lib -lm
#链接
$(TRAGET):$(OBJ)
$(CC) $^ $(LIB) -o $@
cp $@ ~/tftp #将目标文件复制到tftp文件中
#生成目标文件
./obj/%.o:./src/%.c
$(CC) -c $? $(INC) -o $@
#链接
# $(目标文件):(中间文件)
# gcc main.o hello.o 库 -o main
# $(CC) $^ $(LIB) -o $@
# cp $@ ~/tftp
#生成目标文件
# ./obj/%.o:./src/%.c
# $(中间文件):$(依赖文件)
# gcc -c main.c -o main.o 头文件 库
# $(CC) -c $(INC) $? -o $@
clean:
rm $(OBJ)
rm $(TRAGET)
#如果arm-linux-gcc 进行,要将动态库进行修改需要下面的代码
# rm $(lib)