研究基于PX4平台的Ardupilot代码工程的makefile结构
2017-02-06 11:18
585 查看
最近有空,于是想花时间好好研究下ardupilot的软件架构,经过对ardupilot一段时间的熟悉和使用后,对其软件架构已经有了一定的理解,但还称不上特别完备,所以想把每一部分的细节都弄清楚。
makefile定义了一个软件工程的编译规则,以便于其实现自动化编译,这也就是为什么我们在命令行中输入指令:
就可以自动完成整个工程的编译。
看似简单的一条命令,其中makefile完成了很多工作。
然后ardupilot工程那么繁杂,命名为makefile的文件也很多,我们应该从哪个文件开始分析起呢。
回想我们编译的过程,以旋翼机型为例,我们首先是打开“\ardupilot\ArduCopter”路径,那么在这个路径下有没有我们要找的makefile呢,答案是肯定的。
这个makefile中只有一条指令:
然后我们对应地找到apm.mk文件,这个文件的内容就比较多了。一行行地分析,首先看开头几行:
这几行代码是要确定MK_DIR,这个在下面查找mk文件时都会用到,根据我们电脑的操作系统类型确定,如果是Windows应该是执行第一个指令,所以 MK_DIR = “../mk”。也就是“…\ardupilot\mk”文件夹,该文件夹中有许多mk文件,有好多都是我们后面要用到的。
继续往下看:
打开environ.mk,该文件主要是确定一些编译相关的变量:EXTRAFLAGS,SRCROOT,SKETCHBOOK,BUILDROOT以及HAL_BOARD等,这些变量在后面都会用到。我们重点看下HAL_BOARD的确定,APM代码支持多种硬件平台,HAL_BOARD就代表了我们指定运行的硬件平台。关于HAL_BOARD有一长段的if语气对其进行赋值, 其中我们有找到这样一句:
MAKECMDGOALS代表命令行参数列表,如果我们在命令行中输入“make px4-v2”则MAKECMDGOALS就是“px4-v2”,包含px4字符段,所以if语句会执行该条件,HAL_BOARD = HAL_BOARD_PX4。从这里就可以看到我们在命令行中的指令对于编译条件的影响了,后续我们会看到HAL_BOARD的作用。
我们回到APM.mk中,继续往下看:
以指令“px4-v2”为例,会依次包含help.mk,targets.mk,sketch_sources.mk以及board_px4.mk,注意前三个是通用的,而board_px4.mk则是跟硬件平台有关,这里就是依据我们之前确定的HAL_BOARD来选择的。
help.mk中是一些帮助信息,响应“help”指令显示这些帮助信息;
targets.mk是对一些通用目标的响应,主要是支持一些其他类型硬件平台,同时还包含进了module.mk;
module.mk:
这个后面会用到,对于px4平台,由于其代码工程包含子模块,每次编译都会执行CHECK_MODULES。
sketch_sources.mk会基于SRCROOT里面的make.inc文件定义SKETCHLIBS,SKETCHLIBNAMES等变量,如前所述,SRCROOT是在environ.mk中规定的,在此例中,SRCROOT就是“……/ardupilot/arducopter”,在此路径中,可以找到mak.inc文件:
该文件中定义了LIBRARIES 变量。SKETCHLIBS变量是根据LIBRARIES 定义的。sketch_sources.mk同时也定义了一些指令的响应规则,如(BUILDROOT)/make.flags在后面会用到。
下面到了我们的重点board_px4.mk,该文件一开始首先是对PX4_ROOT,NUTTX_SRC和UAVCAN_DIR进行赋值处理,其实就是Ardupilot用到的三个子模块PX4Firmware、PX4NuttX和uavcan的文件路径。然后就是对EXTRAFLAGS变量进行扩展,EXTRAFLAGS表示附加标示,之前在environ.mk文件中已经对其添加了主模块的git版本,在这里会继续添加三个子模块的git版本号,git版本号用于统一主模块和子模块的版本对应关系,在git管理中应用。
board_px4.mk的重点在很多命令的定义,比如我们用到的px4-v2:
下面逐个分析:
$(BUILDROOT)/make.flags:可以在sketch_sources.mk找到定义:
该指令会在命令行中打印一些基本信息,并且将这些信息存放在
“…\Ardupilot\Build.ArduCopter\make.flags”文件中。
CHECK_MODULES在modules.mk中定义:
调用脚本文件check_modules.sh进行子模块检测。
$(PX4_ROOT)/Archives/px4fmu-v2.export是文件。
$(SKETCHCPP)是文件arducopter.cpp。
module_mk:
该指令会在Ardupilot主目录下生成一个module.mk文件。
px4-io-v2:
(v)+(MAKE) -C $(PX4_ROOT) px4io-v2_default会根据子模块PX4Firmware中的makefile来执行,涉及到PX4Firmware中的多个makefile,具体暂不讨论。接下来的指令就是将生成px4io-v2.bin等文件复制到相应的文件路径中去。
$(RULEHDR),RULEHDR是在sketch_sources.mk中定义的:
它会在命令行中打印:%% px4-v2。
接下来的:
这两句是用“…\Ardupilot\mk\PX4\config_px4fmu-v2_APM.mk”替换掉“…、Ardupilot\modules\PX4Firmware\makefiles\nuttx\config_px4fmu-v2_APM.mk”。
$(PX4_MAKE) px4fmu-v2_APM完成目标编译,同样与子模块的makefile有关,后续再做详细分析。
剩下来的指令就是完成arducopter-v2.px4文件的复制和存放。至此,make px4-v2”指令的分析就到此结束,后续会对子模块px4firmware的makefile做进一步分析。
makefile定义了一个软件工程的编译规则,以便于其实现自动化编译,这也就是为什么我们在命令行中输入指令:
make px4-v2
就可以自动完成整个工程的编译。
看似简单的一条命令,其中makefile完成了很多工作。
然后ardupilot工程那么繁杂,命名为makefile的文件也很多,我们应该从哪个文件开始分析起呢。
回想我们编译的过程,以旋翼机型为例,我们首先是打开“\ardupilot\ArduCopter”路径,那么在这个路径下有没有我们要找的makefile呢,答案是肯定的。
这个makefile中只有一条指令:
include ../mk/apm.mk
然后我们对应地找到apm.mk文件,这个文件的内容就比较多了。一行行地分析,首先看开头几行:
SYSTYPE := $(shell uname) ifneq ($(findstring CYGWIN, $(SYSTYPE)),) MK_DIR := $(shell cygpath -m ../mk) else MK_DIR := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST)))) endif
这几行代码是要确定MK_DIR,这个在下面查找mk文件时都会用到,根据我们电脑的操作系统类型确定,如果是Windows应该是执行第一个指令,所以 MK_DIR = “../mk”。也就是“…\ardupilot\mk”文件夹,该文件夹中有许多mk文件,有好多都是我们后面要用到的。
继续往下看:
include $(MK_DIR)/environ.mk
打开environ.mk,该文件主要是确定一些编译相关的变量:EXTRAFLAGS,SRCROOT,SKETCHBOOK,BUILDROOT以及HAL_BOARD等,这些变量在后面都会用到。我们重点看下HAL_BOARD的确定,APM代码支持多种硬件平台,HAL_BOARD就代表了我们指定运行的硬件平台。关于HAL_BOARD有一长段的if语气对其进行赋值, 其中我们有找到这样一句:
ifneq ($(findstring px4, $(MAKECMDGOALS)),) HAL_BOARD = HAL_BOARD_PX4 endif
MAKECMDGOALS代表命令行参数列表,如果我们在命令行中输入“make px4-v2”则MAKECMDGOALS就是“px4-v2”,包含px4字符段,所以if语句会执行该条件,HAL_BOARD = HAL_BOARD_PX4。从这里就可以看到我们在命令行中的指令对于编译条件的影响了,后续我们会看到HAL_BOARD的作用。
我们回到APM.mk中,继续往下看:
# short-circuit build for the configure target 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_APM1) include $(MK_DIR)/board_avr.mk endif ifeq ($(HAL_BOARD),HAL_BOARD_APM2) include $(MK_DIR)/board_avr.mk endif 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_FLYMAPLE) include $(MK_DIR)/board_flymaple.mk endif endif endif
以指令“px4-v2”为例,会依次包含help.mk,targets.mk,sketch_sources.mk以及board_px4.mk,注意前三个是通用的,而board_px4.mk则是跟硬件平台有关,这里就是依据我们之前确定的HAL_BOARD来选择的。
help.mk中是一些帮助信息,响应“help”指令显示这些帮助信息;
targets.mk是对一些通用目标的响应,主要是支持一些其他类型硬件平台,同时还包含进了module.mk;
module.mk:
# git submodule support .PHONY: CHECK_MODULES # PX4 build needs submodules px4-%: CHECK_MODULES CHECK_MODULES: $(v)$(MK_DIR)/check_modules.sh module-update: git submodule update
这个后面会用到,对于px4平台,由于其代码工程包含子模块,每次编译都会执行CHECK_MODULES。
sketch_sources.mk会基于SRCROOT里面的make.inc文件定义SKETCHLIBS,SKETCHLIBNAMES等变量,如前所述,SRCROOT是在environ.mk中规定的,在此例中,SRCROOT就是“……/ardupilot/arducopter”,在此路径中,可以找到mak.inc文件:
LIBRARIES += AP_Common LIBRARIES += AP_Progmem LIBRARIES += AP_Menu LIBRARIES += AP_Param LIBRARIES += StorageManager LIBRARIES += AP_HAL LIBRARIES += AP_HAL_AVR LIBRARIES += AP_HAL_SITL LIBRARIES += AP_HAL_PX4 LIBRARIES += AP_HAL_VRBRAIN LIBRARIES += AP_HAL_FLYMAPLE LIBRARIES += AP_HAL_Linux LIBRARIES += AP_HAL_Empty LIBRARIES += GCS LIBRARIES += GCS_MAVLink ....
该文件中定义了LIBRARIES 变量。SKETCHLIBS变量是根据LIBRARIES 定义的。sketch_sources.mk同时也定义了一些指令的响应规则,如(BUILDROOT)/make.flags在后面会用到。
下面到了我们的重点board_px4.mk,该文件一开始首先是对PX4_ROOT,NUTTX_SRC和UAVCAN_DIR进行赋值处理,其实就是Ardupilot用到的三个子模块PX4Firmware、PX4NuttX和uavcan的文件路径。然后就是对EXTRAFLAGS变量进行扩展,EXTRAFLAGS表示附加标示,之前在environ.mk文件中已经对其添加了主模块的git版本,在这里会继续添加三个子模块的git版本号,git版本号用于统一主模块和子模块的版本对应关系,在git管理中应用。
board_px4.mk的重点在很多命令的定义,比如我们用到的px4-v2:
px4-v2: $(BUILDROOT)/make.flags CHECK_MODULES $(PX4_ROOT)/Archives/px4fmu-v2.export $(SKETCHCPP) module_mk px4-io-v2 $( ca26 RULEHDR) $(v) rm -f $(PX4_ROOT)/makefiles/$(PX4_V2_CONFIG_FILE) $(v) cp $(PX4_V2_CONFIG_FILE) $(PX4_ROOT)/makefiles/nuttx/ $(PX4_MAKE) px4fmu-v2_APM $(v) /bin/rm -f $(SKETCH)-v2.px4 $(v) cp $(PX4_ROOT)/Images/px4fmu-v2_APM.px4 $(SKETCH)-v2.px4 $(v) $(SKETCHBOOK)/Tools/scripts/add_git_hashes.py $(HASHADDER_FLAGS) "$(SKETCH)-v2.px4" "$(SKETCH)-v2.px4" $(v) echo "PX4 $(SKETCH) Firmware is in $(SKETCH)-v2.px4"
下面逐个分析:
$(BUILDROOT)/make.flags:可以在sketch_sources.mk找到定义:
$(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
该指令会在命令行中打印一些基本信息,并且将这些信息存放在
“…\Ardupilot\Build.ArduCopter\make.flags”文件中。
CHECK_MODULES在modules.mk中定义:
CHECK_MODULES: $(v)$(MK_DIR)/check_modules.sh
调用脚本文件check_modules.sh进行子模块检测。
$(PX4_ROOT)/Archives/px4fmu-v2.export是文件。
$(SKETCHCPP)是文件arducopter.cpp。
module_mk:
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 = 8192" >> $(SKETCHBOOK)/module.mk.new $(v) echo "EXTRACXXFLAGS = -Wframe-larger-than=1200" >> $(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
该指令会在Ardupilot主目录下生成一个module.mk文件。
px4-io-v2:
px4-io-v2: $(PX4_ROOT)/Archives/px4io-v2.export $(v)+ $(MAKE) -C $(PX4_ROOT) px4io-v2_default $(v) /bin/rm -f px4io-v2.bin $(v) cp $(PX4_ROOT)/Build/px4io-v2_default.build/firmware.bin px4io-v2.bin $(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) rm -f $(MK_DIR)/PX4/ROMFS/px4io/px4io.bin $(v) cp px4io-v2.bin $(MK_DIR)/PX4/ROMFS/px4io/px4io.bin $(v) mkdir -p $(MK_DIR)/PX4/ROMFS/bootloader/ $(v) rm -f $(MK_DIR)/PX4/ROMFS/bootloader/fmu_bl.bin $(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"
(v)+(MAKE) -C $(PX4_ROOT) px4io-v2_default会根据子模块PX4Firmware中的makefile来执行,涉及到PX4Firmware中的多个makefile,具体暂不讨论。接下来的指令就是将生成px4io-v2.bin等文件复制到相应的文件路径中去。
$(RULEHDR),RULEHDR是在sketch_sources.mk中定义的:
# common header for rules, prints what is being built define RULEHDR @echo %% $(subst $(BUILDROOT)/,,$@) @mkdir -p $(dir $@) endef
它会在命令行中打印:%% px4-v2。
接下来的:
$(v) rm -f $(PX4_ROOT)/makefiles/$(PX4_V2_CONFIG_FILE) $(v) cp $(PX4_V2_CONFIG_FILE) $(PX4_ROOT)/makefiles/nuttx/
这两句是用“…\Ardupilot\mk\PX4\config_px4fmu-v2_APM.mk”替换掉“…、Ardupilot\modules\PX4Firmware\makefiles\nuttx\config_px4fmu-v2_APM.mk”。
$(PX4_MAKE) px4fmu-v2_APM完成目标编译,同样与子模块的makefile有关,后续再做详细分析。
剩下来的指令就是完成arducopter-v2.px4文件的复制和存放。至此,make px4-v2”指令的分析就到此结束,后续会对子模块px4firmware的makefile做进一步分析。
相关文章推荐
- 研究基于PX4平台的Ardupilot代码工程的makefile结构(2)
- linux驱动由浅入深系列:camera驱动之二(基于高通平台的V4L2结构及代码分析)
- 基于SOA的商业智能平台的研究与设计
- 基于J2EE平台Web系统的软件测试研究和实现
- 基于44B0平台的uC-Linux Web服务器实现方法研究
- mos开发系列教程八:页面代码研究-地图控件页面结构
- 文摘:UML建模目标,业务实体建模,认知结构,基于本体的企业工程
- 插件式软件结构设计(一):构建基于插件式软件平台
- 基于.Net平台应用程序唯一运行实例C#代码实现
- 《基于DE2的嵌入式WEB-SERVER研究》(网络工程)
- 基于SharePoint技术构建企业信息平台的研究
- PGP透明加解密研究------代码结构与功能
- (原创)基于or1200最小sopc系统搭建(二)--QuartuII工程及DE2平台下载
- 20.2 平台相关代码结构
- 基于.Net平台应用程序唯一运行实例C#代码实现
- 蜜网中基于Linux平台的蜜罐技术的研究
- 基于gridview的三层结构的代码演示 (二 ) 三层架构的实例演示 (原创,如需转载请联系作者)
- 基于.Net平台应用程序唯一运行实例C#代码实现