PX4中,make xxx_default到底都干了些什么(1)

这篇文章的灵感来自于上篇文章px4 make 固件的顺序和过程细节,写完发现中间有一些忽略的细节。补充一下

希望点赞和收藏❤️

上篇的文章中给出了编译的全流程,如下所示。本篇文章介绍A-D环节。

    A[make命令] --> B[读取顶级Makefile]
    B --> C[调用boards_dir扫描]
    C --> D[定位板级目录]
    D --> E[加载default.px4board]
    E --> F[初始化CMake系统]
    F --> G[加载平台级CMake]
    G --> H[架构级配置]
    H --> I[驱动层编译]
    I --> J[应用层编译]
    J --> K[生成固件]

在px4目录下我们输入命令 make holybro_kakuteh7_default就会在命令窗口开始编译过程。编译的顶级入口是根目录下的Makefile文件,和Cmakelists.txt文件。这两个文件分别是make和cmake的入口。

用户命令 make holybro_kakuteh7_default 首先由 ​​Makefile处理,接下来我们仔细阅读这个文件。有些语法读不懂,直接deepseek和豆包了。我们逐行分析。

ifeq ($(wildcard .git),)
    $(error YOU HAVE TO USE GIT TO DOWNLOAD THIS REPOSITORY. ABORTING.)
endif
    强制要求使用Git仓库(检查.git目录是否存在)

所以如果你的代码不是通过git clone下载的,会编译失败,因为代码本身会以来其他git仓库的子模块。

all: px4_sitl_default
**`all`** 是一个伪目标(phony target),它是Makefile中的默认目标。
当你在命令行中直接运行`make`(不指定任何目标)时,Make工具会自动选择`all`目标来执行。

**`px4_sitl_default`** 是`all`目标的依赖项。这表示`all`目标的构建依赖于`px4_sitl_default`目标的完成。

这一行确保了默认的构建行为是构建`px4_sitl_default`配置。换句话说,运行`make`等价于运行`make px4_sitl_default`。

- `px4_sitl_default` 是PX4固件的一个特定配置,代表“Software In The Loop”(SITL)的默认仿真环境。它用于在主机上运行PX4的仿真版本,而不需要实际的硬件。- 这种设计是Makefile的常见模式,通过`all`目标提供一个默认的构建入口,方便用户直接使用`make`命令。
# define a space character to be able to explicitly find it in strings
space := $(subst ,, )

如英文所示,定义了一个名为space 的变量,其值为一个空格字符

  • 解释

    • $(subst FROM,TO,TEXT) 是 Makefile 的字符串替换函数。

    • 这里 FROMTO 都是空(,,),TEXT 是一个空格( )。

    • 所以 $(subst ,, ) 的结果就是一个空格字符。

  • 用途

    • 在 Makefile 中,空格有时需要显式处理,避免解析错误。这里可能是为了后续的字符串操作做准备。

define make_list
     $(shell [ -f .github/workflows/compile_${1}.yml ] && cat .github/workflows/compile_${1}.yml | sed -E 's|[[:space:]]+(.*),|check_\1|g' | grep check_${2})
endef

定义一个名为 make_list 的多行函数(Makefile 中的 define 类似于其他语言中的函数定义)。

  • ${1}:第一个参数,通常是平台类型(如 nuttxlinux)。

  • ${2}:第二个参数,可选过滤条件(如 px4nxp)。

检查文件是否存在

  • [ -f .github/workflows/compile_${1}.yml ]:检查 .github/workflows/compile_${1}.yml 文件是否存在。

  • 如果存在,则执行后续命令(&& 表示逻辑与)。

读取文件内容

  • cat .github/workflows/compile_${1}.yml:输出文件内容。

正则替换

  • sed -E 's|[[:space:]]+(.*),|check_\1|g'

    • [[:space:]]+:匹配一个或多个空白字符(空格、制表符等)。

    • (.*),:捕获逗号前的所有字符(\1 引用捕获的内容)。

    • 替换为 check_\1,例如将 px4_fmu-v2_default, 变成 check_px4_fmu-v2_default

