目标:

makefile中的变量可能是这样:

CPU = -mcpu=cortex-m4

# fpu
FPU = -mfpu=fpv4-sp-d16

# float-abi
FLOAT-ABI = -mfloat-abi=hard

# mcu
MCU = $(CPU) -mthumb $(FPU) $(FLOAT-ABI)

# macros for gcc
# AS defines
AS_DEFS =

# C defines
C_DEFS = -DUSE_HAL_DRIVER -DSTM32F407xx

如何打印出 C_DEFS 这个变量的值,MCU 这个变量的值???


首先来了解一些基本知识:

make(指的就是make.exe)是要操作makefile文件的,而操作makefile的时候,我们可以给它一些命令,更符合我们的操作方法。

make的命令行选项有如下:

(​ ​make-选项 - 知乎​ ​)

之前指定​ ​make​ ​​要查找的文件时,使用的​ ​-f​ ​​和​ ​--file=​ ​​吗?这是​ ​make​ ​工具的参数,下面看看常用的选项都有哪些:

  1. ​-b​ ​​或​ ​-m​ ​​,忽略其他版本​ ​make​ ​的兼容性。
  2. ​-B​ ​​或​ ​–-always-make​ ​, 重编译
  3. ​-C​ ​​或​ ​--directory=​ ​​,指定读取​ ​makefile​ ​的目录。
  4. ​--debug[=]​ ​​或​ ​-d​ ​​(​ ​--debug=a​ ​​),输出​ ​make​ ​的调试信息,有以下几种级别可选,默认输出最简单信息。
  • ​a​ ​--输出所有调试信息。
  • ​b​ ​--输出简单调试信息。
  • ​v​ ​​--输出​ ​b​ ​级之上的信息。
  • ​i​ ​​--输出隐式规则(​ ​implicit​ ​)。
  • ​j​ ​--输出执行规则中命令的详细信息。
  • ​m​ ​​--输出操作​ ​makefile​ ​时的信息
  1. ​-e​ ​​或​ ​--environment-overrides​ ​​,指明环境变量中的值覆盖​ ​makefile​ ​中的值
  2. ​-f​ ​​或​ ​--file=​ ​​或​ ​--makefile=​ ​, 指定需要执行的 makefile ​。
  3. ​-h​ ​​或​ ​--help​ ​,显示帮助信息。
  4. ​-i​ ​​或​ ​--ignore-errors​ ​,执行时忽略错误。
  5. ​-I​ ​​或​ ​--include-dir=​ ​​,指定包含​ ​makefile​ ​的搜索目录。
  6. ​-j​ ​​或​ ​--jobs[=]​ ​,指定同时运行命令的数目。默认尽可能多的运行
  7. ​-k​ ​​或​ ​--keep-going​ ​,出错也不停止运行。
  8. ​-l​ ​​或​ ​--load-average[=]​ ​​或​ ​--max-load[=]​ ​​,指定​ ​make​ ​运行的负载。
  9. ​-n​ ​​或​ ​--just-print​ ​​或​ ​--dry-run​ ​​或​ ​--recon​ ​,仅输出执行命令序列,但 并不实际执行
  10. ​-o​ ​​或​ ​--old-file=​ ​​或​ ​--assume-old=​ ​,指定不重新生成的目标。
  11. ​-p​ ​​或​ ​--print-data-base​ ​​,输出​ make的内部的 所有数据 ,包括所有预定义的规则和变量。 该选项输出的信息太多了,而且没法缩减的
  12. ​-q​ ​​或​ ​--question​ ​,仅检查目标是否要更新,如果是0说明要更新,2说明有错误
  13. ​-r​ ​​或​ ​--no-builtin-variabes​ ​,禁止使用变量上的隐式规则。
  14. ​-s​ ​​或​ ​--silent​ ​​或​ ​--quiet​ ​,在运行命令时不输出命令的输出
  15. ​-S​ ​​或​ ​--no-keep-going​ ​​或​ ​--stop​ ​​,取消​ ​-k​ ​​选项,一般用在​ ​make​ ​的选项是继承来的,而你又不想要。
  16. ​-t​ ​​或​ ​--toch​ ​,把目标修改日期变为最新的,也就是阻止生成目标。
  17. ​-v​ ​​或​ ​--version​ ​​,输出​ ​make​ ​版本。
  18. ​-w​ ​​或​ ​--print-directory​ ​​,跟踪​ ​makefile​ ​。
  19. ​--no-print-directory​ ​​,禁止​ ​-w​ ​选项。
  20. ​-W​ ​​或​ ​--what-if=​ ​​或​ ​--new-file​ ​​或​ ​--assume-file=​ ​,假定目标需要更新。
  21. ​--warn-undefined-variables​ ​​,只要​ ​make​ ​发现未定义变量,那么给出警告。

