Ardupilot编译流程分析

2023-05-16

▉<=2=>▉---------------------------------------------------------------->>>>>>
编译流程分析
▉<=2=>▉---------------------------------------------------------------->>>>>>
<1>.在ardupilot/ArduCopter/键入:make px4-v2
A. 率先执行ardupilot/ArduCopter/Makefile 只有一句,好尴尬
include ../mk/apm.mk
B. 查看apm.mk 如下:
# find the mk/ directory, which is where this makefile fragment
# lives. (patsubst strips the trailing slash.)
#获取宿主系统的名称(linux)
SYSTYPE := $(shell uname)  


ifneq ($(findstring CYGWIN, $(SYSTYPE)),) 
MK_DIR := $(shell cygpath -m ../mk)
else
#$(patsubst PATTERN, REPLACEMENT, TEXT)
#搜索TEXT中的以空格分开的单词,将符合模式pattern替换为
#replacement,参数pattern可以使用模式通配符%,来代表一个单词
#中的若干字符,如果参数replacement中也包含一个%,那么replacemnt中的
#%将是pattern中的那个%所代表的字符串
#这里相当于,去掉MAKEFILE_LIST中的/
#$(dir NAMES)
#从文件名序列names中取出各个文件名的目录部分,即包含文件名中的最后
# /(包括斜线)之前的部分,这里应该是mk
#make 程序在读取多个 makefile 文件时,包括由环境变量“ MAKEFILES”指定、
#命令行指定、当前工作下的默认的以及使用指示符“include”指定包含的,在对这些文
#件进行解析执行之前make读取的文件名将会被自动依次追加到变量
#“ MAKEFILE_LIST”的定义域中。
#这样我们就可以通过测试此变量的最后一个字来获取当前 make 程序正在处理的
#makefile 文件名。具体地说就是在一个 makefile 文件中如果使用指示符“include”包
#含另外一个文件之后,变量“ MAKEFILE_LIST”的最后一个字只可能是指示符“ include”
#指定所要包含的那个文件的名字。
MK_DIR := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST))))
endif
#包含mk/environ.mk
include $(MK_DIR)/environ.mk


# short-circuit build for the configure target
#make 在执行时设置一个特殊变量“ MAKECMDGOALS”,此变量记录了命令行
#参数指定的终极目标列表,没有通过参数指定终极目标时此变量为空。
#此处为px4-v2
ifeq ($(MAKECMDGOALS), configure)
include $(MK_DIR)/configure.mk
else
# short-circuit build for the help target
include $(MK_DIR)/help.mk


# common makefile components
include $(MK_DIR)/targets.mk
include $(MK_DIR)/sketch_sources.mk


ifneq ($(MAKECMDGOALS), clean)
# board specific includes
ifeq ($(HAL_BOARD),HAL_BOARD_SITL)
include $(MK_DIR)/board_native.mk
endif


ifeq ($(HAL_BOARD),HAL_BOARD_LINUX)
include $(MK_DIR)/board_linux.mk
endif


ifeq ($(HAL_BOARD),HAL_BOARD_PX4)
include $(MK_DIR)/board_px4.mk
endif


ifeq ($(HAL_BOARD),HAL_BOARD_VRBRAIN)
include $(MK_DIR)/board_vrbrain.mk
endif


ifeq ($(HAL_BOARD),HAL_BOARD_QURT)
include $(MK_DIR)/board_qurt.mk
endif
endif
endif
综上:包含的mk有:
ardupilot/ArduCopter/Makefile --> 
../mk/apm.mk -->
a. environ.mk
# find key paths and system type
# Save the system type for later use.

SYSTYPE := $(shell uname)


GIT_VERSION ?= $(shell git rev-parse HEAD | cut -c1-8)
EXTRAFLAGS += -DGIT_VERSION="\"$(GIT_VERSION)\""


# Add missing parts from libc and libstdc++ for all boards
EXTRAFLAGS += -I$(SKETCHBOOK)/libraries/AP_Common/missing


# force LANG to C so awk works sanely(稳健地) on MacOS
export LANG=C


#
# Locate the sketch sources based on the initial Makefile's path
# 取诸makefile列表中的第一个makefile名字的路径
# SRCROOT = ....../ArduCopter/
SRCROOT := $(realpath $(dir $(firstword $(MAKEFILE_LIST))))
ifneq ($(findstring CYGWIN, $(SYSTYPE)),)
 # Workaround a $(realpath ) bug on cygwin
 ifeq ($(SRCROOT),)
SRCROOT := $(shell cygpath -m ${CURDIR})
$(warning your realpath function is not working)
$(warning > setting SRCROOT to $(SRCROOT))
 endif
endif


#
# We need to know the location of the sketchbook.  If it hasn't been overridden,
# try the parent of the current directory.  If there is no libraries directory
# there, assume that we are in a library's examples directory and try backing up
# further.
#
ifeq ($(SKETCHBOOK),)
 SKETCHBOOK := $(shell cd $(SRCROOT)/.. && pwd)
 ifeq ($(wildcard $(SKETCHBOOK)/libraries),)
$(error ERROR: cannot determine sketchbook location - please specify on the commandline with SKETCHBOOK=<path>)
 endif
else
 ifeq ($(wildcard $(SKETCHBOOK)/libraries),)
$(warning WARNING: sketchbook directory $(SKETCHBOOK) contains no libraries)
 endif
endif
#没这货
ifneq ($(findstring CYGWIN, $(SYSTYPE)),)
# Convert cygwin path into a windows normal path
SKETCHBOOK := $(shell cygpath ${SKETCHBOOK})
endif
   #没这货
ifneq ($(wildcard $(SKETCHBOOK)/config.mk),)
$(info Reading $(SKETCHBOOK)/config.mk)
include $(SKETCHBOOK)/config.mk
endif
#没这货
ifneq ($(wildcard $(SKETCHBOOK)/developer.mk),)
$(info Reading $(SKETCHBOOK)/developer.mk)
include $(SKETCHBOOK)/developer.mk
endif


#
# Work out the sketch name from the name of the source directory.
#
#$(lastword text) 取字符串text的末尾单词:
#$(subst from, to, text)text中的from替换为to
#SKETCH: ArduCopter
SKETCH := $(lastword $(subst /, ,$(SRCROOT)))
# Workaround a $(lastword ) bug on cygwin
ifeq ($(SKETCH),)
WORDLIST:= $(subst /, ,$(SRCROOT))
#$(word n, text)
#取字符串text中的第n个单词:
#$(words text)
#统计单词个数,不是字符的个数哦亲。
SKETCH := $(word $(words $(WORDLIST)),$(WORDLIST))
endif


#
# Work out where we are going to be building things
#
TMPDIR ?= /tmp
#$(findstring FIND, IN)
#在IN中查找字符串FIND
#因为传递的 px4-v2
#故而:此处成立
ifneq ($(findstring px4, $(MAKECMDGOALS)),)
# when building px4 we need all sources to be inside the sketchbook directory
# as the NuttX build system relies on it
BUILDROOT := $(SKETCHBOOK)/Build.$(SKETCH) #包含编译路径 ArduCopter/Build.ArduCopter
endif
#忽略一些不成立的指令
......
#

ifneq ($(findstring mavlink1, $(MAKECMDGOALS)),) #不成立
EXTRAFLAGS += -DMAVLINK_PROTOCOL_VERSION=1
MAVLINK_SUBDIR=v1.0
MAVLINK_WIRE_PROTOCOL=1.0
else #成立,这里只有2.0的代码
EXTRAFLAGS += -DMAVLINK_PROTOCOL_VERSION=2
MAVLINK_SUBDIR=v2.0
MAVLINK_WIRE_PROTOCOL=2.0
endif
#??????
ifneq ($(APPDIR),)
# this is a recusive PX4 build
HAL_BOARD = HAL_BOARD_PX4
endif
#成立:HAL_BOARD = HAL_BOARD_PX4
# handle target based overrides for board type
ifneq ($(findstring px4, $(MAKECMDGOALS)),)
HAL_BOARD = HAL_BOARD_PX4
endif
#后面的都没有配置故而,忽略
......
......
#至结束
endif

b. help.mk
输出一些提示信息给编译者.不参与实际工程编译
c. targets.mk 
一些目标板的配置
default: help
# convenient targets for our supported boards
sitl: HAL_BOARD = HAL_BOARD_SITL
sitl: TOOLCHAIN = NATIVE
sitl: all


sitl-arm: HAL_BOARD = HAL_BOARD_SITL
sitl-arm: TOOLCHAIN = RPI
sitl-arm: all


apm1 apm1-1280 apm2 apm2beta:
$(error $@ is deprecated (不赞成)on master branch; use master-AVR)


flymaple flymaple-hil:
$(error $@ is deprecated on master branch; use master-AVR)


linux: HAL_BOARD = HAL_BOARD_LINUX
linux: TOOLCHAIN = NATIVE
linux: BUILDSYS_DEPRECATED = 1
linux: all


erleboard: HAL_BOARD = HAL_BOARD_LINUX
erleboard: TOOLCHAIN = BBONE
erleboard: BUILDSYS_DEPRECATED = 1
erleboard: all


zynq: HAL_BOARD = HAL_BOARD_LINUX
zynq: TOOLCHAIN = ZYNQ
zynq: all
zynq-hil: EXTRAFLAGS += "-DHILMODE=HIL_MODE_ATTITUDE -DHIL_MODE=HIL_MODE_SENSORS "
zynq-hil : zynq


pxf: HAL_BOARD = HAL_BOARD_LINUX
pxf: TOOLCHAIN = BBONE
pxf: BUILDSYS_DEPRECATED = 1
pxf: all


bebop: HAL_BOARD = HAL_BOARD_LINUX
bebop: TOOLCHAIN = BBONE
bebop: LDFLAGS += "-static"
bebop: BUILDSYS_DEPRECATED = 1
bebop: all


minlure: HAL_BOARD = HAL_BOARD_LINUX
minlure: TOOLCHAIN = NATIVE
minlure: BUILDSYS_DEPRECATED = 1
minlure: all


navio: HAL_BOARD = HAL_BOARD_LINUX
navio: TOOLCHAIN = RPI
navio: BUILDSYS_DEPRECATED = 1
navio: all


navio2: HAL_BOARD = HAL_BOARD_LINUX
navio2: TOOLCHAIN = RPI
navio2: BUILDSYS_DEPRECATED = 1
navio2: all


raspilot: HAL_BOARD = HAL_BOARD_LINUX
raspilot: TOOLCHAIN = RPI
raspilot: BUILDSYS_DEPRECATED = 1
raspilot: all


erlebrain2: HAL_BOARD = HAL_BOARD_LINUX
erlebrain2: TOOLCHAIN = RPI
erlebrain2: BUILDSYS_DEPRECATED  = 1
erlebrain2: all


bbbmini: HAL_BOARD = HAL_BOARD_LINUX
bbbmini: TOOLCHAIN = BBONE
bbbmini: BUILDSYS_DEPRECATED  = 1
bbbmini: all