过滤目标

  • grep check_${2}:如果 ${2} 有值,则只保留包含 check_${2} 的行(否则输出所有行)。

define make_list 这是一个函数定义,不会被直接执行,后续代码会进行调用。这个函数用于从 .github/workflows 的 YAML 文件中提取构建目标列表,并添加 check_ 前缀。 make holybro_kakuteh7_default不会执行这行代码,make_list 函数是为 check_ 开头的目标(如 check_px4)服务的,通常用于测试或验证。这行代码在后面调用时再详细分析。

FIRST_ARG := $(firstword $(MAKECMDGOALS))
ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))

这两行代码用于解析 make 命令的参数,将第一个目标(FIRST_ARG)和剩余参数(ARGS)分开存储,以便后续处理。

1. FIRST_ARG := $(firstword $(MAKECMDGOALS))

  • 作用:提取 make 命令中的第一个目标

  • 分解

    • $(MAKECMDGOALS):Makefile 内置变量,表示用户输入的所有目标(如 make target1 target2 中的 target1 target2)。

    • $(firstword ...):取参数列表的第一个单词。

  • 示例

    • 输入 make holybro_kakuteh7_default upload
      FIRST_ARG = holybro_kakuteh7_default


2. ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)

  • 作用:提取 make 命令中除第一个目标外的剩余参数

  • 分解

    • $(words $(MAKECMDGOALS)):计算总参数个数。

    • $(wordlist 2, ..., $(MAKECMDGOALS)):从第 2 个参数开始提取到最后一个参数。

  • 示例

    • 输入 make holybro_kakuteh7_default upload -j4
      ARGS = upload -j4

  • FIRST_ARG:获取用户输入的主构建目标(如硬件配置或仿真目标)。

  • ARGS:获取后续参数(如 uploadtest-j4),用于控制构建行为

MAKE_PID := $(shell echo $$PPID)
j := $(shell ps T | sed -n 's|.*$(MAKE_PID).*$(MAKE).* \(-j\|--jobs\) *\([0-9][0-9]*\).*|\2|p')

# Default j for clang-tidy
j_clang_tidy := $(or $(j),4)

这段代码用于提取 make 命令的并行编译参数 -jN(例如 -j4--jobs=8),并设置默认值,主要用于优化编译和静态分析工具(如 clang-tidy)的并行执行。

  • MAKE_PID:获取父进程 ID,用于定位 make 命令的进程信息。

  • j:提取用户指定的并行编译线程数(如 -j8 中的 8)。

  • j_clang_tidy:为 clang-tidy 设置并行度,优先使用用户指定的 -jN,否则默认 4。

  • 目的:统一管理并行任务数,优化编译和静态分析的性能。

Clang-Tidy 是一个基于 LLVM/Clang 的 C/C++ 静态代码分析工具,用于检测代码中的潜在问题、风格违规和可优化的代码模式。它可以自动修复部分问题,帮助开发者提高代码质量、减少错误,并遵循最佳实践。make clang-tidy 调用 PX4 预定义的检查规则

 

NINJA_BIN := ninja  # 默认尝试使用 `ninja` 命令
ifndef NO_NINJA_BUILD  # 如果没有明确禁用 Ninja
    # 检查 `ninja` 是否可用
    # 静默运行 ninja --version,成功时返回版本号,失败返回空。
    NINJA_BUILD := $(shell $(NINJA_BIN) --version 2>/dev/null)

    # 如果 `ninja` 不可用,尝试 `ninja-build` 命令
    ifndef NINJA_BUILD
        NINJA_BIN := ninja-build
        NINJA_BUILD := $(shell $(NINJA_BIN) --version 2>/dev/null)
    endif
endif

这段代码用于 检测并配置 Ninja 构建工具,它是 PX4 构建系统的重要组成部分。

为什么需要这段代码?

  • 跨平台兼容性

    • 在 Linux 中,Ninja 通常通过 ninja 命令安装。

    • 某些系统(如旧版 Ubuntu)可能将其命名为 ninja-build
      这段代码自动处理不同名称的兼容性问题。

  • 性能优化
    Ninja 比传统 make 更快,尤其是在增量编译时。PX4 优先使用 Ninja 以加速构建。

  • 灵活控制
    通过 NO_NINJA_BUILD=1 可强制禁用 Ninja,回退到 GNU Make(用于调试或兼容旧环境)。

