Ardupilot是一个非常庞大的项目,里面有针对各种机型(固定翼、直升机/多旋翼等)编写上层应用代码模块,也有针对各种硬件模块编写的底层代码模块。当我们购买好飞控板之后,如何根据源码把飞控程序编译并且链接成一个可执行程序烧录进入飞控板呢,这时候.mk(即Makefile)文件就显得非常重要的。.mk文件是一个脚本程序,在.mk中可以选择需要编译和链接的模块,然后运行这个.mk文件就可以生成可执行文件了,具体介绍在这里。Ardupilot中所有的.mk文件都放在\mk目录下面,下面我们依次介绍。本文针对Ardupilot版本:Copter 3.5.5-rc1 24-Jan-2018
编译命令介绍:
这里略过安装Ardupilot的开发环境,常用的编译命令如下:
编译所需固件需要进入相应的目录下,例如要编译多旋翼的话cd到ArduCopter目录下,其他的还有ArduPlane。与六旋翼相同,其余的飞机类型例如“octa”, “octa-quad, “tri”, “single”以及“heli”,直接把hexa进行替换即可。如果编译的是Pixhawk的四旋翼固件,编译成功的话将在ArduCopter目录下生成一个.px4后缀的文件,这就是最终烧录到飞控中的文件,可以使用MissionPlanner手动加载,也可以直接:make px4-v2-upload。
示例:
克隆仓库下来:git clone https://github.com/ArduPilot/ardupilot.git
进入仓库中:cd ardupilot
更新响应的模块:git submodule update --init --recursive
运行脚本文件:Tools/scripts/install-prereqs-ubuntu.sh -y
使配置直接生效:. ~/.profile
进入相应的目录:cd ArduCopter
开始编译四旋翼:make px4-v2
在/ArduCopter目录下有一个Makefile文件,其内容为:include ../mk/apm.mk。在这个apm.mk中,它首先找到\mk目录,然后根据一些条件来判断是否引入\mk目录下的.mk文件。
apm.mk文件:
下面是apm.mk的代码详解:
# 执行shell命令获取系统类型 SYSTYPE := $(shell uname) # 判断系统类型是否是CYGWIN(Cygwin 是一个用于 Windows的类 UNIX shell) ifneq ($(findstring CYGWIN, $(SYSTYPE)),) MK_DIR := $(shell cygpath -m ../mk) # 如果是则将路径转为Windows路径 else # GNU make会自动将所读取得makefile文件的路径都加入到MAKEFILE_LIST变量中,而且是按照读取的先后顺序添加。这里:MAKEFILE_LIST=ArduPilot/ardupilot/ArduCopter/Makefile ArduPilot/ardupilot/mk/apm.mk。 MK_DIR := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST)))) # 此时MK_DIR=ArduPilot/ardupilot/mk endif # 转去执行mk/environ.mk,执行完了之后再回来执行apm.mk include $(MK_DIR)/environ.mk # 如果$(MAKECMDGOALS)=configure。MAKECMDGOALS为命令行传进来的参数,值为cmd命令中make后面的字符串 ifeq ($(MAKECMDGOALS),configure) include $(MK_DIR)/configure.mk # configure.mk只有一句代码,没什么用 else include $(MK_DIR)/help.mk # help.mk都是打印一些信息,也没什么用 include $(MK_DIR)/targets.mk #targets.mk引用了modules.mk、uavcangen.mk、mavgen.mk include $(MK_DIR)/sketch_sources.mk #引用了\mk\make.inc和ArduCopter\make.inc,设置一些环境变量 include $(SKETCHBOOK)/modules/uavcan/libuavcan/include.mk # 设置了 uavcan的一些环境变量 # 如果$(MAKECMDGOALS)!=clean ifneq ($(MAKECMDGOALS),clean) # 如果$(HAL_BOARD)=HAL_BOARD_SITL,$(HAL_BOARD)在environ.mk中设置的 ifeq ($(HAL_BOARD),HAL_BOARD_SITL) include $(MK_DIR)/board_native.mk endif # 如果$(HAL_BOARD)=HAL_BOARD_LINUX ifeq ($(HAL_BOARD),HAL_BOARD_LINUX) include $(MK_DIR)/board_linux.mk endif # 如果$(HAL_BOARD)=HAL_BOARD_PX4 ifeq ($(HAL_BOARD),HAL_BOARD_PX4) include $(MK_DIR)/board_px4.mk #常用的,这个文件引用了find_tools.mk、px4_targets.mk endif # 如果$(HAL_BOARD)=HAL_BOARD_VRBRAIN ifeq ($(HAL_BOARD),HAL_BOARD_VRBRAIN) include $(MK_DIR)/board_vrbrain.mk endif # 如果$(HAL_BOARD)=HAL_BOARD_QURT ifeq ($(HAL_BOARD),HAL_BOARD_QURT) include $(MK_DIR)/board_qurt.mk endif # 如果$(HAL_BOARD)=HAL_BOARD_F4LIGHT ifeq ($(HAL_BOARD),HAL_BOARD_F4LIGHT) include $(MK_DIR)/board_F4Light.mk endif endif endif
environ.mk文件:
environ.mk主要是设置Makefile文件中用到的所有环境变量值,下面是文件代码分析。
# 获取系统名称,window为Cygwin,Linux为Linux SYSTYPE := $(shell uname) # 获取git版本 GIT_VERSION ?= $(shell git rev-parse HEAD | cut -c1-8) EXTRAFLAGS += -DGIT_VERSION="\"$(GIT_VERSION)\"" EXTRAFLAGS += -I$(SKETCHBOOK)/libraries/AP_Common/missing # 强制语言为C语言 export LANG=C #SRCROOT为firstword(ardupilot/ArduCopter/Makefile)的绝对真实路径即为:/ardupilot/ ArduCopter。 SRCROOT:=$(realpath $(dir $(firstword $(MAKEFILE_LIST)))) # 如果是Windows系统 ifneq ($(findstring CYGWIN, $(SYSTYPE)),) # 如果找不到Makefile的绝对路径,就要新建一个,并且发出警告。 ifeq ($(SRCROOT),) SRCROOT:= $(shell cygpath -m ${CURDIR}) # $(CURDIR)为当前目录值 $(warning your realpath function is not working) $(warning > setting SRCROOT to $(SRCROOT)) endif endif # SKETCHBOOK未定义是缺省值,为空。给sketchbook赋值。 ifeq ($(SKETCHBOOK),) #SKETCHBOOK为:ardupilot SKETCHBOOK := $(shell cd $(SRCROOT)/.. && pwd) ifeq ($(wildcard $(SKETCHBOOK)/libraries),) $(error ERROR: cannot determine sketchbook location-please specify on the commandline with SKETCHBOOK=<path>) endif # 如果SKETCHBOOK不为空 else ifeq ($(wildcard $(SKETCHBOOK)/libraries),) $(warning WARNING: sketchbook directory $(SKETCHBOOK) contains no libraries) endif endif # 如果是window系统,则转换路径 ifneq ($(findstring CYGWIN, $(SYSTYPE)),) # Convert cygwin path into a windows normal path SKETCHBOOK := $(shell cygpath ${SKETCHBOOK}) endif # 这句没什么用,.mk已经不需要了 ifneq ($(wildcard $(SKETCHBOOK)/config.mk),) $(info Reading $(SKETCHBOOK)/config.mk) include $(SKETCHBOOK)/config.mk endif # 这句也没什么用,developer.mk文件已经不存在了 ifneq ($(wildcard $(SKETCHBOOK)/developer.mk),) $(info Reading $(SKETCHBOOK)/developer.mk) include $(SKETCHBOOK)/developer.mk endif # 将SRCROOT路径中/用空格代替即为:ardupilot ArduCopter,取其最后一个单词,即 SKETCH= ArduCopter SKETCH := $(lastword $(subst /, ,$(SRCROOT))) # 如果sketch为空,则SKETCH为WORDLIST最后一个单词ArduCopter ifeq ($(SKETCH),) WORDLIST :=$(subst /, ,$(SRCROOT)) SKETCH :=$(word $(words $(WORDLIST)),$(WORDLIST)) # 取wordlist的最后一个单词 endif TMPDIR ?= /tmp # MAKECMDGOALS为命令行传进来的参数,值为cmd命令中make后面的字符串 #如果$(MAKECMDGOALS)中包含px4 ifneq ($(findstring px4, $(MAKECMDGOALS)),) BUILDROOT:=$(SKETCHBOOK)/Build.$(SKETCH) endif #如果$(MAKECMDGOALS)中包含vrbrain ifneq ($(findstring vrbrain, $(MAKECMDGOALS)),) BUILDROOT:=$(SKETCHBOOK)/Build.$(SKETCH) endif #如果$(MAKECMDGOALS)中包含vrubrain ifneq ($(findstring vrubrain, $(MAKECMDGOALS)),) BUILDROOT := $(SKETCHBOOK)/Build.$(SKETCH) endif #如果$(MAKECMDGOALS)中包含vrcore ifneq ($(findstring vrcore, $(MAKECMDGOALS)),) BUILDROOT:=$(SKETCHBOOK)/Build.$(SKETCH) endif # 如果BUILDROOT为空,则设置BUILDROOT ifeq ($(BUILDROOT),) BUILDROOT := $(abspath $(TMPDIR)/$(SKETCH).build) endif #如果为window操作系统 ifneq ($(findstring CYGWIN, $(SYSTYPE)),) ifeq ($(BUILDROOT),) BUILDROOT := C:$(TMPDIR)/$(SKETCH).build $(warning your abspath function is not working) $(warning > setting BUILDROOT to $(BUILDROOT)) else BUILDROOT := $(shell cygpath ${BUILDROOT}) # 转为window下的路径 endif endif # 如果$(MAKECMDGOALS)包含mavlink1 ifneq ($(findstring mavlink1, $(MAKECMDGOALS)),) EXTRAFLAGS += -DMAVLINK_PROTOCOL_VERSION=1 MAVLINK_SUBDIR=v1.0 MAVLINK_WIRE_PROTOCOL=1.0 else EXTRAFLAGS += -DMAVLINK_PROTOCOL_VERSION=2 MAVLINK_SUBDIR=v2.0 MAVLINK_WIRE_PROTOCOL=2.0 endif ifneq ($(APPDIR),) HAL_BOARD = HAL_BOARD_PX4 endif # 如果$(MAKECMDGOALS)中包含px4 ifneq ($(findstring px4, $(MAKECMDGOALS)),) HAL_BOARD = HAL_BOARD_PX4 endif # 如果$(MAKECMDGOALS)中包含sitl ifneq ($(findstring sitl, $(MAKECMDGOALS)),) HAL_BOARD = HAL_BOARD_SITL HAL_BOARD_SUBTYPE = HAL_BOARD_SUBTYPE_NONE endif # 如果$(MAKECMDGOALS)中包含varbrain ifneq ($(findstring vrbrain, $(MAKECMDGOALS)),) HAL_BOARD = HAL_BOARD_VRBRAIN HAL_BOARD_SUBTYPE = HAL_BOARD_SUBTYPE_NONE endif # 如果$(MAKECMDGOALS)中包含vrubrain ifneq ($(findstring vrubrain, $(MAKECMDGOALS)),) HAL_BOARD = HAL_BOARD_VRBRAIN HAL_BOARD_SUBTYPE = HAL_BOARD_SUBTYPE_NONE endif # 如果$(MAKECMDGOALS)中包含vrcore ifneq ($(findstring vrcore, $(MAKECMDGOALS)),) HAL_BOARD = HAL_BOARD_VRBRAIN HAL_BOARD_SUBTYPE = HAL_BOARD_SUBTYPE_NONE endif # 如果$(MAKECMDGOALS)中包含qflight ifneq ($(findstring qflight, $(MAKECMDGOALS)),) HAL_BOARD = HAL_BOARD_LINUX HAL_BOARD_SUBTYPE = HAL_BOARD_SUBTYPE_LINUX_QFLIGHT endif # 如果$(MAKECMDGOALS)中包含qurt ifneq ($(findstring qurt, $(MAKECMDGOALS)),) HAL_BOARD = HAL_BOARD_QURT HAL_BOARD_SUBTYPE = HAL_BOARD_SUBTYPE_NONE endif # 如果$(MAKECMDGOALS)中包含f4light ifneq ($(findstring f4light, $(MAKECMDGOALS)),) HAL_BOARD = HAL_BOARD_F4LIGHT HAL_BOARD_SUBTYPE = HAL_BOARD_SUBTYPE_NONE endif # 如果HAL_BOARD为空,则默认指定为SITL ifeq ($(HAL_BOARD),) HAL_BOARD = HAL_BOARD_SITL HAL_BOARD_SUBTYPE = HAL_BOARD_SUBTYPE_NONE endif
参考:https://blog.csdn.net/oqqENvY12/article/details/60581036
https://blog.csdn.net/jon_wei/article/details/53140384
https://blog.csdn.net/jon_wei/article/details/52984495