bhat: HAL_BOARD = HAL_BOARD_LINUX
bhat: TOOLCHAIN = RPI
bhat: BUILDSYS_DEPRECATED  = 1
bhat: all


pxfmini: HAL_BOARD = HAL_BOARD_LINUX
pxfmini: TOOLCHAIN = RPI
pxfmini: BUILDSYS_DEPRECATED  = 1
pxfmini: all


qflight: HAL_BOARD = HAL_BOARD_LINUX
qflight: TOOLCHAIN = QFLIGHT
qflight: all


empty: HAL_BOARD = HAL_BOARD_EMPTY
empty: TOOLCHAIN = AVR
empty: all


qurt: HAL_BOARD = HAL_BOARD_QURT
qurt: TOOLCHAIN = QURT
qurt: all


# cope with(对付,应付,处理,多指一些难题) HIL targets
%-hil: EXTRAFLAGS += "-DHIL_MODE=HIL_MODE_SENSORS "
%-hilsensors: EXTRAFLAGS += "-DHIL_MODE=HIL_MODE_SENSORS "


# cope with OBC(On-Board Controller 机载控制器) targets
%-obc: EXTRAFLAGS += "-DOBC_FAILSAFE=ENABLED "


# support debug build
%-debug: OPTFLAGS = -g -O0


# support address sanitiser(净化,消毒,审查)
%-asan: OPTFLAGS = -g -O0 -fsanitize=address -fno-omit-frame-pointer
%-asan: LDFLAGS += -fsanitize=address


# cope with -nologging
%-nologging: EXTRAFLAGS += "-DLOGGING_ENABLED=DISABLED "


# cope with(对付,应付,处理,多指一些难题) copter and hil targets
#机架frame类型:
FRAMES = quad tri hexa(6) y6 octa(8) octa-quad heli single coax(同轴) obc(On-Board Controller 机载控制器) nologging
#板子board种类:
#有我们喜欢的 px4-v2 *^_^*么么哒
BOARDS = apm1 apm2 apm2beta apm1-1280 px4 px4-v1 px4-v2 px4-v4 sitl flymaple linux erle pxf navio navio2 
raspilot bbbmini minlure erlebrain2 bhat qflight pxfmini
BOARDS += vrbrain
BOARDS += vrbrain-v51 vrbrain-v52 vrbrain-v54
BOARDS += vrcore-v10
BOARDS += vrubrain-v51 vrubrain-v52

#这里采用指示符“ define”定义一个多行的变量或者命令包,其定义体(“ define”和“ endef”之间的内容)
#会被完整的展开到 Makefile 中引用此变量的地方(包含定义体中的注释行)
#留意这里的临时变量$(1),$(2)用法, 相当于函数参数一般
define frame_template
$(1)-$(2) : EXTRAFLAGS += "-DFRAME_CONFIG=$(shell echo $(2) | tr a-z A-Z | sed s/-/_/g)_FRAME "
$(1)-$(2) : $(1)
$(1)-$(2)-hil : $(1)-$(2)
$(1)-$(2)-debug : $(1)-$(2)
$(1)-$(2)-mavlink1 : $(1)-$(2)
$(1)-$(2)-debug-mavlink1 : $(1)-$(2)
$(1)-$(2)-hilsensors : $(1)-$(2)
$(1)-$(2)-upload : $(1)-$(2)
$(1)-$(2)-upload : $(1)-upload
endef


define board_template
$(1)-hil : $(1)
$(1)-debug : $(1)
$(1)-mavlink1 : $(1)
$(1)-debug-mavlink1 : $(1)-debug
$(1)-asan : $(1)
$(1)-hilsensors : $(1)
endef
#$(foreach VAR,LIST,TEXT)
#这个函数的工作过程是这样的:如果需要(存在变量或者函数的引用),
#首先展开变量“ VAR”和“ LIST”的引用;而表达式“ TEXT”中的变量
#引用不展开。执行时把“ LIST”中使用空格分割的单词依次取出赋值给变量
#“ VAR”,然后执行“ TEXT”表达式。重复直到“ LIST”的最后一个单词(为
#空时结束)。“ TEXT”中的变量或者函数引用在执行时才被展开,因此如果在
#“ TEXT”中存在对“ VAR”的引用,那么“ VAR”的值在每一次展开式将会到
#的不同的值。
#这里就是,依次把$(BOARDS)中以空格分开的单词取出,赋值给board
#然后执行:$(findstring $(board), $(MAKECMDGOALS))
#执行结果是:USED_BOARDS := px4-v2
USED_BOARDS := $(foreach board,$(BOARDS), $(findstring $(board), $(MAKECMDGOALS)))
USED_FRAMES := $(foreach frame,$(FRAMES), $(findstring $(frame), $(MAKECMDGOALS)))
#$(warning $(USED_BOARDS))
#$(warning $(USED_FRAMES))
# generate targets of the form BOARD-FRAME and BOARD-FRAME-HIL
$(foreach board,$(USED_BOARDS),$(eval $(call board_template,$(board))))
$(foreach board,$(USED_BOARDS),$(foreach frame,$(USED_FRAMES),$(eval $(call frame_template,$(board),$(frame)))))


sitl-mount: EXTRAFLAGS += "-DMOUNT=ENABLED"
sitl-mount: sitl
#etags用于生成TAGS文件来提供emacs快速浏览C/C++源代码,它的最大作用就是能够快速跳转到函数定义、
#宏定义、数据结构定义、全局变量定义等。
.PHONY: etags
etags:
cd .. && etags -f ArduCopter/TAGS --lang=c++ $$(git ls-files ArduCopter libraries)
cd .. && etags -f ArduPlane/TAGS --lang=c++ $$(git ls-files ArduPlane libraries)
cd .. && etags -f APMrover2/TAGS --lang=c++ $$(git ls-files APMrover2 libraries)


clean:
@rm -fr $(BUILDROOT)
#包含了两个新mk下面分析:
include $(MK_DIR)/modules.mk
include $(MK_DIR)/mavgen.mk
①. mk/modules.mk 主要是一些提示和git支持
# git submodule support


define echowarning
@echo "WARNING: $1" >&2
endef