对 PX4 构建的影响

  • 构建工具选择
    如果 Ninja 可用,PX4 会生成 build.ninja 文件并调用 ninja 编译;否则生成 Makefile 并调用 make

  • 变量传递
    在后续代码中,PX4_MAKE 会被赋值为 $(NINJA_BIN)make

ifdef NINJA_BUILD
	PX4_CMAKE_GENERATOR := Ninja
	PX4_MAKE := $(NINJA_BIN)

	ifdef VERBOSE
		PX4_MAKE_ARGS := -v
	else
		PX4_MAKE_ARGS :=
	endif

	# Only override ninja default if -j is set.
	ifneq ($(j),)
		PX4_MAKE_ARGS := $(PX4_MAKE_ARGS) -j$(j)
	endif
else 如果未检测到 Ninja
	ifdef SYSTEMROOT # 检测 Windows 环境
		# Windows
		PX4_CMAKE_GENERATOR := "MSYS\ Makefiles" # Windows 用 MSYS Makefiles
	else
		PX4_CMAKE_GENERATOR := "Unix\ Makefiles" # Linux/macOS 用 Unix Makefiles
	endif

	# For non-ninja builds we default to -j4 默认并行数 (-j4)
	j := $(or $(j),4)
	PX4_MAKE = $(MAKE)  # 构建命令设为 make
	PX4_MAKE_ARGS = -j$(j) --no-print-directory  # 强制多线程,禁止目录切换日志
endif

 

这段代码是 PX4 构建系统的核心配置逻辑,用于根据是否检测到 Ninja 构建工具,设置不同的构建参数和生成器(Generator)

如果检测到 Ninja (ifdef NINJA_BUILD)

PX4_CMAKE_GENERATOR := Ninja  # 告诉 CMake 使用 Ninja 作为生成器
PX4_MAKE := $(NINJA_BIN)              #  实际构建命令设为 ninja 或 ninja-build

 

处理构建参数 (PX4_MAKE_ARGS)

VERBOSE 模式

VERBOSE 是一个 控制构建输出详细程度的开关变量。它的核心作用是:决定是否在编译过程中显示完整的底层命令(如编译器指令、链接参数等)

ifdef VERBOSE
    PX4_MAKE_ARGS := -v  # Ninja 的 -v 参数输出详细编译命令
else
    PX4_MAKE_ARGS :=     # 默认静默模式
endif

并行编译 (-jN)

ifneq ($(j),)  # 如果用户通过 -jN 指定了并行数
    PX4_MAKE_ARGS := $(PX4_MAKE_ARGS) -j$(j)  # 传递给 Ninja
endif

Ninja 默认会自动使用多核,-jN 仅用于覆盖其默认行为。

为什么需要这种设计?

  1. 性能优先
    Ninja 比 Make 更快,尤其在增量构建时。

  2. 跨平台兼容
    Windows 需特殊处理生成器类型。

  3. 用户体验
    自动选择最优工具,同时允许手动覆盖。

SRC_DIR := $(shell dirname "$(realpath $(lastword $(MAKEFILE_LIST)))")

# check if replay env variable is set & set build dir accordingly
ifdef replay
	BUILD_DIR_SUFFIX := _replay
else
	BUILD_DIR_SUFFIX :=
endif

CMAKE_ARGS ?=

 

这段代码是 PX4 构建系统中用于 设置关键路径和构建参数 的逻辑

SRC_DIR 定义:获取当前 Makefile 所在的绝对路径作为项目根目录

  • 分解

    • $(MAKEFILE_LIST):当前加载的 Makefile 文件列表。

    • $(lastword ...):取列表中最后一个文件(主 Makefile)。

    • $(realpath ...):转换为绝对路径(解析软链接)。

    • $(dirname ...):提取目录部分。

  • 示例
    若 Makefile 路径为 /home/user/PX4-Autopilot/Makefile,则 SRC_DIR = /home/user/PX4-Autopilot

