PX4-Autopilot v1.11.1 Makefile 的一点解读

好久没关注 PX4 的更新进度,最近正好想重新搭一个仿真环境,就下载了最新的代码来看。

原本的下载地址 https://github.com/PX4/Firmware 已经更名为 https://github.com/PX4/PX4-Autopilot ,目前在浏览器里输入这两个链接都能打开。

代码中只有主目录中一个 Makefile ,而且文件长度比原本 v1.7.3 之前减少了很多,易读性大大增强。(实际上以前的我从来没看懂过,这次反而十几分钟就看懂了。)

主要就干了两件事:1、定义所有可供 make 的 targets; 2、对主要的 targets 采用了统一的形式,都采用 cmake 来实现最终的编译。

其他一些功能,比较零散,大家平时都用不到,这里就不做记录了。


先来看一下,如何定义可供 make 的 targets。

主要是 boards/ 文件夹下的 .cmake 文件,利用文件的路径和文件名来生成目标,其实就一个语句:

# Get a list of all config targets boards/*/*.cmake
ALL_CONFIG_TARGETS := $(shell find boards -maxdepth 3 -mindepth 3 ! -name '*common*' ! -name '*sdflight*' -name '*.cmake' -print | sed -e 's|boards\/||' | sed -e 's|\.cmake||' | sed -e 's|\/|_|g' | sort)

这个语句比较长,但是主体内容是用 “|” 管道连接了一个 “find” 命令,三个 “sed -e” 命令和一个 “sort” 命令。

  1. “find” 命令这句的意思是从 boards/ 文件夹下找到所有路径和名称中不包含 “common” 且不包含 “sdflight” 但是包含了 “.cmake” 的路径和文件。
  2. “sed -e” 命令用来进行字符替换,依次去掉 “boards/” 、去掉 “.cmake” 、将 “/” 替换为 “_” 最后就是一个一个不包含路径和后缀名的字符串了。
  3. "sort" 很简单,按照字母表重新排序。

将这句指令复制到终端里运行的效果如下所示:

aerotenna_ocpoc_default
airmind_mindpx-v2_default
atlflight_cmake_hexagon_bundle
atlflight_cmake_hexagon_fastrpc
atlflight_cmake_hexagon_hexagon_sdk
atlflight_cmake_hexagon_linux_app
atlflight_cmake_hexagon_qurt_flags
atlflight_cmake_hexagon_qurt_lib
atlflight_eagle_default
atlflight_eagle_qurt
atlflight_excelsior_default
atlflight_excelsior_qurt
av_x-v1_default
beaglebone_blue_default
bitcraze_crazyflie_default
cuav_nora_bootloader
cuav_nora_default
cuav_x7pro_bootloader
cuav_x7pro_default
cubepilot_cubeorange_bootloader
cubepilot_cubeorange_console
cubepilot_cubeorange_default
cubepilot_cubeyellow_console
cubepilot_cubeyellow_default
cubepilot_io-v2_default
emlid_navio2_default
holybro_durandal-v1_bootloader
holybro_durandal-v1_default
holybro_durandal-v1_stackcheck
holybro_kakutef7_default
holybro_pix32v5_default
intel_aerofc-v1_default
intel_aerofc-v1_rtps
modalai_fc-v1_default
mro_ctrl-zero-f7_default
mro_x21_default
mro_x21-777_default
nxp_fmuk66-e_default
nxp_fmuk66-e_socketcan
nxp_fmuk66-v3_default
nxp_fmuk66-v3_socketcan
nxp_fmurt1062-v1_default
nxp_rddrone-uavcan146_default
omnibus_f4sd_default
px4_fmu-v2_default
px4_fmu-v2_fixedwing
px4_fmu-v2_lpe
px4_fmu-v2_multicopter
px4_fmu-v2_rover
px4_fmu-v2_test
px4_fmu-v3_default
px4_fmu-v3_rtps
px4_fmu-v3_stackcheck
px4_fmu-v4_cannode
px4_fmu-v4_default
px4_fmu-v4_optimized
px4_fmu-v4_rtps
px4_fmu-v4_stackcheck
px4_fmu-v4pro_default
px4_fmu-v4pro_rtps
px4_fmu-v5_critmonitor
px4_fmu-v5_debug
px4_fmu-v5_default
px4_fmu-v5_fixedwing
px4_fmu-v5_irqmonitor
px4_fmu-v5_multicopter
px4_fmu-v5_optimized
px4_fmu-v5_rover
px4_fmu-v5_rtps
px4_fmu-v5_stackcheck
px4_fmu-v5x_base_phy_DP83848C
px4_fmu-v5x_default
px4_fmu-v6x_bootloader
px4_fmu-v6x_default
px4_fmu-v6x_stackcheck
px4_io-v2_default
px4_raspberrypi_default
px4_sitl_default
px4_sitl_nolockstep
px4_sitl_replay
px4_sitl_rtps
px4_sitl_test
spracing_h7extreme_default
uvify_core_default

这还没完,下面还一条指令,将所有带 “_default” 的字符串都去掉 “_default” 成为另外的指令。