define echoallwarnings
$(call echowarning)
$(call echowarning)
$(call echowarning,make build system is deprecated for Linux boards)
$(call echowarning,new features are not going to be added anymore)
$(call echowarning,See README-WAF.md: https://github.com/ArduPilot/ardupilot/blob/master/README-WAF.md)
$(call echowarning)
$(call echowarning,The make build system will soon be removed)
$(call echowarning)
$(call echowarning)
endef


CHECK_MODULES:
$(if $(BUILDSYS_DEPRECATED),$(call echoallwarnings))
$(v)$(MK_DIR)/check_modules.sh


.PHONY: CHECK_MODULES
all: CHECK_MODULES


module-update:
git submodule update
②. mk/mavgen.mk 提供mavlink编译支持
# mavlink header generation
MAVLINK_DIR := $(SKETCHBOOK)/modules/mavlink/
MESSAGE_DEFINITIONS := $(SKETCHBOOK)/modules/mavlink/message_definitions/v1.0
MAVLINK_HEADERS := $(BUILDROOT)/libraries/GCS_MAVLink/include/mavlink/$(MAVLINK_SUBDIR)/ardupilotmega/mavlink.h 
  $(wildcard $(BUILDROOT)/libraries/GCS_MAVLink/include/mavlink/$(MAVLINK_SUBDIR)/,*.h) 
  $(wildcard $(BUILDROOT)/libraries/GCS_MAVLink/include/mavlink/$(MAVLINK_SUBDIR)/ardupilotmega,*.h)
MAVLINK_OUTPUT_DIR := $(BUILDROOT)/libraries/GCS_MAVLink/include/mavlink/$(MAVLINK_SUBDIR)


$(MAVLINK_HEADERS): $(MESSAGE_DEFINITIONS)/ardupilotmega.xml $(MESSAGE_DEFINITIONS)/common.xml
echo "Generating MAVLink headers..."
#goto mavlink module directory and run the most recent generator script
echo "Generating C code using mavgen.py located at" $(SKETCHBOOK)/modules/mavlink/
-PYTHONPATH=$(MAVLINK_DIR) python $(MAVLINK_DIR)/pymavlink/tools/mavgen.py --lang=C --wire-protocol=$(MAVLINK_WIRE_PROTOCOL) 
--output=$(MAVLINK_OUTPUT_DIR) $(MESSAGE_DEFINITIONS)/ardupilotmega.xml
d. sketch_sources.mk
#
# Sketch
#
# 通配符包含所有的.cpp 文件
SRCSUFFIXES = *.cpp
# ArduCopter/make.inc 文件
MAKE_INC=$(wildcard $(SRCROOT)/make.inc)
ifeq (,$(MAKE_INC))
$(error You must have a make.inc file to list library dependencies)
endif
# mk/make.inc 文件
GLOBAL_MAKE_INC=$(wildcard $(SKETCHBOOK)/mk/make.inc)
ifeq (,$(GLOBAL_MAKE_INC))
$(error You must have a make.inc in mk/ directory)
endif


# Sketch source files
# ../ArduCopter.cpp
# $(addprefix PREFIX,NAMES…)
# 函数名称:加前缀函数— addprefix。
# 函数功能:为“ NAMES…”中的每一个文件名添加前缀“ PREFIX”。参数“ NAMES…”
# 是空格分割的文件名序列,将“ SUFFIX”添加到此序列的每一个文件名之前。
# 返回值:以单空格分割的添加了前缀“ PREFIX”的文件名序列。
# 此处相当于添加绝对路径名。就是包含../ArduCopter/目录下的所有cpp文件
SKETCHSRCS     := $(wildcard $(addprefix $(SRCROOT)/,$(SRCSUFFIXES)))
SKETCHCPP      := $(SRCROOT)/$(SKETCH).cpp #../ArduCopter.cpp


# Sketch object files
SKETCHOBJS := $(subst $(SRCROOT),$(BUILDROOT),$(SKETCHSRCS))
# $(basename NAMES…)
# 函数名称:取前缀函数— basename。
# 函数功能:从文件名序列“ NAMES…”中取出各个文件名的前缀部分
# 前缀部分指的是文件名中最后一个点号之前的部分。
# 返回值:空格分割的文件名序列“ NAMES…”中各个文件的前缀序列。如果文件没有前缀,则返回空字串。
# 函数说明:如果“ NAMES…”中包含没有后缀的文件名,此文件名不改变。如果一
# 个文件名中存在多个点号,则返回值为此文件名的最后一个点号之前的文件名部分。
# 此处相当于:将.cpp 替换为.o 
SKETCHOBJS := $(addsuffix .o,$(basename $(SKETCHOBJS)))


# get list of libraries from make.inc
# 这些源码在ardupilot/libraries/下面
# 包含ArduCopter/make.inc 文件,里面是 LIBRARIES 变量(应用层AP)
include $(MAKE_INC)
# 包含mk/make.inc 文件,里面是 LIBRARIES 变量(应用层AP)
include $(GLOBAL_MAKE_INC)
LIBTOKENS := $(LIBRARIES) # LIBRARIES 变量赋值给LIBTOKENS




# HAL and board specific libraries are included here.
LIBTOKENS += \  # \换行
AP_HAL \
AP_HAL_Empty
# 无效
ifeq ($(HAL_BOARD),HAL_BOARD_APM1)
LIBTOKENS += \
AP_HAL_APM
endif
# 无效
ifeq ($(HAL_BOARD),HAL_BOARD_APM2)
LIBTOKENS += \
AP_HAL_APM
endif
# 无效
ifeq ($(HAL_BOARD),HAL_BOARD_SITL)
LIBTOKENS += \
AP_HAL_SITL \
SITL
endif
# 无效
ifeq ($(HAL_BOARD),HAL_BOARD_LINUX)
LIBTOKENS += \
AP_HAL_Linux
endif
# OK 
ifeq ($(HAL_BOARD),HAL_BOARD_PX4)
LIBTOKENS += \
AP_HAL_PX4
endif
# 无效
ifeq ($(HAL_BOARD),HAL_BOARD_VRBRAIN)
LIBTOKENS += \
AP_HAL_VRBRAIN
endif
# 无效
ifeq ($(HAL_BOARD),HAL_BOARD_QURT)
LIBTOKENS += \
AP_HAL_QURT
endif


#
# Find sketchbook libraries referenced by the sketch.
#
# Include paths for sketch libraries 
#
# 这里相当于为 $(LIBTOKENS) 的每个变量添加绝对路径
# 比如:/home/xxdk/pixHawk@xxdk/ardupilot/libraries/
SKETCHLIBS := $(wildcard $(addprefix $(SKETCHBOOK)/libraries/,$(LIBTOKENS)))
# $(notdir NAMES…)
# 函数名称:取文件名函数—— notdir。
# 函数功能:从文件名序列“ NAMES…”中取出非目录部分。目录部分是指最后一个
# 斜线(“ /”)(包括斜线)之前的部分。删除所有文件名中的目录部分,只保留非目录部分。
# 此处相当于只取:文件名里面的所有文件
SKETCHLIBNAMES := $(notdir $(SKETCHLIBS))
# ???
SKETCHLIBSRCDIRS := $(SKETCHLIBS) $(addsuffix /utility,$(SKETCHLIBS))
# $(suffix NAMES…)
# 函数名称:取后缀函数— suffix。
# 函数功能:从文件名序列“ NAMES…”中取出各个文件名的后缀。后缀是文件名中
# 最后一个以点“ .”开始的(包含点号)部分,如果文件名中不包含一个点号,则为空。
# 通配符包含所有的.cpp 文件
# 前面定义的:SRCSUFFIXES = *.cpp
# 此处类似给 *.cpp 添加绝对路径??????
SKETCHLIBSRCS := $(wildcard $(foreach suffix,$(SRCSUFFIXES),$(addsuffix /$(suffix),$(SKETCHLIBSRCDIRS))))
# 此处相当于.cpp -> .o
SKETCHLIBOBJS := $(addsuffix .o,$(basename $(subst $(SKETCHBOOK),$(BUILDROOT),$(SKETCHLIBSRCS))))
# SKETCHBOOK: sardupilot, BUILDROOT: Build.ArduCopter
SKETCHLIBINCLUDES := -I$(SKETCHBOOK)/libraries/ -I$(BUILDROOT)/libraries/ -I$(BUILDROOT)/libraries/GCS_MAVLink/
# $(subst FROM,TO,TEXT)
# 函数名称:字符串替换函数— subst。
# 函数功能:把字串“ TEXT”中的“ FROM”字符替换为“ TO”。
# 返回值:替换后的新字符串。
# 此处相当于:获取相对路径
SKETCHLIBSRCSRELATIVE := $(subst $(SKETCHBOOK)/,,$(SKETCHLIBSRCS))


ifeq ($(VERBOSE),)
v = @
else
v =
endif


FORCE:
# 生成的 make.flags 文件类容:
#//  BUILDROOT=/home/xxdk/pixHawk@xxdk/ardupilot/Build.ArduCopter 
#//  HAL_BOARD=HAL_BOARD_PX4 HAL_BOARD_SUBTYPE= TOOLCHAIN=NATIVE 
#//  EXTRAFLAGS=-DGIT_VERSION="c5f8d8a6" -I/home/xxdk/pixHawk@xxdk/ardupilot/libraries/AP_Common/missing
#//  -DMAVLINK_PROTOCOL_VERSION=2 -DNUTTX_GIT_VERSION="8c965992" -DPX4_GIT_VERSION="de6b667d" 
#//  -DUAVCAN=1 -D__STDC_FORMAT_MACROS -DHAVE_STD_NULLPTR_T=0 -DHAVE_ENDIAN_H=0 
#//  -DHAVE_BYTESWAP_H=0 -I/home/xxdk/pixHawk@xxdk/ardupilot/Build.ArduCopter/libraries/GCS_MAVLink/include/mavlink
$(BUILDROOT)/make.flags: FORCE
@mkdir -p $(BUILDROOT)
@echo "// BUILDROOT=$(BUILDROOT) HAL_BOARD=$(HAL_BOARD) HAL_BOARD_SUBTYPE=$(HAL_BOARD_SUBTYPE) TOOLCHAIN=$(TOOLCHAIN) EXTRAFLAGS=$(EXTRAFLAGS)" > 
$(BUILDROOT)/make.flags.new
@cmp $(BUILDROOT)/make.flags $(BUILDROOT)/make.flags.new > /dev/null 2>&1 || rm -f $(SRCROOT)/*.o
@cmp $(BUILDROOT)/make.flags $(BUILDROOT)/make.flags.new > /dev/null 2>&1 || mv $(BUILDROOT)/make.flags.new $(BUILDROOT)/make.flags
@rm -f $(BUILDROOT)/make.flags.new
@cat $(BUILDROOT)/make.flags


# common header for rules, prints what is being built
define RULEHDR
@echo %% $(subst $(BUILDROOT)/,,$@)
@mkdir -p $(dir $@)
endef
e. board_px4.mk
TOOLCHAIN = NATIVE
#指定交叉编译工具
include $(MK_DIR)/find_tools.mk
include $(MK_DIR)/px4_targets.mk
下面分析:
①. find_tools.mk
################################################################################
# Tools
# Decide where we are going to look for tools
# 无效
ifeq ($(SYSTYPE),Darwin)
# use the tools that come with Arduino
# use BWK awk
AWK =  awk
FIND_TOOL    =  $(firstword $(wildcard $(addsuffix /$(1),$(TOOLPATH))))
endif
# OK
ifeq ($(SYSTYPE),Linux)
# expect that tools are on the path
# $PATH 系统环境变量中的 :替换为空
# bash: /usr/games:.:/home/xxdk/bin:
# /home/xxdk/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:
# /sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/arm/gcc-arm-none-eabi-4_9-2015q3/bin:
# /home/xxdk/pixhawk/ardupilot/Tools/autotest:/home/xxdk/Qt5.7.0/5.7/gcc_64/bin:
# /home/xxdk/src@xxdk/JLink_Linux_V612_x86_64/:
TOOLPATH :=  $(subst :, ,$(PATH))
FIND_TOOL =  $(firstword $(wildcard $(addsuffix /$(1),$(TOOLPATH))))
endif
# 无效
ifeq ($(findstring CYGWIN, $(SYSTYPE)),CYGWIN)
TOOLPATH :=  $(subst :, ,$(PATH))
FIND_TOOL = $(firstword $(wildcard $(addsuffix /$(1).exe,$(TOOLPATH))))
endif
# 无效
ifeq ($(findstring MINGW, $(SYSTYPE)),MINGW)
# expect that tools are on the path
TOOLPATH :=  $(subst :, ,$(PATH))
FIND_TOOL    =  $(firstword $(wildcard $(addsuffix /$(1).exe,$(TOOLPATH))))
endif
# 本机编译器
NATIVE_CXX     :=  g++
NATIVE_CC      :=  gcc
NATIVE_AS      :=  gcc
NATIVE_AR      :=  ar
NATIVE_LD      :=  g++
NATIVE_GDB     :=  gdb
NATIVE_OBJCOPY :=  objcopy


AVARICE      :=  $(call FIND_TOOL,avarice)


# toolchains for beagleboneblack
BBONE_CXX     :=  arm-linux-gnueabihf-g++
BBONE_CC      :=  arm-linux-gnueabihf-gcc
BBONE_AS      :=  arm-linux-gnueabihf-gcc
BBONE_AR      :=  ar
BBONE_LD      :=  arm-linux-gnueabihf-g++
BBONE_GDB     :=  gdb
BBONE_OBJCOPY :=  objcopy


# toolchains for Raspberry Pi
RPI_CXX     :=  arm-linux-gnueabihf-g++
RPI_CC      :=  arm-linux-gnueabihf-gcc
RPI_AS      :=  arm-linux-gnueabihf-gcc
RPI_AR      :=  arm-linux-gnueabihf-ar
RPI_LD      :=  arm-linux-gnueabihf-g++
RPI_GDB     :=  arm-linux-gnueabihf-gdb
RPI_OBJCOPY :=  arm-linux-gnueabihf-obj


# toolchains for zynq
ZYNQ_CXX     :=  arm-xilinx-linux-gnueabi-g++
ZYNQ_CC      :=  arm-xilinx-linux-gnueabi-gcc
ZYNQ_AS      :=  arm-xilinx-linux-gnueabi-gcc
ZYNQ_AR      :=  arm-xilinx-linux-gnueabi-ar
ZYNQ_LD      :=  arm-xilinx-linux-gnueabi-g++
ZYNQ_GDB     :=  arm-xilinx-linux-gnueabi-gdb
ZYNQ_OBJCOPY :=  arm-xilinx-linux-gnueabi-objcopy


# enable ccache if installed
CCACHE :=  $(call FIND_TOOL,ccache)
export CCACHE


CXX = $(CCACHE) $($(TOOLCHAIN)_CXX)
CC = $(CCACHE) $($(TOOLCHAIN)_CC)
AS = $($(TOOLCHAIN)_AS)
AR = $($(TOOLCHAIN)_AR)
LD = $($(TOOLCHAIN)_LD)
GDB = $($(TOOLCHAIN)_GDB)
OBJCOPY = $($(TOOLCHAIN)_OBJCOPY)


ifeq ($(CXX),)
$(error ERROR: cannot find the compiler tools for $(TOOLCHAIN) anywhere on the path $(TOOLPATH))
endif


# Find awk
AWK ?= gawk
ifeq ($(shell which $(AWK)),)
$(error ERROR: cannot find $(AWK) - you may need to install GNU awk)
endif
②. px4_targets.mk
# PX4 build is via external build system
# 确认以下三个路径变量为空
ifneq ($(PX4_ROOT),)
$(error PX4_ROOT found in config.mk - Please see http://dev.ardupilot.org/wiki/git-submodules/)
endif


ifneq ($(NUTTX_SRC),)
$(error NUTTX_SRC found in config.mk - Please see http://dev.ardupilot.org/wiki/git-submodules/)
endif


ifneq ($(UAVCAN_DIR),)
$(error UAVCAN_DIR found in config.mk - Please see http://dev.ardupilot.org/wiki/git-submodules/)
endif


# these can be overridden in developer.mk
# “?=”只有此变量在之前没有赋值的情况下才会对这个变量进行赋值。
# ardupilot/modules/PX4Firmware
PX4FIRMWARE_DIRECTORY ?= $(SKETCHBOOK)/modules/PX4Firmware
PX4NUTTX_DIRECTORY ?= $(SKETCHBOOK)/modules/PX4NuttX
UAVCAN_DIRECTORY ?= $(SKETCHBOOK)/modules/uavcan
# 在使用“ :=”定义变量时,变量值中对其他量或者函数的引用在定义变量时被展开(对变量进行替换)
# 所以变量被定义后就是一个实际需要的文本串,其中不再包含任何变量的引用
PX4_ROOT := $(shell cd $(PX4FIRMWARE_DIRECTORY) && pwd) # ardupilot/modules/PX4Firmware
NUTTX_ROOT := $(shell cd $(PX4NUTTX_DIRECTORY) && pwd)  # ardupilot/modules/PX4NuttX
NUTTX_SRC := $(NUTTX_ROOT)/nuttx/ # ardupilot/modules/PX4NuttX/nuttx
UAVCAN_DIR=$(shell cd $(UAVCAN_DIRECTORY) && pwd)/ # ardupilot/modules/uavcan


NUTTX_GIT_VERSION ?= $(shell cd $(NUTTX_SRC) && git rev-parse HEAD | cut -c1-8) # 8c965992
PX4_GIT_VERSION   ?= $(shell cd $(PX4_ROOT) && git rev-parse HEAD | cut -c1-8)  # de6b667d
# 加入宏控制值
EXTRAFLAGS += -DNUTTX_GIT_VERSION="\"$(NUTTX_GIT_VERSION)\""
EXTRAFLAGS += -DPX4_GIT_VERSION="\"$(PX4_GIT_VERSION)\""
EXTRAFLAGS += -DUAVCAN=1
EXTRAFLAGS += -D__STDC_FORMAT_MACROS
# 加入宏控制值
# Add missing parts from libc and libstdc++
EXTRAFLAGS += -DHAVE_STD_NULLPTR_T=0
EXTRAFLAGS += -DHAVE_ENDIAN_H=0
EXTRAFLAGS += -DHAVE_BYTESWAP_H=0


EXTRAFLAGS += -I$(BUILDROOT)/libraries/GCS_MAVLink/include/mavlink


# we have different config files for V1 and V2
PX4_V1_CONFIG_FILE=$(MK_DIR)/PX4/config_px4fmu-v1_APM.mk
# 指定 px4-v2 配置ardupilot/mk/PX4/config_px4fmu-v2_APM.mk 后面分析①
PX4_V2_CONFIG_FILE=$(MK_DIR)/PX4/config_px4fmu-v2_APM.mk
PX4_V4_CONFIG_FILE=$(MK_DIR)/PX4/config_px4fmu-v4_APM.mk


SKETCHFLAGS=$(SKETCHLIBINCLUDES) -DARDUPILOT_BUILD -DTESTS_MATHLIB_DISABLE -DCONFIG_HAL_BOARD=HAL_BOARD_PX4 -DSKETCHNAME="\\\"$(SKETCH)\\\"" -DSKETCH_MAIN=ArduPilot_main -DAPM_BUILD_DIRECTORY=APM_BUILD_$(SKETCH)


WARNFLAGS = -Wall -Wextra -Wlogical-op -Werror -Wno-unknown-pragmas -Wno-redundant-decls -Wno-psabi -Wno-packed -Wno-error=double-promotion 
-Wno-error=unused-variable -Wno-error=reorder -Wno-error=float-equal -Wno-error=pmf-conversions -Wno-error=missing-declarations -Wno-error=unused-function
OPTFLAGS = -fsingle-precision-constant


# avoid PX4 submodules
export GIT_SUBMODULES_ARE_EVIL = 1
# 指定两个PYTHON 脚本路径
PYTHONPATH=$(SKETCHBOOK)/mk/PX4/Tools/genmsg/src:$(SKETCHBOOK)/mk/PX4/Tools/gencpp/src
export PYTHONPATH
# MAKE 变量 指定了编译路径,和包含的根makefile
# 1. ardupilot/Makefile 
# 2. ardupilot/modules/PX4Firmware/Makefile.make
# 3. ardupilot/modules/PX4Firmware/Makefile 
PX4_MAKE = $(v)+ GIT_SUBMODULES_ARE_EVIL=1 ARDUPILOT_BUILD=1 $(MAKE) -C $(SKETCHBOOK) -f $(PX4_ROOT)/Makefile.make EXTRADEFINES="$(SKETCHFLAGS) $(WARNFLAGS) $(OPTFLAGS) "'$(EXTRAFLAGS)' 
  APM_MODULE_DIR=$(SKETCHBOOK) SKETCHBOOK=$(SKETCHBOOK) CCACHE=$(CCACHE) PX4_ROOT=$(PX4_ROOT) NUTTX_SRC=$(NUTTX_SRC) MAXOPTIMIZATION="-Os" UAVCAN_DIR=$(UAVCAN_DIR)
PX4_MAKE_ARCHIVES = $(MAKE) -C $(PX4_ROOT) -f $(PX4_ROOT)/Makefile.make NUTTX_SRC=$(NUTTX_SRC) CCACHE=$(CCACHE) archives MAXOPTIMIZATION="-Os"


HASHADDER_FLAGS += --ardupilot "$(SKETCHBOOK)"


ifneq ($(wildcard $(PX4_ROOT)),)
HASHADDER_FLAGS += --px4 "$(PX4_ROOT)"
endif
ifneq ($(wildcard $(NUTTX_SRC)/..),)
HASHADDER_FLAGS += --nuttx "$(NUTTX_SRC)/.."
endif
HASHADDER_FLAGS += --uavcan "$(UAVCAN_DIR)"


.PHONY: module_mk
# 自动生成audupilot/module.mk 如下:
# # Auto-generated file - do not edit
# MODULE_COMMAND = ArduPilot
#   # 包含 ArduCopter 和 libraries 文件夹下的 源文件.cpp 
#   # 也就是:$(SRCROOT)/*.cpp 和 $(SKETCHLIBSRCSRELATIVE)
# SRCS = /home/xxdk/pixHawk@xxdk/ardupilot/ArduCopter/......cpp
#   libraries/....../.cpp
#          ......
#          ......
# MODULE_STACKSIZE = 4096
# EXTRACXXFLAGS = -Wframe-larger-than=1300
module_mk:
$(v) echo "Building $(SKETCHBOOK)/module.mk"
$(RULEHDR)
$(v) echo "# Auto-generated file - do not edit" > $(SKETCHBOOK)/module.mk.new
$(v) echo "MODULE_COMMAND = ArduPilot" >> $(SKETCHBOOK)/module.mk.new
$(v) echo "SRCS = $(wildcard $(SRCROOT)/*.cpp) $(SKETCHLIBSRCSRELATIVE)" >> $(SKETCHBOOK)/module.mk.new
$(v) echo "MODULE_STACKSIZE = 4096" >> $(SKETCHBOOK)/module.mk.new
$(v) echo "EXTRACXXFLAGS = -Wframe-larger-than=1300" >> $(SKETCHBOOK)/module.mk.new
$(v) cmp $(SKETCHBOOK)/module.mk $(SKETCHBOOK)/module.mk.new 2>/dev/null || mv $(SKETCHBOOK)/module.mk.new $(SKETCHBOOK)/module.mk
$(v) rm -f $(SKETCHBOOK)/module.mk.new


px4-v1: $(BUILDROOT)/make.flags CHECK_MODULES $(MAVLINK_HEADERS) $(PX4_ROOT)/Archives/px4fmu-v1.export $(SKETCHCPP) module_mk px4-io-v1
$(v) echo Building px4-v1
$(RULEHDR)
$(v) cp $(PX4_V1_CONFIG_FILE) $(PX4_ROOT)/makefiles/nuttx/
$(v) $(PX4_MAKE) px4fmu-v1_APM
$(v) arm-none-eabi-size $(PX4_ROOT)/Build/px4fmu-v1_APM.build/firmware.elf
$(v) cp $(PX4_ROOT)/Images/px4fmu-v1_APM.px4 $(SKETCH)-v1.px4
$(v) $(SKETCHBOOK)/Tools/scripts/add_git_hashes.py $(HASHADDER_FLAGS) "$(SKETCH)-v1.px4" "$(SKETCH)-v1.px4"
$(v) echo "PX4 $(SKETCH) Firmware is in $(SKETCH)-v1.px4"

# px4-v2 依赖于 module_mk 在前面
#        依赖于 ardupilot/Build.ArduCopter/make.flags
#        依赖于 ardupilot/modules/PX4Firmware/Archives/px4fmu-v2.export
#        依赖于 px4-io-v2 在后面
# 。。。。。。
# 这里马上正式开始编译,棒棒哒----------------------------------------->>>>>>
px4-v2: $(BUILDROOT)/make.flags CHECK_MODULES $(MAVLINK_HEADERS) $(PX4_ROOT)/Archives/px4fmu-v2.export $(SKETCHCPP) module_mk px4-io-v2
$(v) echo Building px4-v2
$(RULEHDR)

# ardupilot/mk/PX4/config_px4fmu-v2_APM.mk 
$(v) cp $(PX4_V2_CONFIG_FILE) $(PX4_ROOT)/makefiles/nuttx/

#------------------------------------------------------------------------------>>>>>>
# 这里终于正式开始编译,感觉自己萌萌哒----------------------------------------->>>>>>
# ----------------------------------------------------------------------------->>>>>>
$(PX4_MAKE) px4fmu-v2_APM

# arm-none-eabi-size firmware.elf 执行效果,和编译控制台输出的最后3行吻合 yeah!
#   text   data    bss    dec    hex filename
#   954220   2848  61404 1018472  f8a68 firmware.elf
$(v) arm-none-eabi-size $(PX4_ROOT)/Build/px4fmu-v2_APM.build/firmware.elf

# copy ardupilot/modules/PX4Firmware/Images/px4fmu-v2_APM.px4  to ArduCopter/ArduCopter-v2.px4
$(v) cp $(PX4_ROOT)/Images/px4fmu-v2_APM.px4 $(SKETCH)-v2.px4

# 执行了一段Python 脚本ardupilot/Tools/scripts/add_git_hashes.py
# 目的是:Add git hashes to .px4 file for PX4/Pixhawk build
$(v) $(SKETCHBOOK)/Tools/scripts/add_git_hashes.py $(HASHADDER_FLAGS) "$(SKETCH)-v2.px4" "$(SKETCH)-v2.px4"

# 大功告成前的一句:PX4 ArduCopter Firmware is in ArduCopter-v2.px4
$(v) echo "PX4 $(SKETCH) Firmware is in $(SKETCH)-v2.px4"


px4-v4: $(BUILDROOT)/make.flags CHECK_MODULES $(MAVLINK_HEADERS) $(PX4_ROOT)/Archives/px4fmu-v4.export $(SKETCHCPP) module_mk
$(v) echo Building px4-v4
$(RULEHDR)
$(v) cp $(PX4_V4_CONFIG_FILE) $(PX4_ROOT)/makefiles/nuttx/
$(PX4_MAKE) px4fmu-v4_APM
$(v) arm-none-eabi-size $(PX4_ROOT)/Build/px4fmu-v4_APM.build/firmware.elf
$(v) cp $(PX4_ROOT)/Images/px4fmu-v4_APM.px4 $(SKETCH)-v4.px4
$(v) mkdir -p $(MK_DIR)/PX4/ROMFS/bootloader/
$(v) cp $(SKETCHBOOK)/mk/PX4/bootloader/px4fmuv4_bl.bin $(MK_DIR)/PX4/ROMFS/bootloader/fmu_bl.bin
$(v) $(SKETCHBOOK)/Tools/scripts/add_git_hashes.py $(HASHADDER_FLAGS) "$(SKETCH)-v4.px4" "$(SKETCH)-v4.px4"
$(v) echo "PX4 $(SKETCH) Firmware is in $(SKETCH)-v4.px4"


# force the 3 build types to not run in parallel. We got bad binaries with incorrect parameter handling
# when these were allowed to happen in parallel
px4:
$(MAKE) px4-v1
$(MAKE) px4-v2
$(MAKE) px4-v4


px4-clean: clean CHECK_MODULES px4-archives-clean px4-cleandep
$(v) /bin/rm -rf $(PX4_ROOT)/makefiles/build $(PX4_ROOT)/Build $(PX4_ROOT)/Images/*.px4 $(PX4_ROOT)/Images/*.bin
$(v) /bin/rm -rf $(PX4_ROOT)/src/modules/uORB/topics $(PX4_ROOT)/src/platforms/nuttx/px4_messages
$(v) /bin/rm -f $(SRCROOT)/*.o


px4-cleandep: clean
$(v) mkdir -p $(PX4_ROOT)/Build
$(v) find $(PX4_ROOT)/Build -type f -name '*.d' | xargs rm -f
$(v) find $(UAVCAN_DIRECTORY) -type f -name '*.d' | xargs rm -f
$(v) find $(SKETCHBOOK)/$(SKETCH) -type f -name '*.d' | xargs rm -f


px4-v2-upload-solo: px4-v2
scp $(SKETCH)-v2.px4 root@10.1.1.10:/tmp/
ssh root@10.1.1.10 PYTHONUNBUFFERED=1 loadPixhawk.py /tmp/ArduCopter-v2.px4
ssh root@10.1.1.10 rm /tmp/ArduCopter-v2.px4;


px4-v1-upload: px4-v1
$(RULEHDR)
$(v) $(PX4_MAKE) px4fmu-v1_APM upload
# 这里是上载到板子的 执行流:-------------------------------------------->>>>>>
px4-v2-upload: px4-v2
$(RULEHDR)
$(v) $(PX4_MAKE) px4fmu-v2_APM upload


px4-v4-upload: px4-v4
$(RULEHDR)
$(v) $(PX4_MAKE) px4fmu-v4_APM upload


px4-upload: px4-v1-upload


px4-archives-clean:
$(v) /bin/rm -rf $(PX4_ROOT)/Archives


px4-io-v1: $(PX4_ROOT)/Archives/px4io-v1.export
$(v)+ $(MAKE) -C $(PX4_ROOT) -f $(PX4_ROOT)/Makefile.make px4io-v1_default EXTRADEFINES="-DARDUPILOT_BUILD"
$(v) cp $(PX4_ROOT)/Images/px4io-v1_default.bin px4io-v1.bin
$(v) cp $(PX4_ROOT)/Build/px4io-v1_default.build/firmware.elf px4io-v1.elf
$(v) mkdir -p $(MK_DIR)/PX4/ROMFS/px4io/
$(v) cp px4io-v1.bin $(MK_DIR)/PX4/ROMFS/px4io/px4io.bin
$(v) mkdir -p $(MK_DIR)/PX4/ROMFS/bootloader/
$(v) cp $(SKETCHBOOK)/mk/PX4/bootloader/px4fmu_bl.bin $(MK_DIR)/PX4/ROMFS/bootloader/fmu_bl.bin
$(v) echo "PX4IOv1 Firmware is in px4io-v1.bin"


# 前面 px4-v2 目标的一个依赖
# px4-io-v2依赖于: ardupilot/modules/PX4Firmware/Archives/px4io-v2.export
px4-io-v2: $(PX4_ROOT)/Archives/px4io-v2.export
# PX4_ROOT:ardupilot/modules/PX4Firmware
# 执行的 makefile 
# ardupilot/modules/PX4Firmware/Makefile
# ardupilot/modules/PX4Firmware/Makefile.make 
#
$(v)+ $(MAKE) -C $(PX4_ROOT) -f $(PX4_ROOT)/Makefile.make px4io-v2_default EXTRADEFINES="-DARDUPILOT_BUILD"

$(v) cp $(PX4_ROOT)/Images/px4io-v2_default.bin px4io-v2.bin

$(v) cp $(PX4_ROOT)/Build/px4io-v2_default.build/firmware.elf px4io-v2.elf
$(v) mkdir -p $(MK_DIR)/PX4/ROMFS/px4io/
$(v) cp px4io-v2.bin $(MK_DIR)/PX4/ROMFS/px4io/px4io.bin
$(v) mkdir -p $(MK_DIR)/PX4/ROMFS/bootloader/
$(v) cp $(SKETCHBOOK)/mk/PX4/bootloader/px4fmuv2_bl.bin $(MK_DIR)/PX4/ROMFS/bootloader/fmu_bl.bin
$(v) echo "PX4IOv2 Firmware is in px4io-v2.bin"


px4-io: px4-io-v1 px4-io-v2


# These targets can't run in parallel because they all need to generate a tool
# to generate the config.h inside them. This could trigger races if done in
# parallel, trying to generate the tool and replacing it while the header is already
# being generated
#
# We could serialize inside PX4Firmware, but it's easier to serialize here
# while maintaining the rest of the build parallelized


.NOTPARALLEL: \
$(PX4_ROOT)/Archives/px4fmu-v1.export \
$(PX4_ROOT)/Archives/px4fmu-v2.export \
$(PX4_ROOT)/Archives/px4fmu-v4.export \
$(PX4_ROOT)/Archives/px4io-v1.export \
$(PX4_ROOT)/Archives/px4io-v2.export


$(PX4_ROOT)/Archives/px4fmu-v1.export:
$(v) $(PX4_MAKE_ARCHIVES) BOARDS="px4fmu-v1"

# 1. ardupilot/modules/PX4Firmware/Makefile.make
# 2. ardupilot/modules/PX4Firmware/Makefile 
$(PX4_ROOT)/Archives/px4fmu-v2.export:
$(v) $(PX4_MAKE_ARCHIVES) BOARDS="px4fmu-v2"


$(PX4_ROOT)/Archives/px4fmu-v4.export:
$(v) $(PX4_MAKE_ARCHIVES) BOARDS="px4fmu-v4"


$(PX4_ROOT)/Archives/px4io-v1.export:
$(v) $(PX4_MAKE_ARCHIVES) BOARDS="px4io-v1"


$(PX4_ROOT)/Archives/px4io-v2.export:
$(v) $(PX4_MAKE_ARCHIVES) BOARDS="px4io-v2"


px4-archives:
$(v) $(PX4_MAKE_ARCHIVES) BOARDS="px4io-v1 px4io-v2 px4fmu-v1 px4fmu-v2 px4fmu-v4"

下面是前面包含的 config_px4fmu-v2_APM.mk
①. ardupilot/mk/PX4/config_px4fmu-v2_APM.mk
#
# Makefile for the px4fmu-v2_APM configuration
#
include $(SKETCHBOOK)/mk/PX4/px4_common.mk


MODULES += drivers/lsm303d
MODULES += drivers/l3gd20
MODULES += drivers/mpu9250
MODULES += drivers/boards/px4fmu-v2
MODULES += drivers/pwm_input
MODULES     += modules/uavcan
MODULES     += lib/mathlib
MODULES += drivers/px4io
MODULES += drivers/px4flow
MODULES += drivers/oreoled

  Ⅰ. 首先来看看 ardupilot/mk/PX4/px4-common.mk 
#
# common makefile elements for all PX4 boards
#
#
# Use the configuration's ROMFS.
#
ROMFS_ROOT = $(SKETCHBOOK)/mk/PX4/ROMFS
MODULES += $(APM_MODULE_DIR)


# 板级相关的模块
# Board support modules
#
MODULES += drivers/device
MODULES += drivers/stm32
MODULES += drivers/stm32/adc
MODULES += drivers/stm32/tone_alarm
MODULES += drivers/led
MODULES += drivers/px4fmu
MODULES += drivers/rgbled
MODULES += drivers/mpu6000
MODULES += drivers/hmc5883
MODULES += drivers/ms5611
MODULES += drivers/mb12xx
MODULES += drivers/ll40ls
MODULES += drivers/trone
#MODULES += drivers/gps
#MODULES += drivers/hil
#MODULES += drivers/hott_telemetry
#MODULES += drivers/blinkm
#MODULES += modules/sensors
MODULES += drivers/airspeed
MODULES += drivers/ets_airspeed
MODULES += drivers/meas_airspeed
MODULES += drivers/mkblctrl
MODULES += drivers/batt_smbus
MODULES += drivers/irlock


#
# System commands
#
MODULES += systemcmds/bl_update
MODULES += systemcmds/mixer
MODULES += systemcmds/perf
MODULES += systemcmds/pwm
MODULES += systemcmds/reboot
MODULES += systemcmds/top
#MODULES += systemcmds/tests
MODULES += systemcmds/nshterm
MODULES     += systemcmds/mtd
MODULES     += systemcmds/ver
MODULES     += systemcmds/otp


ifneq ($(wildcard $(PX4_ROOT)/src/systemcmds/reflect),)  
MODULES += systemcmds/reflect
endif
ifneq ($(wildcard $(PX4_ROOT)/src/systemcmds/motor_test),)  
MODULES += systemcmds/motor_test
endif
ifneq ($(wildcard $(PX4_ROOT)/src/systemcmds/usb_connected),)  
MODULES += systemcmds/usb_connected
endif


#
# Library modules
#
MODULES += modules/systemlib
MODULES += modules/systemlib/mixer
MODULES += modules/uORB
MODULES += lib/mathlib/math/filter


# Note: auth disabled to keep us under 1MB flash because of STM32 bug
#ifneq ($(wildcard $(PX4_ROOT)/src/systemcmds/auth),)  
#MODULES += systemcmds/auth
#endif
#ifneq ($(wildcard $(PX4_ROOT)/src/modules/libtomfastmath),)  
#MODULES        += modules/libtomfastmath
#MODULES         += modules/libtomcrypt
#endif


MODULES += lib/conversion


#
# Transitional support - add commands from the NuttX export archive.
#
# In general, these should move to modules over time.
#
# Each entry here is <command>.<priority>.<stacksize>.<entrypoint> but we use a helper macro
# to make the table a bit more readable.
# $(or condition1[,condition2[,condition3...]])
# The or function provides a “short-circuiting” OR operation. Each argument is expanded, in order. 
# If an argument expands to a non-empty string the processing stops and the result of the expansion is that string. 
# If, after all arguments are expanded, all of them are false (empty), then the result of the expansion is the empty string.
# $(strip STRINT)
   # 函数名称:去空格函数— strip。
# 函数功能:去掉字串(若干单词,使用若干空字符分割)“ STRINT”开头和结尾的
# 空字符,并将其中多个连续空字符合并为一个空字符。
define _B
$(strip $1).$(or $(strip $2),SCHED_PRIORITY_DEFAULT).$(or $(strip $3),CONFIG_PTHREAD_STACK_DEFAULT).$(strip $4)
endef


# command priority stack  entrypoint 
BUILTIN_COMMANDS := \
$(call _B, sercon, , 2048, sercon_main) \ 
$(call _B, serdis, , 2048, serdis_main)

  Ⅱ. 再来 see see 前面包含的 ardupilot/Makefile
# top level makefile to build SITL for primary vehicle targets. 
# Useful for static analysis tools


all: sitl


sitl: TARGET=sitl
sitl: plane copter rover antennatracker


linux: TARGET=linux
linux: plane copter rover antennatracker


clean: TARGET=clean
clean: copter rover antennatracker


.PHONY: plane copter rover antennatracker


plane:
# $(MAKE) -C ArduPlane $(TARGET)
# 进入 ArduCopter下其 Makefile TMD就一句:include ../mk/apm.mk 也就是开始总工程编译 
copter:
$(MAKE) -C ArduCopter $(TARGET)


rover:
# $(MAKE) -C APMrover2 $(TARGET)


antennatracker:
# $(MAKE) -C AntennaTracker $(TARGET)
  Ⅲ. 下面来 see see 前面包含的ardupilot/modules/PX4Firmware/Makefile
############################################################################
############################################################################
# Enforce the presence of the GIT repository
#
# We depend on our submodules, so we have to prevent attempts to
# compile without it being present.
ifeq ($(wildcard .git),)
$(error YOU HAVE TO USE GIT TO DOWNLOAD THIS REPOSITORY. ABORTING.)
endif
# cmake 版本 133343?
CMAKE_VER := $(shell Tools/check_cmake.sh; echo $$?)

ifneq ($(CMAKE_VER),0)
$(warning Not a valid CMake version or CMake not installed.)
$(warning On Ubuntu, install or upgrade via:)
$(warning )
$(warning 3rd party PPA:)
$(warning sudo add-apt-repository ppa:george-edison55/cmake-3.x -y)
$(warning sudo apt-get update)
$(warning sudo apt-get install cmake)
$(warning )
$(warning Official website:)
$(warning wget https://cmake.org/files/v3.3/cmake-3.3.2-Linux-x86_64.sh)
$(warning chmod +x cmake-3.3.2-Linux-x86_64.sh)
$(warning sudo mkdir /opt/cmake-3.3.2)
$(warning sudo ./cmake-3.3.2-Linux-x86_64.sh --prefix=/opt/cmake-3.3.2 --exclude-subdir)
$(warning export PATH=/opt/cmake-3.3.2/bin:$$PATH)
$(warning )
$(error Fatal)
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.
#
# 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.


#  explicity set default build target
all: px4fmu-v2_default


# Parsing
# --------------------------------------------------------------------
# assume 1st argument passed is the main target, the
# rest are arguments to pass to the makefile generated
# by cmake in the subdirectory
# MAKECMDGOALS: px4-v2
ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
j ?= 4

# ninja 英[ˈnɪndʒə]
# 美['nɪndʒə]
# n.(受过偷窃技术专门训练被雇作间谍或刺客的)日本武士;
NINJA_BUILD := $(shell ninja --version 2>/dev/null)
ifdef NINJA_BUILD
PX4_CMAKE_GENERATOR ?= "Ninja"
PX4_MAKE = ninja
PX4_MAKE_ARGS =
else
ifdef SYSTEMROOT
# Windows
PX4_CMAKE_GENERATOR ?= "MSYS Makefiles"
else
PX4_CMAKE_GENERATOR ?= "Unix Makefiles"
endif
# 重要的 PX4_MAKE 变量 
PX4_MAKE = make 
PX4_MAKE_ARGS = -j$(j) --no-print-directory
endif


# Functions
# --------------------------------------------------------------------
# describe how to build a cmake config
define cmake-build
+@if [ $(PX4_CMAKE_GENERATOR) = "Ninja" ] && [ -e $(PWD)/build_$@/Makefile ]; then rm -rf $(PWD)/build_$@; fi
+@if [ ! -e $(PWD)/build_$@/CMakeCache.txt ]; then Tools/check_submodules.sh && mkdir -p $(PWD)/build_$@ && cd $(PWD)/build_$@ && cmake .. -G$(PX4_CMAKE_GENERATOR) -DCONFIG=$(1) || (cd .. && rm -rf $(PWD)/build_$@); fi
+@Tools/check_submodules.sh
+$(PX4_MAKE) -C $(PWD)/build_$@ $(PX4_MAKE_ARGS) $(ARGS)
endef


# create empty targets to avoid msgs for targets passed to cmake
define cmake-targ
$(1):
@#
.PHONY: $(1)
endef


# ADD CONFIGS HERE
# --------------------------------------------------------------------
#  Do not put any spaces between function arguments.


px4fmu-v1_default:
$(call cmake-build,nuttx_px4fmu-v1_default)


px4fmu-v2_default:
$(call cmake-build,nuttx_px4fmu-v2_default)


px4fmu-v4_default:
$(call cmake-build,nuttx_px4fmu-v4_default)


px4-stm32f4discovery_default:
$(call cmake-build,nuttx_px4-stm32f4discovery_default)


px4fmu-v2_ekf2:
$(call cmake-build,nuttx_px4fmu-v2_ekf2)


px4fmu-v2_lpe:
$(call cmake-build,nuttx_px4fmu-v2_lpe)


mindpx-v2_default:
$(call cmake-build,nuttx_mindpx-v2_default)


posix_sitl_default:
$(call cmake-build,$@)


posix_sitl_lpe:
$(call cmake-build, $@)


posix_sitl_ekf2:
$(call cmake-build,$@)


posix_sitl_replay:
$(call cmake-build,$@)


ros_sitl_default:
@echo "This target is deprecated. Use make 'posix_sitl_default gazebo' instead."


qurt_eagle_travis:
$(call cmake-build,$@)


qurt_eagle_release:
$(call cmake-build,$@)


posix_eagle_release:
$(call cmake-build,$@)


qurt_eagle_default:
$(call cmake-build,$@)


eagle_default: posix_eagle_default qurt_eagle_default


posix_eagle_default:
$(call cmake-build,$@)


posix_rpi2_default:
$(call cmake-build,$@)


posix_rpi2_release:
$(call cmake-build,$@)


posix: posix_sitl_default


sitl_deprecation:
@echo "Deprecated. Use 'make posix_sitl_default jmavsim' or"
@echo "'make posix_sitl_default gazebo' if Gazebo is preferred."


run_sitl_quad: sitl_deprecation
run_sitl_plane: sitl_deprecation
run_sitl_ros: sitl_deprecation


# Other targets
# --------------------------------------------------------------------


uavcan_firmware:
@(rm -rf vectorcontrol && git clone https://github.com/thiemar/vectorcontrol \
&& cd vectorcontrol && BOARD=s2740vc_1_0 make --no-print-directory -s \
&& BOARD=px4esc_1_6 make --no-print-directory -s && ../Tools/uavcan_copy.sh)


check_format:
@./Tools/check_code_style.sh


check: px4fmu-v1_default px4fmu-v2_default px4fmu-v4_default px4-stm32f4discovery_default check_format tests


unittest: posix_sitl_default
@(cd unittests && cmake -G$(PX4_CMAKE_GENERATOR) && $(PX4_MAKE) $(PX4_MAKE_ARGS) && ctest)


tests: unittest
@make --no-print-directory px4fmu-v2_default test
@make --no-print-directory posix_sitl_default test


package_firmware:
@zip --junk-paths Firmware.zip `find . -name \*.px4`


clean:
@rm -rf build_*/
@(cd NuttX/nuttx && make clean)


submodulesclean:
@git submodule deinit -f .
@git submodule sync
@git submodule update --init --recursive --force


distclean: submodulesclean
@git clean -ff -x -d


# targets handled by cmake
cmake_targets = test upload package package_source debug debug_tui debug_ddd debug_io debug_io_tui debug_io_ddd check_weak \
run_cmake_config config gazebo gazebo_gdb gazebo_lldb jmavsim replay \
jmavsim_gdb jmavsim_lldb gazebo_gdb_iris gazebo_lldb_tailsitter gazebo_iris gazebo_iris_opt_flow gazebo_tailsitter \
gazebo_gdb_standard_vtol gazebo_lldb_standard_vtol gazebo_standard_vtol gazebo_plane
$(foreach targ,$(cmake_targets),$(eval $(call cmake-targ,$(targ))))


.PHONY: clean


CONFIGS:=$(shell ls cmake/configs | sed -e "s~.*/~~" | sed -e "s~\..*~~")


# Future:
#$(CONFIGS):
## @cd Build/$@ && cmake ../.. -DCONFIG=$@
# @cd Build/$@ && make
#
#clean-all:
# @rm -rf Build/*
#
#help:
# @echo
# @echo "Type 'make ' and hit the tab key twice to see a list of the available"
# @echo "build configurations."
# @echo
  Ⅳ. 接着来 see see 前面包含的ardupilot/modules/PX4Firmware/Makefile.make
#
# Top-level Makefile for building PX4 firmware images.
#


TARGETS := nuttx posix qurt # $(filter PATTERN…,TEXT) 
# 函数功能:过滤掉字串“TEXT”中所有不符合模式“PATTERN”的单词,保留所
# 有符合此模式的单词。可以使用多个模式。
EXPLICIT_TARGET := $(filter $(TARGETS),$(MAKECMDGOALS))


ifneq ($(EXPLICIT_TARGET),)
export PX4_TARGET_OS=$(EXPLICIT_TARGET)
export GOALS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
endif


#
# Get path and tool configuration
#
export PX4_BASE := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))/
# ardupilot/modules/PX4Firmware/makefiles/setup.mk 后面分析 
# 主要是包含一些px4相关的代码路径
include $(PX4_BASE)makefiles/setup.mk