BUILD_DIR_SUFFIX 设置

  • 作用:根据是否启用 replay 模式,决定构建目录的后缀。

    • 若定义了 replay 环境变量(如 export replay=1),则构建目录会添加 _replay 后缀(例如 build/px4_fmu-v5_default_replay)。

    • 否则无后缀(例如 build/px4_fmu-v5_default)。

  • 用途
    PX4 的 Replay 模式用于重放飞行日志,需要独立的构建目录以避免与正常构建冲突。

CMAKE_ARGS 初始化

CMAKE_ARGS ?=

作用:声明一个可被用户覆盖的 CMake 参数变量。

  • ?= 表示仅当变量未定义时才赋空值。

  • 用户可通过命令行或环境变量传递自定义 CMake 参数

例如 make CMAKE_ARGS="-DDEBUG=ON" px4_fmu-v5_default,我怎么知道CMAKE_ARGS都有哪些参数呢,可以直接查看 CMake 脚本,浏览 CMakeLists.txt文件,比如,我在px4的根目录下输入

grep -r "option(" CMakeLists.txt src/

搜索到的内容,是 PX4 项目中所有通过 CMake 的 option() 命令定义的 可配置编译选项。这些选项允许开发者在构建时自定义功能模块、调试设置等。截取部分

解释如下

PYTHON_COVERAGE启用 Python 代码覆盖率统计(用于测试)OFF
CMAKE_TESTING是否编译测试代码OFF

 其他类似。


外部模块路径配置
作用:如果用户定义了 EXTERNAL_MODULES_LOCATION 环境变量,将其作为 CMake 参数传递。
用途:指定外部模块(非 PX4 主代码库的模块)的存放路径。
ifdef EXTERNAL_MODULES_LOCATION
	override CMAKE_ARGS += -DEXTERNAL_MODULES_LOCATION:STRING=$(EXTERNAL_MODULES_LOCATION)
endif


示例

export EXTERNAL_MODULES_LOCATION=/path/to/external_modules
make px4_sitl_default

px4的功能代码块都在px4文件夹下,如果你自己定义了额外的功能模块,并且没有放在src文件夹下,那么就需要执行以上命令。

2. 构建类型配置
(1) 直接指定构建类型
如果用户通过 PX4_CMAKE_BUILD_TYPE 显式定义了构建类型(如 Debug/Release),直接传递给 CMake。
在 PX4 的构建系统中,PX4_CMAKE_BUILD_TYPE 用于指定不同的构建类型,每种类型会启用特定的编译器选项和优化策略。

ifdef PX4_CMAKE_BUILD_TYPE
	override CMAKE_ARGS += -DCMAKE_BUILD_TYPE=${PX4_CMAKE_BUILD_TYPE}

PX4_CMAKE_BUILD_TYPE都有哪些呢,我通过deepseek找到了一些

类型含义适用场景
Debug启用调试符号,禁用优化,便于调试。开发阶段(GDB 调试、崩溃分析)。
Release最大优化(如 -O3),禁用调试符号。正式发布(追求最高性能)。
RelWithDebInfo优化级别 -O2,但保留调试符号。需要平衡性能与调试的场景(如现场问题排查)。
MinSizeRel优化以减少代码体积(如 -Os)。资源受限的硬件(如 Flash 空间紧张的飞控)。

使用时,例如

# 1. 启用 Debug 构建
make px4_sitl_default PX4_CMAKE_BUILD_TYPE=Debug
(2) 自动化工具链配置(Sanitizers/Fuzzing)

如果未指定 PX4_CMAKE_BUILD_TYPE,则检查以下代码分析工具的环境变量,并自动设置对应的构建类型:
else

	# Address Sanitizer
	ifdef PX4_ASAN
		override CMAKE_ARGS += -DCMAKE_BUILD_TYPE=AddressSanitizer
	endif

	# Memory Sanitizer
	ifdef PX4_MSAN
		override CMAKE_ARGS += -DCMAKE_BUILD_TYPE=MemorySanitizer
	endif

	# Thread Sanitizer
	ifdef PX4_TSAN
		override CMAKE_ARGS += -DCMAKE_BUILD_TYPE=ThreadSanitizer
	endif

	# Undefined Behavior Sanitizer
	ifdef PX4_UBSAN
		override CMAKE_ARGS += -DCMAKE_BUILD_TYPE=UndefinedBehaviorSanitizer
	endif

	# Fuzz Testing
	ifdef PX4_FUZZ
		override CMAKE_ARGS += -DCMAKE_BUILD_TYPE=FuzzTesting
	endif

