啰嗦:越会一件事情,就会忘了不会一件事情的感觉。前段时间在微信上看到这句话,深以为然,这就是为什么很多时候懂的人觉得自己讲的很清楚了,但是不懂的人却觉得并没有讲的清楚明了,简单易懂。以下把自己学习理解的过程记录下来,欢迎大神指点。
1.PX4的makefile当中用到的Makefile语法
本小节给出Makefile文件中使用到部分语法的简单说明,如果想要完全理解、读懂、甚至编写Makefile,需要仔细阅读《GNU Makefile 中文手册》。
:= --直接式变量展开,引用的变量或者函数都会被其定义值替换,如果:= 右端为空,可能是赋值了一个空格;
= 及 define --递归式变量展开,在引用处只是文本替换,在使用时才会展开;
$ --取变量值操作,可以嵌套使用,例如$($(X))。同时可以用于调用内嵌函数:$(FCTION ARGUMENTS);
?= --条件赋值,只有变量尚未被赋值的情况下,才能将?=后边的值赋给变量;
patsubst --模式替换,引用格式:$(patsubst A,B,(VAR)), VAR表示变量,下同,例如:$(patsubst %.c %.o, a.c,b.c);
wildcard --通用符,引用格式如:$(wildcard *.c),当前路径下的所有.c结尾的文件;
+= --追加赋值,VAR定义时给一个基本值,+=就在原来的变量基础上增加一 个赋值,注意不是覆盖;
% --模式字符,例如:%.c 表示后缀为.c模式的文件;
ifeq、ifneq --条件判断关键字;
ifdef、ifndef --条件判断关键字;
// + --命令行前使用+,表示;
subset --字符串替换,例如:$(subst,e,E,feet),结果为:fEEt;
filter --过滤函数,例如:$(filter %.c %.s, $(VAR)),返回VAR中所有后缀为.c,.s的文件;
sort --将字符串升序排列,并去掉重复单词;
word --取单词函数,$(word 1, text),取text的第1个单词;
wordlist --取字符串函数,$(word 1,5, text)表示取text的第1个到第5个单词字串;
words --统计字符串中单词数目;
firstword --取字符串的第一个单词,lastword同理取最后一个单词;
dir --取目录,包含指定文件的路径目录;
basename --取前缀函数,例如 $(basename src/foo.c),返回值为src/foo;
foreach --循环执行;
call --实现用户自定义函数的引用,$(call 函数,参数1,参数2,...);
@echo --在界面上输出build信息;
eval --比较复杂,没看懂,构造一个依赖关系链,其主要功能是根据参 数关系、结构,对它们进行替换展开;
shell --大致功能是将shell的参数放入shell环境中执行并返回结果;
error --$(error TEXT...),返回错误信息并退出执行;
MAKECMDGOALS
-(用户输入的)命令行参数;
$@ -表示规则的目标文件名,一般与改符号上文中的文件相对应,例如前边出现.C,可能默认就是对应的.O文件
2.PX4的makefile编译过程分析
本次编译过程基于Windows下的PX4Toolchain中的PX4 Console模式,方法参考PX4开发手册或网上教程,输入的指令为:
以下是对Makefile原文注解:
- ############################################################################
- #
- # Copyright (c) 2015 - 2017 PX4 Development Team. All rights reserved.
- #
- #部分版权、使用等的申明,此处删去
- #
- ############################################################################
- # Enforce the presence of the GIT repository
- #
- # We depend on our submodules, so we have to prevent attempts to
- # compile without it being present.
- # 强制性保证GIT repository存在,由于于PX4依赖于其子模块,
- # 所以必须防止在缺少子模块的情况下编译,从而有了此处的强制检查
- # $(wildcard .git)用来获取工作路径下所有后缀为.git的文件,执行GIT检查
- # ifeq...endif为条件判断
- ifeq ($(wildcard .git),)
- $(error YOU HAVE TO USE GIT TO DOWNLOAD THIS REPOSITORY. ABORTING.)
- endif
- # Help
- # --------------------------------------------------------------------
- # Don't be afraid of this makefile, it is just passing
- # arguments to cmake to allow us to keep the wiki pages etc.
- # that describe how to build the px4 firmware
- # the same even when using cmake instead of make.
- # 这个Makefile主要是讲怎么传递参数,怎么编译px4固件,同时使用make和cmake是一样的
- # Example usage:三种使用方法示例
- #
- # make px4fmu-v2_default (builds)
- # make px4fmu-v2_default upload (builds and uploads)
- # make px4fmu-v2_default test (builds and tests)
- #
- # This tells cmake to build the nuttx px4fmu-v2 default config in the
- # directory build/nuttx_px4fmu-v2_default and then call make
- # in that directory with the target upload.
- # 以上的命令告诉cmake使用build/nuttx_px4fmu-v2_default的默认配置来build nuttx
- # px4fmu,然后调用该路径下的make来上传target(编译好的文件)
- # 明确设置默认的build目标,编译目标为all,编译规则为posix_sitl_default,如果make不指定编译
- # 目标就会编译默认目标,此处输出的编译目标是px4fmu-v2_default
- all: posix_sitl_default # (默认build就是这个)
- # Parsing 解析
- # --------------------------------------------------------------------
- # assume 1st argument passed is the main target, the
- # rest are arguments to pass to the makefile generated
- # by cmake in the subdirectory
- # 假设第传递的第一个参数是主目标,余下的参数是传输给子路径下的cmake产生的makefile的
- # MAKECMDGOALS 就是输出的命令行参数px4fmu-v2_default
- # FIRST_ARG 变量值就是px4fmu
- FIRST_ARG := $(firstword$(MAKECMDGOALS))
- # ARGS的变量值就是default
- ARGS := $(