#
# Get a version string provided by git
# This assumes that git command is available and that
# the directory holding this file also contains .git directory
#
GIT_DESC := $(shell git log -1 --pretty=format:%H)
ifneq ($(words $(GIT_DESC)),1)
GIT_DESC := "unknown_git_version"
endif


GIT_DESC_SHORT := $(shell echo $(GIT_DESC) | cut -c1-16)


$(shell mkdir -p $(BUILD_DIR))
$(shell rm -f $(BUILD_DIR)git_version.*)
$(shell echo "#include <systemlib/git_version.h>" > $(BUILD_DIR)git_version.c)
$(shell echo "const char* px4_git_version = \"$(GIT_DESC)\";" >> $(BUILD_DIR)git_version.c)
$(shell echo "const uint64_t px4_git_version_binary = 0x$(GIT_DESC_SHORT);" >> $(BUILD_DIR)git_version.c)


#
# Canned firmware configurations that we (know how to) build.
#
KNOWN_CONFIGS := $(subst config_,,$(basename $(notdir $(wildcard $(PX4_MK_DIR)/$(PX4_TARGET_OS)/config_*.mk))))
CONFIGS ?= $(KNOWN_CONFIGS)


#
# Boards that we (know how to) build NuttX export kits for.
#
KNOWN_BOARDS := $(subst board_,,$(basename $(notdir $(wildcard $(PX4_MK_DIR)/$(PX4_TARGET_OS)/board_*.mk))))
BOARDS ?= $(KNOWN_BOARDS)