endif
环境变量对应的 CMake 构建类型作用
PX4_ASANAddressSanitizer检测内存错误(如越界访问、释放后使用)。
PX4_MSANMemorySanitizer检测未初始化的内存读取。
PX4_TSANThreadSanitizer检测多线程竞争条件。
PX4_UBSANUndefinedBehaviorSanitizer检测未定义行为(如整数溢出、空指针解引用)。
PX4_FUZZFuzzTesting启用模糊测试(Fuzzing)相关的编译选项。

实例:make px4_sitl_default PX4_ASAN=1 ,表示启用地址消毒器(ASan)。

关键点说明

  • override 关键字:确保强制覆盖 CMAKE_ARGS 中可能已存在的参数。

  • += 操作符:追加参数,而非覆盖整个变量。

  • :STRING 类型声明:显式指定 CMake 参数类型(可选,但提高可读性)。

ifdef PYTHON_EXECUTABLE
	override CMAKE_ARGS += -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE}
endif

允许用户自定义 Python 解释器的路径

  • 作用:如果用户通过环境变量 PYTHON_EXECUTABLE 指定了 Python 解释器的路径,则将其作为 CMake 参数 -DPYTHON_EXECUTABLE 传递给构建系统。

  • 关键点

    • override:确保强制覆盖 CMake 中可能已存在的同名参数。

    • +=:追加参数,不影响其他已定义的 CMAKE_ARGS

    • 使用方法

                (1) 临时指定 Python 路径

# 明确使用 /usr/bin/python3
make px4_sitl_default PYTHON_EXECUTABLE=/usr/bin/python3

                (2) 通过环境变量永久设置

# 在 shell 配置文件中设置(如 ~/.bashrc)
export PYTHON_EXECUTABLE=~/.conda/envs/px4/bin/python

 

通过 grep "PYTHON_EXECUTABLE" build/px4_sitl_default/CMakeCache.txt输出应显示指定的 Python 路径,例如:PYTHON_EXECUTABLE:FILEPATH=/usr/bin/python3

