Ardupilot源码编译(一)

    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

猜你喜欢

转载自blog.csdn.net/mou_it/article/details/80406017