#
# Debugging
#
MQUIET = --no-print-directory
#MQUIET = --print-directory


################################################################################
# No user-serviceable parts below
################################################################################


#
# If the user has listed a config as a target, strip it out and override CONFIGS.
#
FIRMWARE_GOAL = firmware
EXPLICIT_CONFIGS := $(filter $(CONFIGS),$(MAKECMDGOALS))
ifneq ($(EXPLICIT_CONFIGS),)
CONFIGS := $(EXPLICIT_CONFIGS)
.PHONY: $(EXPLICIT_CONFIGS)
$(EXPLICIT_CONFIGS): all


#
# If the user has asked to upload, they must have also specified exactly one
# config.
# 判定是否需要 upload
ifneq ($(filter upload,$(MAKECMDGOALS)),)
ifneq ($(words $(EXPLICIT_CONFIGS)),1)
$(error In order to upload, exactly one board config must be specified)
endif
FIRMWARE_GOAL = upload
.PHONY: upload
upload:
@:
endif
endif


ifeq ($(PX4_TARGET_OS),nuttx) 
#
# Built products
#
DESIRED_FIRMWARES = $(foreach config,$(CONFIGS),$(IMAGE_DIR)$(config).px4)
STAGED_FIRMWARES = $(foreach config,$(KNOWN_CONFIGS),$(IMAGE_DIR)$(config).px4)
FIRMWARES = $(foreach config,$(KNOWN_CONFIGS),$(BUILD_DIR)$(config).build/firmware.px4)