define cmake-build
	$(eval override CMAKE_ARGS += -DCONFIG=$(1))
	@$(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
	@# make sure to start from scratch if ninja build file is missing
	@if [ $(PX4_CMAKE_GENERATOR) = "Ninja" ] && [ ! -f $(BUILD_DIR)/build.ninja ]; 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

cmake-build 函数

功能:负责执行完整的 CMake 构建流程,包括配置(configure)和编译(build)。

参数

  • $(1):构建目标的名称(如 px4_fmu-v5_default)。

执行步骤

        设置配置参数  $(eval override CMAKE_ARGS += -DCONFIG=$(1)),将 -DCONFIG=<目标名> 添加到 CMAKE_ARGS 中。

        定义构建目录 @$(eval BUILD_DIR = "$(SRC_DIR)/build/$(1)"),构建路径为 PX4-Autopilot/build/<目标名>/。

        检查配置缓存 @$(call cmake-cache-check),调用 cmake-cache-check 函数,检查当前 CMAKE_ARGS 是否与缓存一致。

        清理旧构建(必要时)

        @if [ $(PX4_CMAKE_GENERATOR) = "Ninja" ] && [ -e $(BUILD_DIR)/Makefile ]; then rm -rf $(BUILD_DIR); fi
        @if [ $(PX4_CMAKE_GENERATOR) = "Ninja" ] && [ ! -f $(BUILD_DIR)/build.ninja ]; then rm -rf $(BUILD_DIR); fi。如果从 Make 切换到 Ninja,或 Ninja 构建文件丢失,则清理目录

        运行 CMake 配置 

        @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

        如果缓存不存在或配置不匹配,则重新运行 CMake。

        执行构建 cmake --build $(BUILD_DIR) -- $(PX4_MAKE_ARGS) $(ARGS),调用 cmake --build 实际编译代码,传递 PX4_MAKE_ARGS(如 -j8)和用户参数 $(ARGS)(如 upload)

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

cmake-cache-check 函数

功能

        比较当前的 CMAKE_ARGS 与构建目录中缓存的 CMake 配置,判断是否需要重新配置。

执行步骤

        提取缓存的 CMake 选项 @$(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' ))

  • 进入构建目录,运行 cmake -L 列出所有缓存变量。

  • 使用 sed 移除变量类型(如 :BOOL),格式化为 VAR=VALUE

        提取当前的 CMake 参数 @$(eval DESIRED_CMAKE_OPTIONS = $(shell echo $(CMAKE_ARGS) | sed -n 's|-D\([^[:blank:]]*=[^[:blank:]]*\)|\1|gp' )) CMAKE_ARGS 中去掉 -D 前缀,格式化为 VAR=VALUE

        验证参数一致性 @$(eval VERIFIED_CMAKE_OPTIONS = $(foreach option,$(DESIRED_CMAKE_OPTIONS),$(strip $(findstring $(option)$(space),$(CACHED_CMAKE_OPTIONS)))))检查每个当前参数是否与缓存完全匹配

        设置重新配置标志 @$(eval CMAKE_CACHE_CHECK = $(if $(findstring $(DESIRED_CMAKE_OPTIONS),$(VERIFIED_CMAKE_OPTIONS)),,y))如果不匹配,设置 CMAKE_CACHE_CHECK=y,触发重新配置。

关键设计思想

  1. 增量配置

    • 仅当参数变化时重新运行 CMake,避免不必要的重复配置。

  2. 跨生成器兼容

    • 处理 Ninja 和 Make 生成器的切换场景,确保构建目录干净。

  3. 用户参数透传

    • $(ARGS)(如 upload)传递给底层的构建工具(Ninja/Make)。

(1) 普通构建 make px4_fmu-v5_default

  • 调用 cmake-build 函数,配置并编译 px4_fmu-v5_default

(2) 带参数构建 make px4_fmu-v5_default upload -j8

  • $(ARGS) 包含 uploadPX4_MAKE_ARGS 包含 -j8

(3) 强制重新配置 rm -rf build/px4_fmu-v5_default,make px4_fmu-v5_default 删除构建目录后,cmake-cache-check 会触发重新配置。

COLOR_BLUE = \033[0;94m  # 蓝色 ANSI 转义码
NO_COLOR   = \033[m       # 重置颜色的 ANSI 转义码

define colorecho
+@echo -e '${COLOR_BLUE}${1} ${NO_COLOR}'
endef

定义了一个 带颜色输出的 Shell 回显功能,用于在终端中显示彩色的文本(这里是蓝色)

  • \033:ASCII 转义字符(Esc),表示开始控制序列。

  • [0;94m

    • 0 表示正常样式(非粗体/斜体)。

    • 94 是亮蓝色的颜色代码。

  • [m:重置所有样式和颜色。

📌 ANSI 颜色代码参考

  • 30-37:标准色(黑、红、绿、黄等)

  • 90-97:亮色(灰、亮红、亮蓝等)

  • 39:默认前景色

  • 49:默认背景色

colorecho 函数

  • 功能:输出蓝色文字,并在末尾重置颜色。

  • 参数
    ${1}:要显示的文本内容。

  • 关键符号

    • +@

      • + 表示始终执行该命令(即使 Make 运行在 -n 只打印模式)。

      • @ 抑制命令本身的回显(不显示 echo 这一行)。

    • -e:允许 echo 解释转义字符(如 \033)。

确保始终用 ${NO_COLOR} 重置,否则后续所有文本可能保持蓝色!

这篇文章先分析这么多,makefile实在太多了,下次接着看。有些直接deepseek和元宝搜的,根据自己的理解进行了整理。下篇文章继续!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值