打印变量的方法1

我们从这些选项可以看出, 没有可以打印出makefile中我们定义的变量的值的选项。即使 -p 可以,但是打印出的文本信息太多了,一次性输出这么多信息,并非是我们所希望的。​​Makefile(make)之(3)输出变量值_Once_day的博客-CSDN博客​​

从博客可知 ​ ​shell - 保存/导出make环境中的所有变量? - Thinbug​

应该这样做,在makefile中写个伪目标showAllVar,伪目标的执行内容是如下之一都行:(​​Makefile 打印变量的值_墨痕诉清风的博客-CSDN博客​​)

  • @echo "$(var)" 来输出 变量var的值
  • $(info $(TARGET_DEVICE) )
  • $(warning  $(XXX))   打印变量的值
  • $(error "error: this will stop the compile")

举例如下:(用echo举例)

然后用

make -n showAllVar

命令就能打出来啦

CPU = -mcpu=cortex-m4

# fpu
FPU = -mfpu=fpv4-sp-d16

# float-abi
FLOAT-ABI = -mfloat-abi=hard

# mcu
MCU = $(CPU) -mthumb $(FPU) $(FLOAT-ABI)

# macros for gcc
# AS defines
AS_DEFS =

# C defines
C_DEFS = -DUSE_HAL_DRIVER -DSTM32F407xx

# 这样来打印出我们设置的这些变量的值
showAllVar:
@echo "$(CPU)"
@echo "$(FLOAT-ABI)"
@echo "$(MCU )"
@echo "$(AS_DEFS )"
@echo "$(C_DEFS )"

为了省去手写这些打印变量语句,可以直接用这个博客提到的方法​​Makefile(make)之(3)输出变量值_Once_day的博客-CSDN博客​​

获得变量的值的方法2

makefile文件内容还是比较简单的,我们可以自己 直接写个简单的读取函数 ,来解析得到我们指定变量的值的(这个方法简单高效(原理就是一行行分析,自己写字符串匹配然后提取), 不用增加makefile里面任何内容 )。这个对于一般变量是没问题的,当这个变量是嵌套变量,或者考虑到了赋值 =、:= 等符号特性的时候,自己写的这个读取函数可能就费劲了。所以简单应用场合,可以用这个。

方法总结:

方法1:需要在makefile中加入打印语句,而且需要启动一个make进程。能应对复杂应用场合。但是,在 makefile文件内容里面 增加一个变量的时候,更新一个变量的值时候,make就做不了的,因为它只读取和执行这个文件里面的内容。make只可以  make EXTRAVAR="-Ddef4 -Ddef5" (带空格的标记必须用引号引起来)这样的方式来增加一个变量,但是makefile这个文件里的实际内容是不会变的(也就是文件没有被修改)。
​​ ​如何在向变量追加一个值列表的同时启动make? - 问答 - 腾讯云开发者社区-腾讯云​

注:​ ​make FOO+=​ ​​执行与​ ​make FOO=​ ​相同的操作。它不会追加,它会覆盖FOO这个变量。要想增加,可以这样:

VAR = -Ddef1 -Ddef2 -Ddef3 $( EXTRAVAR )

make EXTRAVAR ="-Ddef4 -Ddef5"              #就实现了向VAR变量中增加两个值 -Ddef4 -Ddef5

方法2:直接函数读取,不用修改makefile任何内容,但是复杂变量就难以解析了。可以自己方便的增加一个变量进去,更新变量值啥的,都能做到(也就是自己直接 修改makefile文件里面的内容了的 )。简单应用场合可以的。

所以,具体用方法1还是2,看自己的应用场景吧。我是因为用makefile来直接存储项目的编译等参数,所以需要实际修改makefile文件的内容,所以只能是自己写解析函数了的。(还需要仅仅读复杂变量的值的话,可能就再用一下方法1了)