all: $(DESIRED_FIRMWARES)


#
# Copy FIRMWARES into the image directory.
#
# XXX copying the .bin files is a hack to work around the PX4IO uploader
#     not supporting .px4 files, and it should be deprecated onced that
#     is taken care of.
#
$(STAGED_FIRMWARES): $(IMAGE_DIR)%.px4: $(BUILD_DIR)%.build/firmware.px4
@$(ECHO) %% Copying $@
$(Q) $(COPY) $< $@
# 格式:$(patsubst <pattern>,<replacement>,<text> ) 
# 名称:模式字符串替换函数——patsubst。
# 功能:查找<text>中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合模式<pattern>,
# 如果匹配的话,则以<replacement>替换。这里,<pattern>可以包括通配符“%”,表示任意长度的字串。
# 如果<replacement>中也包含“%”,那么,<replacement>中的这个“%”将是<pattern>中的那个“%”所代表的字串。
# (可以用“\”来转义,以“\%”来表示真实含义的“%”字符)
$(Q) $(COPY) $(patsubst %.px4,%.bin,$<) $(patsubst %.px4,%.bin,$@)


#
# Generate FIRMWARES.
# ardupilot/modules/PX4Firmware/Build/px4io-v2_default.build/firmware.px4
# ardupilot/modules/PX4Firmware/Build/px4fmu-v2_APM.build/firmware.px4