# Filter for only default targets to allow omiting the "_default" postfix
CONFIG_TARGETS_DEFAULT := $(patsubst %_default,%,$(filter %_default,$(ALL_CONFIG_TARGETS)))

然后将所有字符串都作为可供 make 的 targets

all_config_targets: $(ALL_CONFIG_TARGETS)
all_default_targets: $(CONFIG_TARGETS_DEFAULT)

# All targets with just dependencies but no recipe must either be marked as phony (or have the special @: as recipe).
.PHONY: all px4_sitl_default all_config_targets all_default_targets

接下来看如何采用 cmake 实现编译。

直接上代码:

# All targets.
$(ALL_CONFIG_TARGETS):
	@$(eval PX4_CONFIG = $@)
	@$(eval CMAKE_ARGS += -DCONFIG=$(PX4_CONFIG))
	@$(call cmake-build,$(PX4_CONFIG)$(BUILD_DIR_SUFFIX))

$(CONFIG_TARGETS_DEFAULT):
	@$(eval PX4_CONFIG = $@_default)
	@$(eval CMAKE_ARGS += -DCONFIG=$(PX4_CONFIG))
	@$(call cmake-build,$(PX4_CONFIG)$(BUILD_DIR_SUFFIX))

可以看到无论是直接从路径和文件名获取的 targets, 还是去除了 “_default” 之后的 targets 都是采用了相同的规则,也就是 call cmake-build 来进行 cmake 编译。

而这里的 cmake-build 就是 Makefile 中定义的一个内部规则:

# Functions
# --------------------------------------------------------------------
# describe how to build a cmake config
define cmake-build
	@$(eval BUILD_DIR = "$(SRC_DIR)/build/$(1)")
	@# check if the desired cmake configuration matches the cache then CMAKE_CACHE_CHECK stays empty
	@$(call cmake-cache-check)
	@# make sure to start from scratch when switching from GNU Make to Ninja
	@if [ $(PX4_CMAKE_GENERATOR) = "Ninja" ] && [ -e $(BUILD_DIR)/Makefile ]; then rm -rf $(BUILD_DIR); fi
	@# only excplicitly configure the first build, if cache file already exists the makefile will rerun cmake automatically if necessary
	@if [ ! -e $(BUILD_DIR)/CMakeCache.txt ] || [ $(CMAKE_CACHE_CHECK) ]; then \
		mkdir -p $(BUILD_DIR) \
		&& cd $(BUILD_DIR) \
		&& cmake "$(SRC_DIR)" -G"$(PX4_CMAKE_GENERATOR)" $(CMAKE_ARGS) \
		|| (rm -rf $(BUILD_DIR)); \
	fi
	@# run the build for the specified target
	@cmake --build $(BUILD_DIR) -- $(PX4_MAKE_ARGS) $(ARGS)
endef

# check if the options we want to build with in CMAKE_ARGS match the ones which are already configured in the cache inside BUILD_DIR
define cmake-cache-check
	@# change to build folder which fails if it doesn't exist and CACHED_CMAKE_OPTIONS stays empty
	@# fetch all previously configured and cached options from the build folder and transform them into the OPTION=VALUE format without type (e.g. :BOOL)
	@$(eval CACHED_CMAKE_OPTIONS = $(shell cd $(BUILD_DIR) 2>/dev/null && cmake -L 2>/dev/null | sed -n 's|\([^[:blank:]]*\):[^[:blank:]]*\(=[^[:blank:]]*\)|\1\2|gp' ))
	@# transform the options in CMAKE_ARGS into the OPTION=VALUE format without -D
	@$(eval DESIRED_CMAKE_OPTIONS = $(shell echo $(CMAKE_ARGS) | sed -n 's|-D\([^[:blank:]]*=[^[:blank:]]*\)|\1|gp' ))
	@# find each currently desired option in the already cached ones making sure the complete configured string value is the same
	@$(eval VERIFIED_CMAKE_OPTIONS = $(foreach option,$(DESIRED_CMAKE_OPTIONS),$(strip $(findstring $(option)$(space),$(CACHED_CMAKE_OPTIONS)))))
	@# if the complete list of desired options is found in the list of verified options we don't need to reconfigure and CMAKE_CACHE_CHECK stays empty
	@$(eval CMAKE_CACHE_CHECK = $(if $(findstring $(DESIRED_CMAKE_OPTIONS),$(VERIFIED_CMAKE_OPTIONS)),,y))
endef

举个例子:

比如要编译软件在环仿真 SITL 并且用 gazebo 作为仿真器,只需要在命令行中敲一下 make px4_sitl gazebo

mkdir -p build/px4_sitl_default

cd build/px4_sitl_default

cmake "主目录" -G"Ninja" -DCONFIG=px4_sitl_default

cmake --build build/px4_sitl_default -- gazebo

这样一来,就可以在 build/ 文件夹下编译完成所需的目标了。

这里着重就要去看主目录下的 CMakeList.txt 和之后生成的编译目录中文件的内容了。

 

你可能感兴趣的:(PX4代码分析)