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规则

      1. INCLUDE_DIR = ./LED
      2. main:main.c LED.c
      3.    #将*.c编译但不连接
      4.   sdcc -c LED.c -I $(INCLUDE_DIR)
      5.   sdcc -c main.c
      6.    #编译链接*.o
      7.   sdcc  main.rel LED.rel
      8.    #将ihx转换为hex格式
      9.   packihx main.ihx > main.hex
      10.    #将hex格式转换为bin
      11.   objcopy -I ihex -O binary main.hex main.bin
      12. #清理编译产物
      13. clean:
      14.   rm -rf *.ihx *.bin *.lst *.rel *.sym  *.rst *.lk *.asm *.map *.mcu8051ide~ *.mem *.hex
  • 使用自动化变量

      1. #添加依赖头文件路径
      2. INCLUDE_DIR = ./LED
      3. #最终生成的目标名字都为main.*
      4. obj= LED.rel  main.rel
      5. #$^  :  规则的所有依赖文件列表
      6. #生成main,bin文件
      7. main:main.hex
      8.    #将hex格式转换为bin
      9. objcopy -I ihex -O binary main.hex main.bin
      10. #生成main.hex
      11. main.hex:main.ihx
      12. packihx main.ihx > main.hex
      13. #$^  :   规则的所有依赖文件列表
      14. main.ihx:$(obj)
      15. sdcc  $^ -o main.ihx
      16. #$<  :   规则的第一个依赖文件名
      17. #$@  :   代表规则中的目标文件名
      18. %.rel:%.c
      19. sdcc -c $< -I $(INCLUDE_DIR) -o $@
      20. #清理编译产物
      21. .PHONY:clean
      22. clean:
      23. rm -rf *.ihx *.bin *.lst *.rel *.sym  *.rst *.lk *.asm *.map *.mcu8051ide~ *.mem *.hex
  • 输出的文件在obj中,bin文件在当前目录下,源码放在当前目录,秩序在source添加自己的.c文件,在INCLUDE_DIR添加头文件路径

    1. INCLUDE_DIR = ./
    2. source = LED.c main.c
    3. #不能有空格,将.c结尾的文件名转换为.rel结尾的文件名列表
    4. objs = $(source:.c=.rel)
    5. #在每一个文件名前加上路径./objdir/
    6. objs := $(addprefix ./objdir/,$(objs))
    7. main: objdir $(objs)
    8. #将*.c编译但不连接
    9. #编译链接*.o
    10. sdcc  ./objdir/main.rel ./objdir/LED.rel -o ./objdir/main.ihx
    11. #将ihx转换为hex格式
    12. packihx ./objdir/main.ihx > ./objdir/main.hex
    13. #将hex格式转换为bin
    14. objcopy -I ihex -O binary ./objdir/main.hex main.bin
    15. objdir:
    16. mkdir objdir
    17. ./objdir/%.rel:%.c
    18. sdcc -c $< -I $(INCLUDE_DIR) -o $@
    19. #清理编译产物
    20. clean:
    21.   rm -rf ./objdir main.bin
  • 自动扫描当前文件中c文件,并编译链接

      1. ################################################################################
      2. #添加自己的头文件位置
      3. INCLUDE_DIR = ./
      4. #    自动扫描当前文件中的c文件
      5. source = $(wildcard ./*.c)
      6. ################################################################################
      7. #不能有空格,将.c结尾的文件名转换为.rel结尾的文件名列表
      8. objs = $(source:.c=.rel)
      9. #在每一个文件名前加上路径./objdir/
      10. objs := $(addprefix ./objdir/,$(objs))
      11. main: objdir $(objs)
      12. #编译链接*.o
      13. sdcc  $(objs)  -o ./objdir/main.ihx
      14. #将ihx转换为hex格式
      15. packihx ./objdir/main.ihx > ./objdir/main.hex
      16. #将hex格式转换为bin
      17. objcopy -I ihex -O binary ./objdir/main.hex main.bin
      18. objdir:
      19. mkdir objdir
      20. #将*.c编译但不连接
      21. ./objdir/%.rel:%.c
      22. sdcc -c $< -I $(INCLUDE_DIR) -o $@
      23. #清理编译产物
      24. clean:
      25.   rm -rf ./objdir main.bin
  • 源文件定义在DIR_SRC,头文件定义在DIR_INC,中间文件定义在DIR_OBJ,目标文件生成目录DIR_BIN

    • 

      1. #定义头文件路径
      2. DIR_INC = ./include
      3. #定义源文件路径
      4. DIR_SRC = ./src
      5. #定义中间文件路径
      6. DIR_OBJ = ./obj
      7. #定义目标文件路径
      8. DIR_BIN = .
      9. # wildcard : 扩展通配符
      10. # notdir : 去除路径
      11. # patsubst :替换通配符
      12. #搜索制定目录所有文件
      13. SRC = $(wildcard ${DIR_SRC}/*.c)
      14. #将.c文件替换成.rel文件
      15. OBJ = $(patsubst %.c,${DIR_OBJ}/%.rel,$(notdir ${SRC}))
      16. # $@代表规则中的目标文件名
      17. main:$(DIR_OBJ) ${OBJ}
      18. #编译链接*.o
      19. sdcc  $(OBJ)  -o $(DIR_OBJ)/main.ihx
      20. #将ihx转换为hex格式
      21. packihx $(DIR_OBJ)/main.ihx > $(DIR_OBJ)/main.hex
      22. #将hex格式转换为bin
      23. objcopy -I ihex -O binary $(DIR_OBJ)/main.hex $(DIR_BIN)/main.bin
      24. $(DIR_OBJ):
      25. mkdir $(DIR_OBJ)
      26. echo $(SRC)
      27. echo $(OBJ)
      28. #将*.c编译但不连接
      29. $(DIR_OBJ)/%.rel:${DIR_SRC}/%.c
      30. sdcc -c $< -I $(DIR_INC) -o $@
      31. #清理编译产物
      32. clean:
      33. rm -rf $(DIR_OBJ) main.bin
  • 多级文件的Makefile编写

    • 执行shell命令,将结果返回(返回所有头文件,包括路径)

      • INCLUDE := $(shell find ./ -name "*.h")

      1. #找到所有的源文件
      2. SRC := $(shell find ./ -name "*.c")
      3. #找到所有的头文件路径
      4. INCLUDE := $(shell find ./ -name "*.h")
      5. # dir : 取目录函数
      6. DIR_INC = $(addprefix -I,$(dir $(INCLUDE)))
      7. #定义中间文件路径
      8. DIR_OBJ = ./obj
      9. #定义目标文件路径
      10. DIR_BIN = .
      11. #将.c文件替换成.rel文件
      12. #在编译的时候,直接将目标文件的后缀替换,这样在以后编译文件时,可以更方便的写之后的Makefile
      13. OBJ = $(patsubst %.c,%.rel,${SRC})
      14. # $@代表规则中的目标文件名
      15. main:$(DIR_OBJ) ${OBJ}
      16. #编译链接*.o
      17. sdcc  $(addprefix $(DIR_OBJ)/,$(notdir ${OBJ}))  -o $(DIR_OBJ)/main.ihx
      18. #将ihx转换为hex格式
      19. packihx $(DIR_OBJ)/main.ihx > $(DIR_OBJ)/main.hex
      20. #将hex格式转换为bin
      21. objcopy -I ihex -O binary $(DIR_OBJ)/main.hex $(DIR_BIN)/main.bin
      22. $(DIR_OBJ):
      23. mkdir $(DIR_OBJ)
      24. echo $(DIR_INC)
      25. echo $(SRC)
      26. echo $(OBJ)
      27. #将*.c编译但不连接
      28. %.rel:%.c
      29. sdcc -c $< $(DIR_INC) -o $(addprefix $(DIR_OBJ)/,$(notdir $@))
      30. #清理编译产物
      31. clean:
      32. rm -rf ./obj ./main.bin


      1. #找到所有的源文件
      2. SRC := $(shell find ./ -name "*.c")
      3. #找到所有的头文件路径
      4. INCLUDE := $(shell find ./ -name "*.h")
      5. # dir : 取目录函数
      6. DIR_INC = $(addprefix -I,$(dir $(INCLUDE)))
      7. #定义中间文件路径
      8. DIR_OBJ = ./obj
      9. #定义目标文件路径
      10. DIR_BIN = .
      11. #将.c文件替换成.rel文件
      12. OBJ = $(patsubst %.c,%.rel,${SRC})
      13. # $@代表规则中的目标文件名
      14. main:$(DIR_OBJ) ${OBJ}
      15. #编译链接*.o
      16. sdcc  ${OBJ}  -o $(DIR_OBJ)/main.ihx
      17. #将ihx转换为hex格式
      18. packihx $(DIR_OBJ)/main.ihx > $(DIR_OBJ)/main.hex
      19. #将hex格式转换为bin
      20. objcopy -I ihex -O binary $(DIR_OBJ)/main.hex $(DIR_BIN)/main.bin
      21. #将*.c编译但不连接
      22. %.rel:%.c
      23. sdcc -c $< $(DIR_INC) -o $@
      24. #清理编译产物
      25. clean:
      26. #查找文件,进行删除
      27. find  ./ -name "*.rel" -exec rm -rf {} \;
      28. find  ./ -name "*.lst" -exec rm -rf {} \;
      29. find  ./ -name "*.rst" -exec rm -rf {} \;
      30. find  ./ -name "*.sym" -exec rm -rf {} \;
      31. find  ./ -name "*.asm" -exec rm -rf {} \;
      32. rm $(DIR_BIN)/main.bin
      33. 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

        1. #自己添加要编译的文件,这样就不会因为编译没有用到的文件而浪费空间
        2. SRC := main.c ./TIMER/TIMER.c ./DS18B20/DS18B20.c ./LCD1602/LCD1602.c \
        3. ./UART/UART.c
        4. #找到所有的头文件路径
        5. INCLUDE := $(shell find ./ -name "*.h")
        6. # dir : 取目录函数
        7. DIR_INC = $(addprefix -I,$(dir $(INCLUDE)))
        8. #定义中间文件路径
        9. DIR_OBJ = ./obj
        10. #定义目标文件路径
        11. DIR_BIN = .
        12. #将.c文件替换成.rel文件
        13. #在编译的时候,直接将目标文件的后缀替换,这样在以后编译文件时,可以更方便的写之后的Makefile
        14. OBJ = $(patsubst %.c,%.rel,${SRC})
        15. # $@代表规则中的目标文件名
        16. main:$(DIR_OBJ) ${OBJ}
        17. #编译链接*.o
        18. sdcc $(addprefix $(DIR_OBJ)/,$(notdir ${OBJ})) -o $(DIR_OBJ)/main.ihx
        19. #将ihx转换为hex格式
        20. packihx $(DIR_OBJ)/main.ihx > $(DIR_OBJ)/main.hex
        21. #将hex格式转换为bin
        22. objcopy -I ihex -O binary $(DIR_OBJ)/main.hex $(DIR_BIN)/main.bin
        23. $(DIR_OBJ):
        24. mkdir $(DIR_OBJ)
        25. echo $(DIR_INC)
        26. echo $(SRC)
        27. echo $(OBJ)
        28. #将*.c编译但不连接
        29. %.rel:%.c
        30. sdcc -c $< $(DIR_INC) -o $(addprefix $(DIR_OBJ)/,$(notdir $@))
        31. #清理编译产物
        32. clean:
        33. rm -rf ./obj ./main.bin


0 0
原创粉丝点击