.PHONY: $(FIRMWARES)
$(BUILD_DIR)%.build/firmware.px4: config   = $(patsubst $(BUILD_DIR)%.build/firmware.px4,%,$@)
$(BUILD_DIR)%.build/firmware.px4: work_dir = $(BUILD_DIR)$(config).build/
$(FIRMWARES): $(BUILD_DIR)%.build/firmware.px4: generateuorbtopicheaders checksubmodules
@$(ECHO) %%%%
@$(ECHO) %%%% Building $(config) in $(work_dir)
@$(ECHO) %%%%
$(Q) $(MKDIR) -p $(work_dir)
$(Q)+ $(MAKE) -r -C $(work_dir) \
-f $(PX4_MK_DIR)firmware.mk \  # 后面分析 
CONFIG=$(config) \
WORK_DIR=$(work_dir) \
$(FIRMWARE_GOAL)


#
# Make FMU firmwares depend on the corresponding IO firmware.
#
# This is a pretty vile hack, since it hard-codes knowledge of the FMU->IO dependency
# and forces the _default config in all cases. There has to be a better way to do this...
#
FMU_VERSION = $(patsubst px4fmu-%,%,$(word 1, $(subst _, ,$(1))))
define FMU_DEP
$(BUILD_DIR)$(1).build/firmware.px4: $(IMAGE_DIR)px4io-$(call FMU_VERSION,$(1))_default.px4
endef
FMU_CONFIGS := $(filter px4fmu%,$(CONFIGS))
# $(foreach config,$(FMU_CONFIGS),$(eval $(call FMU_DEP,$(config))))


#
# Build the NuttX export archives.
#
# Note that there are no explicit dependencies extended from these
# archives. If NuttX is updated, the user is expected to rebuild the
# archives/build area manually. Likewise, when the 'archives' target is
# invoked, all archives are always rebuilt.
#
# XXX Should support fetching/unpacking from a separate directory to permit
#     downloads of the prebuilt archives as well...
#
# 下面是关于Nuttx的编译
NUTTX_ARCHIVES = $(foreach board,$(BOARDS),$(ARCHIVE_DIR)$(board).export)
.PHONY: archives
archives: checksubmodules $(NUTTX_ARCHIVES)


$(ARCHIVE_DIR)%.export: board = $(notdir $(basename $@))
$(ARCHIVE_DIR)%.export: configuration = nsh
$(NUTTX_ARCHIVES): $(ARCHIVE_DIR)%.export: $(NUTTX_SRC)
@$(ECHO) %% Configuring NuttX for $(board)
$(Q) (cd $(NUTTX_SRC) && $(RMDIR) nuttx-export)
$(Q)+ $(MAKE) -C $(NUTTX_SRC) -r $(MQUIET) distclean
$(Q) (cd $(NUTTX_SRC)/configs && $(COPYDIR) $(PX4_BASE)nuttx-configs/$(board) .)
$(Q) (cd $(NUTTX_SRC)tools && ./configure.sh $(board)/$(configuration))
@$(ECHO) %% Exporting NuttX for $(board)
# ardupilot/modules/PX4NuttX/nuttx/Makfile 制定Nuttx的编译规则 后面分析
# -r: 禁止使用预定义的隐含规则,同时也清除了缺省的后缀列表和后缀规则。注意缺省的变量仍然有效。
$(Q)+ $(MAKE) -C $(NUTTX_SRC) -r $(MQUIET) CONFIG_ARCH_BOARD=$(board) export
$(Q) $(MKDIR) -p $(dir $@)
# ardupilot/modules/PX4NuttX/nuttx/nuttx-export.zip
$(Q) $(COPY) $(NUTTX_SRC)nuttx-export.zip $@
$(Q) (cd $(NUTTX_SRC)/configs && $(RMDIR) $(board))


#
# The user can run the NuttX 'menuconfig' tool for a single board configuration with
# make BOARDS=<boardname> menuconfig
#
ifeq ($(MAKECMDGOALS),menuconfig)
ifneq ($(words $(BOARDS)),1)
$(error BOARDS must specify exactly one board for the menuconfig goal)
endif
BOARD = $(BOARDS)
menuconfig: $(NUTTX_SRC)
@$(ECHO) %% Configuring NuttX for $(BOARD)
$(Q) (cd $(NUTTX_SRC) && $(RMDIR) nuttx-export)
$(Q)+ $(MAKE) -C $(NUTTX_SRC) -r $(MQUIET) distclean
$(Q) (cd $(NUTTX_SRC)/configs && $(COPYDIR) $(PX4_BASE)nuttx-configs/$(BOARD) .)
$(Q) (cd $(NUTTX_SRC)tools && ./configure.sh $(BOARD)/nsh)
@$(ECHO) %% Running menuconfig for $(BOARD)
$(Q)+ $(MAKE) -C $(NUTTX_SRC) -r $(MQUIET) menuconfig
@$(ECHO) %% Saving configuration file
$(Q)$(COPY) $(NUTTX_SRC).config $(PX4_BASE)nuttx-configs/$(BOARD)/nsh/defconfig
else
menuconfig:
@$(ECHO) ""
@$(ECHO) "The menuconfig goal must be invoked without any other goal being specified"
@$(ECHO) ""
endif


$(NUTTX_SRC): checksubmodules


$(UAVCAN_DIR):
$(Q) (./Tools/check_submodules.sh)


endif


ifeq ($(PX4_TARGET_OS),nuttx)
# TODO
# Move the above nuttx specific rules into $(PX4_BASE)makefiles/firmware_nuttx.mk
endif
ifeq ($(PX4_TARGET_OS),posix)
include $(PX4_BASE)makefiles/firmware_posix.mk
endif
ifeq ($(PX4_TARGET_OS),qurt)
include $(PX4_BASE)makefiles/firmware_qurt.mk
endif


.PHONY: checksubmodules
checksubmodules:
$(Q) ($(PX4_BASE)/Tools/check_submodules.sh)


.PHONY: updatesubmodules
updatesubmodules:
$(Q) (git submodule init)
$(Q) (git submodule update)


MSG_DIR = $(PX4_BASE)msg
UORB_TEMPLATE_DIR = $(PX4_BASE)msg/templates/uorb
MULTIPLATFORM_TEMPLATE_DIR = $(PX4_BASE)msg/templates/px4/uorb
TOPICS_DIR = $(PX4_BASE)src/modules/uORB/topics
MULTIPLATFORM_HEADER_DIR = $(PX4_BASE)src/platforms/$(PX4_TARGET_OS)/px4_messages
MULTIPLATFORM_PREFIX = px4_
TOPICHEADER_TEMP_DIR = $(BUILD_DIR)topics_temporary
GENMSG_PYTHONPATH = $(PX4_BASE)Tools/genmsg/src
GENCPP_PYTHONPATH = $(PX4_BASE)Tools/gencpp/src


