makefile的编写
来源:互联网 发布:域名转入万网和阿里云 编辑:程序博客网 时间:2024/06/15 01:49
这里使用的sdcc编辑器, Makefile是为了编译单片机项目自己写的,写的过程中,改进的,到最后使用自己添加文件防止编译一些自己没有使用到的文件而浪费了大量内存和空间.
$@
代表规则中的目标文件名。如果目标是一个文档(Linux中,一般称.a文件为文档),那么它代表这个文档的文件名。在多目标的模式规则中,它代表的是哪个触发规则被执行的目标文件名。
$%
规则的目标文件是一个静态库文件时,代表静态库的一个成员名。例如,规则的目标是“foo.a(bar.o)”,那么,“$%”的值就为“bar.o”,“$@”的值为“foo.a”。如果目标不是函数库文件,其值为空。
$<
规则的第一个依赖文件名。如果是隐含规则,则它代表通过目标指定的第一个依赖文件。
$?
所有比目标文件更新的依赖文件列表,空格分割。如果目标是静态库文件名,代表的是库成
员(.o文件)的更新情况。
$^
规则的所有依赖文件列表,使用空格分隔。如果目标是静态库文件名,它所代表的只能是所有库成员(.o文件)名。一个文件可重复的出现在目标的依赖中,变量“$^”只记录它的一次引用情况。就是说变量“$^”会去掉重复的依赖文件。
$+
类似“$^”,但是它保留了依赖文件中重复出现的文件。主要用在程序链接时,库的交叉引用场合。
$(@D)
代表目标文件的目录部分(去掉目录部分的最后一个斜杠)。如果“$@”是“dir/foo.o”,那么“$(@D)”的值为“dir”。如果“$@”不存在斜杠,其值就是“.”(当前目录)。注意它和函数“dir”的区别!
$(@F)
目标文件的完整文件名中除目录以外的部分(实际文件名)。如果“$@”为“dir/foo.o”,那么“$(@F)”只就是“foo.o”。“$(@F)”等价于函数“$(notdir $@)”。
$(%D)
$(%F)
当以如“archive(member)”形式静态库为目标时,分别表示库文件成员“member”名中的目录部分和文件名部分。它仅对这种形式的规则目标有效。
$(<D)
$(<F)分别表示规则中第一个依赖文件的目录部分和文件名部分。
$(^D)
$(^F)分别表示所有依赖文件的目录部分和文件部分(不存在同一文件)。
$(+D)
$(+F)分别表示所有依赖文件的目录部分和文件部分(可存在重复文件)。
$(?D)
$(?F)分别表示被更新的依赖文件的目录部分和文件部分。
寻找.o文件并且删除.
find ${DIR_OBJ} -name *.o -exec rm -rf {} \ ;
foreach:
foreach是用来做循环用的,类似于for 语句,语法是:$(foreach <var>,<list>,<text> )
意思:把参数<list>中的单词逐一取出放到参数<var>所指定的变量中,然后再执行<text>所包含的表达式。每一次<text>会返回一个字符串,循环过程中,<text>的所返回的每个字符串会以空格分隔,最后当整个循环结束时,<text>所返回的每个字符串所组成的整个字符串(以空格分隔)将会是foreach函数的返回值。所以,<var>最好是一个变量名,<list>可以是一个表达式,而<text>中一般会使用<var>这个参数来依次枚举<list>中的单词。
下面我们要介绍的函数主要是处理文件名的。每个函数的参数字符串都会被当做一个或是一系列的文件名来对待。
$(dir )
名称:取目录函数——dir。功能:从文件名序列中取出目录部分。目录部分是指最后一个反斜杠(“/”)之前的部分。如果没有反斜杠,那么返回“./”。返回:返回文件名序列的目录部分。示例: $(dir src/foo.c hacks)返回值是“src/ ./”。 $(notdir )
名称:取文件函数——notdir。功能:从文件名序列中取出非目录部分。非目录部分是指最后一个反斜杠(“/”)之后的部分。返回:返回文件名序列的非目录部分。示例: $(notdir src/foo.c hacks)返回值是“foo.c hacks”。 $(suffix )
名称:取后缀函数——suffix。功能:从文件名序列中取出各个文件名的后缀。返回:返回文件名序列的后缀序列,如果文件没有后缀,则返回空字串。示例:$(suffix src/foo.c src-1.0/bar.c hacks)返回值是“.c .c”。 $(basename )名称:取前缀函数——basename。功能:从文件名序列中取出各个文件名的前缀部分。返回:返回文件名序列的前缀序列,如果文件没有前缀,则返回空字串。示例:$(basename src/foo.c src-1.0/bar.c hacks)返回值是“src/foo src-1.0/bar hacks”。
$(addsuffix , )
名称:加后缀函数——addsuffix。功能:把后缀加到中的每个单词后面。返回:返回加过后缀的文件名序列。示例:$(addsuffix .c,foo bar)返回值是“foo.c bar.c”。 $(addprefix , )
名称:加前缀函数——addprefix。功能:把前缀加到中的每个单词后面。返回:返回加过前缀的文件名序列。示例:$(addprefix src/,foo bar)返回值是“src/foo src/bar”。 $(join , )名称:连接函数——join。功能:把中的单词对应地加到的单词后面。如果的单词个数要比的多,那么,中的多出来的单词将保持原样。如果的单词个数要比多,那么,多出来的单词将被复制到中。返回:返回连接过后的字符串。示例:$(join aaa bbb , 111 222 333)返回值是“aaa111 bbb222 333”。
使用简单的makefile规则
INCLUDE_DIR = ./LED
main:main.c LED.c
#将*.c编译但不连接
sdcc -c LED.c -I $(INCLUDE_DIR)
sdcc -c main.c
#编译链接*.o
sdcc main.rel LED.rel
#将ihx转换为hex格式
packihx main.ihx > main.hex
#将hex格式转换为bin
objcopy -I ihex -O binary main.hex main.bin
#清理编译产物
clean:
rm -rf *.ihx *.bin *.lst *.rel *.sym *.rst *.lk *.asm *.map *.mcu8051ide~ *.mem *.hex
使用自动化变量
#添加依赖头文件路径
INCLUDE_DIR = ./LED
#最终生成的目标名字都为main.*
obj= LED.rel main.rel
#$^ : 规则的所有依赖文件列表
#生成main,bin文件
main:main.hex
#将hex格式转换为bin
objcopy -I ihex -O binary main.hex main.bin
#生成main.hex
main.hex:main.ihx
packihx main.ihx > main.hex
#$^ : 规则的所有依赖文件列表
main.ihx:$(obj)
sdcc $^ -o main.ihx
#$< : 规则的第一个依赖文件名
#$@ : 代表规则中的目标文件名
%.rel:%.c
sdcc -c $< -I $(INCLUDE_DIR) -o $@
#清理编译产物
.PHONY:clean
clean:
rm -rf *.ihx *.bin *.lst *.rel *.sym *.rst *.lk *.asm *.map *.mcu8051ide~ *.mem *.hex
输出的文件在obj中,bin文件在当前目录下,源码放在当前目录,秩序在source添加自己的.c文件,在INCLUDE_DIR添加头文件路径
INCLUDE_DIR = ./
source = LED.c main.c
#不能有空格,将.c结尾的文件名转换为.rel结尾的文件名列表
objs = $(source:.c=.rel)
#在每一个文件名前加上路径./objdir/
objs := $(addprefix ./objdir/,$(objs))
main: objdir $(objs)
#将*.c编译但不连接
#编译链接*.o
sdcc ./objdir/main.rel ./objdir/LED.rel -o ./objdir/main.ihx
#将ihx转换为hex格式
packihx ./objdir/main.ihx > ./objdir/main.hex
#将hex格式转换为bin
objcopy -I ihex -O binary ./objdir/main.hex main.bin
objdir:
mkdir objdir
./objdir/%.rel:%.c
sdcc -c $< -I $(INCLUDE_DIR) -o $@
#清理编译产物
clean:
rm -rf ./objdir main.bin
自动扫描当前文件中c文件,并编译链接
################################################################################
#添加自己的头文件位置
INCLUDE_DIR = ./
# 自动扫描当前文件中的c文件
source = $(wildcard ./*.c)
################################################################################
#不能有空格,将.c结尾的文件名转换为.rel结尾的文件名列表
objs = $(source:.c=.rel)
#在每一个文件名前加上路径./objdir/
objs := $(addprefix ./objdir/,$(objs))
main: objdir $(objs)
#编译链接*.o
sdcc $(objs) -o ./objdir/main.ihx
#将ihx转换为hex格式
packihx ./objdir/main.ihx > ./objdir/main.hex
#将hex格式转换为bin
objcopy -I ihex -O binary ./objdir/main.hex main.bin
objdir:
mkdir objdir
#将*.c编译但不连接
./objdir/%.rel:%.c
sdcc -c $< -I $(INCLUDE_DIR) -o $@
#清理编译产物
clean:
rm -rf ./objdir main.bin
源文件定义在DIR_SRC,头文件定义在DIR_INC,中间文件定义在DIR_OBJ,目标文件生成目录DIR_BIN
#定义头文件路径
DIR_INC = ./include
#定义源文件路径
DIR_SRC = ./src
#定义中间文件路径
DIR_OBJ = ./obj
#定义目标文件路径
DIR_BIN = .
# wildcard : 扩展通配符
# notdir : 去除路径
# patsubst :替换通配符
#搜索制定目录所有文件
SRC = $(wildcard ${DIR_SRC}/*.c)
#将.c文件替换成.rel文件
OBJ = $(patsubst %.c,${DIR_OBJ}/%.rel,$(notdir ${SRC}))
# $@代表规则中的目标文件名
main:$(DIR_OBJ) ${OBJ}
#编译链接*.o
sdcc $(OBJ) -o $(DIR_OBJ)/main.ihx
#将ihx转换为hex格式
packihx $(DIR_OBJ)/main.ihx > $(DIR_OBJ)/main.hex
#将hex格式转换为bin
objcopy -I ihex -O binary $(DIR_OBJ)/main.hex $(DIR_BIN)/main.bin
$(DIR_OBJ):
mkdir $(DIR_OBJ)
echo $(SRC)
echo $(OBJ)
#将*.c编译但不连接
$(DIR_OBJ)/%.rel:${DIR_SRC}/%.c
sdcc -c $< -I $(DIR_INC) -o $@
#清理编译产物
clean:
rm -rf $(DIR_OBJ) main.bin
多级文件的Makefile编写
执行shell命令,将结果返回(返回所有头文件,包括路径)
INCLUDE := $(shell find ./ -name "*.h")
#找到所有的源文件
SRC := $(shell find ./ -name "*.c")
#找到所有的头文件路径
INCLUDE := $(shell find ./ -name "*.h")
# dir : 取目录函数
DIR_INC = $(addprefix -I,$(dir $(INCLUDE)))
#定义中间文件路径
DIR_OBJ = ./obj
#定义目标文件路径
DIR_BIN = .
#将.c文件替换成.rel文件
#在编译的时候,直接将目标文件的后缀替换,这样在以后编译文件时,可以更方便的写之后的Makefile
OBJ = $(patsubst %.c,%.rel,${SRC})
# $@代表规则中的目标文件名
main:$(DIR_OBJ) ${OBJ}
#编译链接*.o
sdcc $(addprefix $(DIR_OBJ)/,$(notdir ${OBJ})) -o $(DIR_OBJ)/main.ihx
#将ihx转换为hex格式
packihx $(DIR_OBJ)/main.ihx > $(DIR_OBJ)/main.hex
#将hex格式转换为bin
objcopy -I ihex -O binary $(DIR_OBJ)/main.hex $(DIR_BIN)/main.bin
$(DIR_OBJ):
mkdir $(DIR_OBJ)
echo $(DIR_INC)
echo $(SRC)
echo $(OBJ)
#将*.c编译但不连接
%.rel:%.c
sdcc -c $< $(DIR_INC) -o $(addprefix $(DIR_OBJ)/,$(notdir $@))
#清理编译产物
clean:
rm -rf ./obj ./main.bin
#找到所有的源文件
SRC := $(shell find ./ -name "*.c")
#找到所有的头文件路径
INCLUDE := $(shell find ./ -name "*.h")
# dir : 取目录函数
DIR_INC = $(addprefix -I,$(dir $(INCLUDE)))
#定义中间文件路径
DIR_OBJ = ./obj
#定义目标文件路径
DIR_BIN = .
#将.c文件替换成.rel文件
OBJ = $(patsubst %.c,%.rel,${SRC})
# $@代表规则中的目标文件名
main:$(DIR_OBJ) ${OBJ}
#编译链接*.o
sdcc ${OBJ} -o $(DIR_OBJ)/main.ihx
#将ihx转换为hex格式
packihx $(DIR_OBJ)/main.ihx > $(DIR_OBJ)/main.hex
#将hex格式转换为bin
objcopy -I ihex -O binary $(DIR_OBJ)/main.hex $(DIR_BIN)/main.bin
#将*.c编译但不连接
%.rel:%.c
sdcc -c $< $(DIR_INC) -o $@
#清理编译产物
clean:
#查找文件,进行删除
find ./ -name "*.rel" -exec rm -rf {} \;
find ./ -name "*.lst" -exec rm -rf {} \;
find ./ -name "*.rst" -exec rm -rf {} \;
find ./ -name "*.sym" -exec rm -rf {} \;
find ./ -name "*.asm" -exec rm -rf {} \;
rm $(DIR_BIN)/main.bin
rm ./obj -rf
循环执行USR_SUB_DIR文件中的Makefile
@for n in $(USR_SUB_DIR);do $(MAKE) -C $$n;done
@for n in $(USR_SUB_DIR);do $(MAKE) -C $$n;done
#自己添加要编译的文件,这样就不会因为编译没有用到的文件而浪费空间
SRC := main.c ./TIMER/TIMER.c ./DS18B20/DS18B20.c ./LCD1602/LCD1602.c \
./UART/UART.c
#找到所有的头文件路径
INCLUDE := $(shell find ./ -name "*.h")
# dir : 取目录函数
DIR_INC = $(addprefix -I,$(dir $(INCLUDE)))
#定义中间文件路径
DIR_OBJ = ./obj
#定义目标文件路径
DIR_BIN = .
#将.c文件替换成.rel文件
#在编译的时候,直接将目标文件的后缀替换,这样在以后编译文件时,可以更方便的写之后的Makefile
OBJ = $(patsubst %.c,%.rel,${SRC})
# $@代表规则中的目标文件名
main:$(DIR_OBJ) ${OBJ}
#编译链接*.o
sdcc $(addprefix $(DIR_OBJ)/,$(notdir ${OBJ})) -o $(DIR_OBJ)/main.ihx
#将ihx转换为hex格式
packihx $(DIR_OBJ)/main.ihx > $(DIR_OBJ)/main.hex
#将hex格式转换为bin
objcopy -I ihex -O binary $(DIR_OBJ)/main.hex $(DIR_BIN)/main.bin
$(DIR_OBJ):
mkdir $(DIR_OBJ)
echo $(DIR_INC)
echo $(SRC)
echo $(OBJ)
#将*.c编译但不连接
%.rel:%.c
sdcc -c $< $(DIR_INC) -o $(addprefix $(DIR_OBJ)/,$(notdir $@))
#清理编译产物
clean:
rm -rf ./obj ./main.bin
- Makefile的编写方法
- MakeFile的编写指导
- MakeFile的编写指导
- 编写Makefile的心得
- Makefile的编写
- Makefile文件的编写
- makefile的编写
- 编写vxworks的MakeFile
- Makefile的编写指导
- 编写简单的makefile
- Makefile的编写
- makefile文件的编写
- [转]Makefile的编写
- Makefile的编写
- Makefile的编写
- MakeFile的编写
- Makefile文件的编写
- Makefile的编写详解
- 我的JAVA初学之路----List集合和Set集合(上)
- 字符识别OCR研究一(模板匹配&BP神经网络训练)
- Struts2【三】
- live555 之改造成双向通信
- 新手必看,老鸟绕道–LAMP简易安装
- makefile的编写
- 从留言板开始做网站(一)——准备工作
- 软件开发流程、测试流程及常用工具
- API
- OkHttp使用
- 总结4
- php中的sprintf()函数的format格式字符串
- Error:warning: Ignoring InnerClasses attribute for an anonymous inner class
- 2016 四川省赛 A.Nearest Neighbor Search