.PHONY: generateuorbtopicheaders
generateuorbtopicheaders: checksubmodules
@$(ECHO) "Generating uORB topic headers"
$(Q) (PYTHONPATH=$(GENMSG_PYTHONPATH):$(GENCPP_PYTHONPATH):$(PYTHONPATH) $(PYTHON) \
$(PX4_BASE)Tools/px_generate_uorb_topic_headers.py \
-d $(MSG_DIR) -o $(TOPICS_DIR) -e $(UORB_TEMPLATE_DIR) -t $(TOPICHEADER_TEMP_DIR))
@$(ECHO) "Generating multiplatform uORB topic wrapper headers"
$(Q) (rm -r $(TOPICHEADER_TEMP_DIR))
$(Q) (PYTHONPATH=$(GENMSG_PYTHONPATH):$(GENCPP_PYTHONPATH):$(PYTHONPATH) $(PYTHON) \
$(PX4_BASE)Tools/px_generate_uorb_topic_headers.py \
-d $(MSG_DIR) -o $(MULTIPLATFORM_HEADER_DIR) -e $(MULTIPLATFORM_TEMPLATE_DIR) -t $(TOPICHEADER_TEMP_DIR) -p $(MULTIPLATFORM_PREFIX))
$(Q) (rm -r $(TOPICHEADER_TEMP_DIR))


#
# Testing targets
#
testbuild:
$(Q) (cd $(PX4_BASE) && $(MAKE) distclean && $(MAKE) archives && $(MAKE) -j8)
$(Q) (zip -r Firmware.zip $(PX4_BASE)/Images)


nuttx posix qurt: 
ifeq ($(GOALS),)
+$(MAKE) PX4_TARGET_OS=$@ $(GOALS)
else
export PX4_TARGET_OS=$@
endif


posixrun:
Tools/posix_run.sh


qurtrun:
$(MAKE) PX4_TARGET_OS=qurt sim


#
# Unittest targets. Builds and runs the host-level
# unit tests.
.PHONY: tests
tests: generateuorbtopicheaders
$(Q) (mkdir -p $(PX4_BASE)/unittests/build && cd $(PX4_BASE)/unittests/build && cmake .. && $(MAKE) unittests)


.PHONY: format check_format
check_format:
$(Q) (./Tools/check_code_style.sh | sort -n)


#
# Cleanup targets.  'clean' should remove all built products and force
# a complete re-compilation, 'distclean' should remove everything
# that's generated leaving only files that are in source control.
#
.PHONY: clean
clean:
@echo > /dev/null
$(Q) $(RMDIR) $(BUILD_DIR)*.build
$(Q) $(REMOVE) $(BUILD_DIR)git_version.*
$(Q) $(REMOVE) $(IMAGE_DIR)*.px4


.PHONY: distclean
distclean: clean
@echo > /dev/null
$(Q) $(REMOVE) $(ARCHIVE_DIR)*.export
$(Q)+ $(MAKE) -C $(NUTTX_SRC) -r $(MQUIET) distclean
$(Q) (cd $(NUTTX_SRC)/configs && $(FIND) . -maxdepth 1 -type l -delete)


#
# Print some help text
#
.PHONY: help
help:
@$(ECHO) ""
@$(ECHO) " PX4 firmware builder"
@$(ECHO) " ===================="
@$(ECHO) ""
@$(ECHO) "  Available targets:"
@$(ECHO) "  ------------------"
@$(ECHO) ""
ifeq ($(PX4_TARGET_OS),nuttx)
@$(ECHO) "  archives"
@$(ECHO) "    Build the NuttX RTOS archives that are used by the firmware build."
@$(ECHO) ""
endif
@$(ECHO) "  all"
@$(ECHO) "    Build all firmware configs: $(CONFIGS)"
@$(ECHO) "    A limited set of configs can be built with CONFIGS=<list-of-configs>"
@$(ECHO) ""
@for config in $(CONFIGS); do \
$(ECHO) "  $$config"; \
$(ECHO) "    Build just the $$config firmware configuration."; \
$(ECHO) ""; \
done
@$(ECHO) "  clean"
@$(ECHO) "    Remove all firmware build pieces."
@$(ECHO) ""
ifeq ($(PX4_TARGET_OS),nuttx)
@$(ECHO) "  distclean"
@$(ECHO) "    Remove all compilation products, including NuttX RTOS archives."
@$(ECHO) ""
@$(ECHO) "  upload"
@$(ECHO) "    When exactly one config is being built, add this target to upload the"
@$(ECHO) "    firmware to the board when the build is complete. Not supported for"
@$(ECHO) "    all configurations."
@$(ECHO) ""
endif
@$(ECHO) "  testbuild"
@$(ECHO) "    Perform a complete clean build of the entire tree."
@$(ECHO) ""
@$(ECHO) "  Common options:"
@$(ECHO) "  ---------------"
@$(ECHO) ""
@$(ECHO) "  V=1"
@$(ECHO) "    If V is set, more verbose output is printed during the build. This can"
@$(ECHO) "    help when diagnosing issues with the build or toolchain."
@$(ECHO) ""
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Ardupilot编译流程分析 的相关文章

  • Java中两种方法实现栈和队列(面试)

    学到LinkedList xff0c 上课时老师提了一下代码实现栈和队列 xff0c 面试可能会用上 xff0c 就码了栈和队列两种实现方案 如有问题 xff0c 希望指出 一 栈 1 数组实现栈 span class token comm
  • docker容器迁移教程

    前言 被领导要求部署一个和测试环境一样的演示环境 xff0c 并且数据库也要同步过去 xff0c 服务器上的各种服务都是docker部署的 xff0c 由于之前docker玩的比较少 xff0c 所以还是踩了不少坑的 xff0c 在此记录一
  • Java多sheet模板导出表格

    前言 需求是这样的 xff0c 需要在页面导出列表表格时同时导出每项的详情数据 xff0c 而且详情表格并不是一个常规的二维表格 xff0c 就像图中这样的效果 xff0c 所以要解决的最主要两个问题就是 xff1a 多sheet实现 异形
  • docker容器时间不同步导致在java应用中获取的时间不正确问题

    一 前言 在把Java应用部署到docker容器时 xff0c 发现应用获取到的时间和现实时间相差了8个小时 xff0c 会导致一系列不必要的麻烦 二 解决方案 1 首选需要确保宿主机的时区和时间的准确 现在宿主机上用 date R 看一下
  • Caffeine一级缓存介绍和应用

    Caffeine介绍 redis和caffeine的区别 相同点就不用说 xff0c 广义上都是缓存的方式 咱们就说说不同 redis是将数据存储到内存里 xff1b caffeine是将数据存储在本地应用里caffeine和redis相比
  • Java中使用es条件构造器BoolQueryBuilder

    前言 由于es在java中查询没法像mybatis那样方便 xff0c 而且es的构造器使用也比较繁琐 xff0c 理解不是很方便 xff0c 所以写一篇文章来记录es构造器BoolQueryBuilder查询时各种条件的构造的正确姿势 教
  • 群晖docker容器内mysql部署和远程连接

    群晖docker容器内mysql部署和远程连接 1 docker内Mysql部署2 Mysql远程访问配置 1 docker内Mysql部署 首先在群晖docker内安装ubuntu镜像 xff0c 启用镜像时注意对容器和宿主机的端口映射进
  • eclipse的安装及配置PyDev插件(win10)

    原博文 xff1a Windows下安装Eclipse 43 python2 7 43 Pydev 一 安装eclipse 学习Java第一步就是装eclipse 我每学习一门语言都会先死在安装程序上 这个也一样 一 去eclipse官网下
  • 小微企业技术人员面试流程及常见问题整理分析

    技术人员面试流程 在同一个小的企业做久了 xff0c 当有人员离职后 xff0c 招聘中的面试的工作就落在了资历老一点的员工上 虽然不是专业的HR xff0c 但还是在此记录一下一些人员面试的基本流程步骤及主要内容 一 面试流程 1 接待应
  • Ubuntu 解决触摸板不识别问题

    Ubuntu 解决触摸板不识别问题 span class hljs built in sudo span vi etc default grub span class hljs comment 把GRUB CMDLINE LINUX 61
  • 图像的灰度化、二值化

    目录 1 图像像素点 2 灰度化 3 二值化 4 使用open cv库进行图片的灰度化 二值化 4 1 将图片转换为灰度图 4 2 将灰度图转换为二值化图图片 1 图像像素点 在图像处理中 xff0c 用RGB三个分量 xff08 R xf
  • 【嵌入式】stm32程序跳转实验

    嵌入式 stm32程序跳转实验 菜老越 于 2019 04 23 17 54 56 发布 2888 收藏 22 分类专栏 xff1a 嵌入式 文章标签 xff1a keil stm32 程序跳转 IAP BootLoader 版权 嵌入式
  • C++/C语言实现HTTP的GET和POST请求

    阅读目录 HTTP请求和IP TCP 实现GET请求 实现POST请求 xff1a 参考 xff1a 回到顶部 HTTP请求和IP TCP 所谓的HTTP协议是基于IP TCP协议的 xff0c 所以要获取远端的html数据只要创建sock
  • C++ 简单实现HTTP GET/POST 请求

    HTTP 超文本传输协议 是一种客户端与服务端的传输协议 xff0c 最早用于浏览器和服务器之间的通信 xff0c 后来因为其使用灵活 方便等特点 xff0c 广泛用于客户端与服务端的通信 文章将简单介绍HTTP协议 xff0c 同时以C
  • 分布式系统架构简单介绍

    目录 xff1a 一 什么是分布式系统 xff1f 二 为什么要走分布式系统架构 xff1f 三 系统如何进行拆分 xff1f 四 分布式之后带来的技术挑战 xff1f 一 什么是分布式系统 xff1f 在谈分布式系统架构前 xff0c 我
  • 使用javascript实现对于chineseocr的API调用

    ChineseOCR在线API 网页地址 界面 提供多种接口调用方式 xff0c 比如在线调用 Javascript api调用 curl api调用和python api调用四种方式 xff0c 本次使用javascript api调用的
  • Qt-QMessageBox用法详解

    QMessageBox 是 Qt 框架中常用的一个类 xff0c 可以生成各式各样 各种用途的消息对话框 xff0c 如图 1 所示 图 1 QMessageBox消息对话框 很多 GUI 程序都会用到消息对话框 xff0c 且很多场景中使
  • C++中UDP通讯详解

    C 43 43 Socket编程及TCP UDP通信代码实现 一 简介 Socket编程的目的是使网络的进程进行通信 xff0c 基于TCP IP协议簇 xff0c 通过三元组 xff08 ip地址 协议 端口 xff09 标志进程 xff
  • sphinx写文档的简单尝试--index.rst的内容分析

    先说简单的结论 xff0c rst上手难度远高于markdown 功能扩展完爆markdown 在安装sphinx后 xff0c 开始编写shpinx的第一步 xff0c 就是使用sphinx quickstart来生成配置文件 我的目录结
  • 读书笔记:嵌入式常用算法_note_1

    目录 折线插值 抛物线插值 折线插值 include lt stdio h gt define N 10 折线由10段线段组成 即有11个插值节点 float w 61 10 0 插值节点间隔为10 0 即 w 61 y1 y0 61 10

随机推荐