mirror of
https://github.com/PX4/PX4-Autopilot.git
synced 2026-07-24 15:27:41 +08:00
* feat(secure_bootloader): add ed25519 key and signing helpers
Scaffolding for PX4 secure-boot firmware signing, split into two
self-contained scripts:
- generate_signing_keys.py: produces <name>.json (private+public hex)
for use by sign_firmware.py and <name>.pub (C-array public key)
for inclusion in the bootloader build via CONFIG_PUBLIC_KEYn.
Refuses to overwrite existing private-key files.
- sign_firmware.py: pads an input .bin to a 4-byte boundary and
appends a 64-byte ed25519 signature, producing a file that drops
directly into the flash slot described by the image TOC.
Optionally appends an R&D certificate binary after the signature.
Replaces the signing path of the old Tools/cryptotools.py that was
removed along with the log-encryption cleanup; the new layout keeps
bootloader-signing tooling separate from log encryption to avoid
confusing the two independent crypto surfaces.
* fix(bootloader): panic if px4_get_secure_random is ever called
sw_crypto's crypto_open() unconditionally references
px4_get_secure_random from its XCHACHA20 path, so even a bootloader
that only performs ed25519 signature verification (and never touches
stream ciphers) pulls in an undefined symbol at link time.
The app build resolves it through nuttx_random.c, which is gated
behind CONFIG_CRYPTO_RANDOM_POOL and only compiled in when the
NuttX random pool is enabled. That config isn't on in the tiny
bootloader NuttX defconfig, and enabling it would pull in a pile
of kernel code the bootloader doesn't need.
Supply the symbol locally, but make it call up_assert() instead of
returning zeros. Silently handing out predictable bytes would be a
serious security bug if anyone later enables the XCHACHA20 path in
the bootloader without wiring up a real RNG. Aborting makes the
mistake impossible to miss.
* fix(bootloader): add PROTO_VERIFY_SIG opcode for upload-time signature check
Today a signed-boot failure is invisible to the uploader: verify_app()
runs inside jump_to_app() after PROTO_BOOT has already rebooted the
chip, so the host sees a successful upload followed by the device
silently staying in the bootloader. There is no protocol-level signal
that the image that was just written is not going to run.
Add PROTO_VERIFY_SIG (0x39) so the host can ask the bootloader to run
find_toc() + verify_app(0) *before* the reboot and get a concrete
OK / FAILED / INVALID answer back over the still-open USB connection.
The new opcode is gated on BOOTLOADER_USE_SECURITY: bootloaders built
without secure boot return cmd_bad (INSYNC/INVALID) so an uploader
can tell "I don't know this command" apart from "verification failed".
Two subtleties required care:
1. PROG_MULTI deliberately defers the very first word of the app
image to a RAM variable (first_word) and only commits it to flash
inside PROTO_BOOT, so a partial upload can never become bootable.
But verify_app() reads directly from flash, so if we verified
before committing first_word, even a valid image would always
fail (the first four bytes at APP_LOAD_ADDRESS would still be
0xffffffff). The handler therefore mirrors the first half of the
PROTO_BOOT handler: gate on STATE_ALLOWS_REBOOT, program the
deferred first word, then run the crypto check.
2. On failure we deliberately do not try to "undo" the first-word
write — H7 flash programming granularity makes it impossible to
revert in place, and the device was going to end up in the same
reject state at the next boot either way. The improvement is
purely that the uploader sees the failure before REBOOT instead
of after.
Chose opcode 0x39 to stay clear of ArduPilot's 0x28 (READ_MULTI) and
0x40 (CHIP_FULL_ERASE), which PX4 does not currently use but which
an AP-compatible uploader might.
ArduPilot also has bootloader secure boot (monocypher ed25519, like
us) but their verification runs at boot time, not upload time — so
neither project currently solves the "upload silently wrote a bad
image" problem. This puts PX4 ahead on that.
* feat(Tools): add --image_signed to mark signed firmware for uploader
px_uploader.py only needs to run signature verification over USB for
images that actually carry a signature — asking the bootloader to
verify an unsigned image would always fail, and the extra round trip
is wasted time for the common unsigned case. It therefore needs a
reliable way to tell the two apart.
We cannot tell by inspecting the bytes: a sign_firmware.py output is
just the raw .bin with 64 bytes of ed25519 signature glued on the
end, indistinguishable in content from an unsigned image of the same
padded length. The natural place to put the flag is the .px4 JSON
envelope, which already carries board_id / version / summary / etc.
Add --image_signed to px_mkfw.py, which sets "image_signed": true
in the emitted JSON. The flag has no effect on what bytes actually
end up on the device — it just tells the uploader "this blob has a
signature, please verify it before booting".
* feat(Tools): verify firmware signature before reboot
After PROG_MULTI + GET_CRC, send a new VERIFY_SIG opcode (0x39) to
the bootloader to check the ed25519 signature over the freshly
flashed image *before* sending REBOOT. This way a signature failure
is reported as a clean error from the uploader script, instead of a
silent "device stays in bootloader after reboot" that leaves the user
guessing.
The uploader always probes VERIFY_SIG. The bootloader is the source
of truth for whether secure boot is enabled:
- INSYNC/OK -> verification passed, proceed to REBOOT
- INSYNC/FAILED -> raise; "Signature does not verify against any
trusted key" if the firmware claims to be signed,
"Secure bootloader rejected an unsigned image"
otherwise (= helpful guidance for the common
misconfiguration of uploading default firmware
to a secureboot bootloader)
- INSYNC/INVALID -> bootloader has no secure boot. Quietly proceed
unless the firmware metadata says image_signed,
in which case raise.
- recv timeout -> assume a pre-VERIFY_SIG bootloader, proceed.
Surfaces a "Verifying image signature... passed" line on the upload
status path when the firmware is marked signed, so users get a clear
positive signal that the secure-boot pipeline ran end-to-end.
Also drop the redundant logger.error in the upload() loop, which was
duplicating the error message printed by the top-level handler in
main() for every UploadError path (not specific to verify_signature,
but only became obvious once these clean error messages started
firing in normal usage).
* fix(cmake): fix .px4board variant resolution to require exact match
px4_config.cmake matched the requested CONFIG against each candidate
.px4board with `MATCHES`, which is a regex partial match. For a
config like `px4_fmu-v6x_bootloader_secureboot`, the iteration over
.px4board files (alphabetical glob order) would match
`bootloader.px4board` first — because "px4_fmu-v6x_bootloader" is a
prefix of "px4_fmu-v6x_bootloader_secureboot" — and stop, silently
selecting the wrong board config.
Use `STREQUAL` instead so each candidate has to match the full
requested CONFIG. Existing single-label cases (e.g. exact match on
`px4_fmu-v2_default` or `px4_fmu-v2`) are unaffected because they
were already exact in practice; this just plugs the prefix-match
hole that any future `<label>_<suffix>` variant would trip over.
* fix(nuttx): support bootloader_<variant> labels
Boards can ship bootloader variants beyond the default `bootloader`
label — e.g. a `bootloader_secureboot` that adds crypto + keystore
Kconfig on top of the same source tree. Two pieces of build glue
were hardcoded to the exact label `bootloader` and need to relax to
match any `bootloader_*` label:
1. platforms/nuttx/CMakeLists.txt picked the bootloader linker
script and bootloader-specific library list only when the label
was exactly `bootloader`. Any other label (including
`bootloader_secureboot`) silently fell through to the app build,
producing nonsensical link flags. Match `^bootloader` instead,
and explicitly set SCRIPT_PREFIX to `bootloader_` so all
bootloader variants share the single existing linker script
regardless of their full label.
2. platforms/nuttx/cmake/px4_impl_os.cmake selects the NuttX config
subdirectory by exact label match, falling back to `nsh` when no
matching directory exists. For `bootloader_secureboot` that fell
through to `nsh`, dragging in a full app-style NuttX with cromfs,
networking, and the full heap subsystem — a 128 KB bootloader
sector overflowed by ~50 KB. Add an intermediate fallback: if the
label starts with `bootloader` and a `bootloader/` subdir exists,
use that instead of `nsh`.
Both changes are backward-compatible: existing single-label
`bootloader` builds take exactly the same path as before. They only
gain the ability for boards to add `bootloader_<suffix>.px4board`
files without duplicating bootloader build wiring.
* feat(build): auto-sign secure-boot images via BOARD_SECUREBOOT
Add a Kconfig pair that boards can opt into:
CONFIG_BOARD_SECUREBOOT -- bool: sign the .px4 with ed25519
CONFIG_BOARD_SECUREBOOT_KEY -- string: path to JSON private key
(default: Tools/test_keys/test_keys.json)
When set, the .px4 build rule inserts a Tools/secure_bootloader/sign_firmware.py
step between the unsigned .bin and px_mkfw.py, and passes --image_signed
so the .px4 envelope's metadata flags it for the uploader's VERIFY_SIG
step. The unsigned .bin is still produced alongside the .px4, so users
can sign with their own key out-of-tree if they prefer.
A BOARD_SECUREBOOT_KEY environment variable overrides the Kconfig path
at build time, mirroring the override pattern used for CONFIG_PUBLIC_KEYn
in stub_keystore. This makes release builds practical:
BOARD_SECUREBOOT_KEY=/secure/path/release.json make px4_<board>_secureboot
Relative paths in the Kconfig are resolved against the repo root (not
the build directory) so the same value works regardless of where the
build runs from.
Default builds are byte-identical to before; the new code path is gated
on CONFIG_BOARD_SECUREBOOT being set.
* feat(boards): add secureboot demo variant + docs
Two coordinated build variants demonstrate end-to-end secure boot
on px4_fmu-v6x without touching the default builds:
px4_fmu-v6x_secureboot -- the app, with TOC + signing
px4_fmu-v6x_bootloader_secureboot -- the matching secure bootloader
App side (secureboot.px4board):
- Selects nuttx-config/scripts/secureboot-script.ld via
CONFIG_BOARD_LINKER_PREFIX. The script is a copy of the default
layout plus a fixed 0x800 reservation past the vector table for
the image TOC, and an empty .signature section at end-of-FLASH
so sign_firmware.py knows where the appended ed25519 signature
will land.
- Compiles src/toc.c (a four-entry IMAGE_MAIN_TOC matching the
layout used elsewhere in the tree) into drivers_board, gated on
PX4_BOARD_LABEL == secureboot so the default build still
produces the existing layout.
- Sets CONFIG_BOARD_SECUREBOOT=y so the .px4 build rule signs the
image with the upstream test key by default.
Bootloader side (bootloader_secureboot.px4board):
- Enables CONFIG_BOARD_CRYPTO + DRIVERS_SW_CRYPTO + DRIVERS_STUB_KEYSTORE,
which links monocypher and the stub keystore into the bootloader.
- Bakes Tools/test_keys/key0.pub in as CONFIG_PUBLIC_KEY0, paired
with the test_keys.json the app variant signs with.
- hw_config.h gates BOOTLOADER_USE_SECURITY, BOOTLOADER_SIGNING_ALGORITHM
(CRYPTO_ED25519), and BOARD_IMAGE_TOC_OFFSET (0x800) on PX4_CRYPTO,
so they only activate in this variant.
Together the two variants implement the workflow:
make px4_fmu-v6x_bootloader_secureboot # build + flash via SWD once
make px4_fmu-v6x_secureboot upload # signs with test key, verifies
Bootloader fits in 128 KB (~57 KB used) thanks to --gc-sections
stripping the unused libtomcrypt code; nothing in the bootloader
binary depends on monocypher beyond the ed25519 verifier.
Replace the bundled test key for production with
Tools/secure_bootloader/generate_signing_keys.py output and update
both .px4board files (or set BOARD_SECUREBOOT_KEY at build time) —
see docs/en/advanced_config/bootloader_secure_boot.md.
* fix(boards): cap H7 bootloader linker scripts at 128 KB
Roughly half of the H7 boards in tree had `LENGTH = 2048K` for the
bootloader sector in their bootloader_script.ld, even though the
matching app linker script places APP_LOAD_ADDRESS at 0x08020000 —
i.e. the bootloader actually only owns the first 128 KB sector.
The 2048K constraint is wrong: it lets a bootloader that grew past
the 128 KB sector silently overflow into the app sector at link
time and corrupt the start of the app on flash. The linker should
fail the build instead.
The current default bootloader is ~46 KB, well under 128 KB on every
affected board, so this change is a no-op for default builds. It
just plugs a footgun for anyone adding bootloader features (secure
boot, extra UI, network boot, ...) that would have otherwise
silently grown into the app's flash range.
Boards fixed:
3dr-style H7 reference boards: cubepilot/cubeorange,
cubepilot/cubeorangeplus, holybro/durandal-v1, narinfc/h7
vendor variants: corvon/743v1, cuav/nora, cuav/x7pro,
gearup/airbrainh743, hkust/nxt-dual, hkust/nxt-v1,
matek/h743, matek/h743-mini, matek/h743-slim,
micoair/h743, micoair/h743-aio, micoair/h743-lite,
micoair/h743-v2, x-mav/ap-h743r1, x-mav/ap-h743v2
Boards already correct (LENGTH = 128K) are unchanged.
* fix(ci): add pynacl to Python requirements
Tools/secure_bootloader/sign_firmware.py uses PyNaCl for ed25519
signing, and the .px4 build rule for boards with CONFIG_BOARD_SECUREBOOT
calls it as part of the normal build (e.g. px4_fmu-v6x_secureboot).
Without pynacl in the dev requirements, those builds fail in CI and
fresh dev setups.
* docs(update): Subedit
* docs(update): Fix example error I made
* fix(docs): document BOOT and SIG1 regions
* fix(platforms): style fix
* fix(ci): workaround to get pip dependency
* fix(ci): fall back to plain pip on older build containers
The voxl2 build image ships a pip that predates --break-system-packages
(added in pip 23.0.1), so the install step blew up with "no such option".
Modern containers enforce PEP 668 and need the flag; older ones don't
support it but also don't enforce PEP 668, so plain pip works there.
Try the modern flag first, fall back if pip rejects it.
Signed-off-by: Julian Oes <julian@oes.ch>
* fix(build): strip BUILD_DIR_SUFFIX from CONFIG in cmake-build
cmake-build was passing the full build-dir name (including any
BUILD_DIR_SUFFIX like _replay or _failsafe_web) as -DCONFIG=, which
the board-lookup in cmake/px4_config.cmake then tried to match
against <vendor>_<model>_<label> .px4board files. That used to work
by accident because px4_config.cmake matched with regex MATCHES, but
since the switch to STREQUAL (needed to disambiguate
bootloader_secureboot from bootloader) the suffixed CONFIG no longer
matches anything and LABEL ends up empty, tripping a CMake error in
kconfig.cmake.
Pass the bare CONFIG and keep the suffix only on the build dir so
both concerns are independent.
Signed-off-by: Julian Oes <julian@oes.ch>
---------
Signed-off-by: Julian Oes <julian@oes.ch>
Co-authored-by: Hamish Willee <hamishwillee@gmail.com>
696 lines
30 KiB
Makefile
696 lines
30 KiB
Makefile
############################################################################
|
|
#
|
|
# Copyright (c) 2015 - 2024 PX4 Development Team. All rights reserved.
|
|
#
|
|
# Redistribution and use in source and binary forms, with or without
|
|
# modification, are permitted provided that the following conditions
|
|
# are met:
|
|
#
|
|
# 1. Redistributions of source code must retain the above copyright
|
|
# notice, this list of conditions and the following disclaimer.
|
|
# 2. Redistributions in binary form must reproduce the above copyright
|
|
# notice, this list of conditions and the following disclaimer in
|
|
# the documentation and/or other materials provided with the
|
|
# distribution.
|
|
# 3. Neither the name PX4 nor the names of its contributors may be
|
|
# used to endorse or promote products derived from this software
|
|
# without specific prior written permission.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
|
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
# POSSIBILITY OF SUCH DAMAGE.
|
|
#
|
|
############################################################################
|
|
|
|
# Enforce the presence of the GIT repository
|
|
#
|
|
# We depend on our submodules, so we have to prevent attempts to
|
|
# compile without it being present.
|
|
ifeq ($(wildcard .git),)
|
|
$(error YOU HAVE TO USE GIT TO DOWNLOAD THIS REPOSITORY. ABORTING.)
|
|
endif
|
|
|
|
# Help
|
|
# --------------------------------------------------------------------
|
|
# Don't be afraid of this makefile, it is just passing
|
|
# arguments to cmake to allow us to keep the wiki pages etc.
|
|
# that describe how to build the px4 firmware
|
|
# the same even when using cmake instead of make.
|
|
#
|
|
# Example usage:
|
|
#
|
|
# make px4_fmu-v2_default (builds)
|
|
# make px4_fmu-v2_default upload (builds and uploads)
|
|
# make px4_fmu-v2_default test (builds and tests)
|
|
#
|
|
# This tells cmake to build the nuttx px4_fmu-v2 default config in the
|
|
# directory build/px4_fmu-v2_default and then call make
|
|
# in that directory with the target upload.
|
|
|
|
# explicity set default build target
|
|
all: px4_sitl_default
|
|
|
|
# define a space character to be able to explicitly find it in strings
|
|
space := $(subst ,, )
|
|
|
|
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
|
|
|
|
# Parsing
|
|
# --------------------------------------------------------------------
|
|
# assume 1st argument passed is the main target, the
|
|
# rest are arguments to pass to the makefile generated
|
|
# by cmake in the subdirectory
|
|
FIRST_ARG := $(firstword $(MAKECMDGOALS))
|
|
ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
|
|
|
|
# Get -j or --jobs argument as suggested in:
|
|
# https://stackoverflow.com/a/33616144/8548472
|
|
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)
|
|
|
|
NINJA_BIN := ninja
|
|
ifndef NO_NINJA_BUILD
|
|
NINJA_BUILD := $(shell $(NINJA_BIN) --version 2>/dev/null)
|
|
|
|
ifndef NINJA_BUILD
|
|
NINJA_BIN := ninja-build
|
|
NINJA_BUILD := $(shell $(NINJA_BIN) --version 2>/dev/null)
|
|
endif
|
|
endif
|
|
|
|
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
|
|
ifdef SYSTEMROOT
|
|
# Windows
|
|
PX4_CMAKE_GENERATOR := "MSYS\ Makefiles"
|
|
else
|
|
PX4_CMAKE_GENERATOR := "Unix\ Makefiles"
|
|
endif
|
|
|
|
# For non-ninja builds we default to -j4
|
|
j := $(or $(j),4)
|
|
PX4_MAKE = $(MAKE)
|
|
PX4_MAKE_ARGS = -j$(j) --no-print-directory
|
|
endif
|
|
|
|
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 ?=
|
|
|
|
# additional config parameters passed to cmake
|
|
ifdef EXTERNAL_MODULES_LOCATION
|
|
override CMAKE_ARGS += -DEXTERNAL_MODULES_LOCATION:STRING=$(EXTERNAL_MODULES_LOCATION)
|
|
endif
|
|
|
|
ifdef PX4_CMAKE_BUILD_TYPE
|
|
override CMAKE_ARGS += -DCMAKE_BUILD_TYPE=${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
|
|
|
|
endif
|
|
|
|
# Prefer the interpreter from an active Python virtual environment.
|
|
# Otherwise leave PYTHON_EXECUTABLE unset and let CMake resolve Python.
|
|
ifneq ($(strip $(VIRTUAL_ENV)),)
|
|
PYTHON_EXECUTABLE ?= $(VIRTUAL_ENV)/bin/python
|
|
endif
|
|
|
|
# Pick up specific Python path if set
|
|
ifdef PYTHON_EXECUTABLE
|
|
override CMAKE_ARGS += -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE}
|
|
endif
|
|
|
|
# Functions
|
|
# --------------------------------------------------------------------
|
|
# describe how to build a cmake config
|
|
define cmake-build
|
|
# Strip BUILD_DIR_SUFFIX (e.g. _replay, _failsafe_web) from CONFIG so the
|
|
# board lookup in cmake/px4_config.cmake sees the bare <vendor>_<model>_<label>
|
|
# even when the build dir is suffixed for variant builds.
|
|
$(eval override CMAKE_ARGS += -DCONFIG=$(patsubst %$(BUILD_DIR_SUFFIX),%,$(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)
|
|
@# NuttX builds into the shared submodule trees under platforms/nuttx/NuttX/{nuttx,apps},
|
|
@# not into build/$(1)/. Recursive make there does not treat PX4 defconfig changes as a
|
|
@# reason to recompile, so switching board configs links stale objects (e.g. kmm_* from a
|
|
@# protected build into a flat build). Wipe the submodules when the active target changes,
|
|
@# mirroring Tools/ci/build_all_runner.sh.
|
|
@mkdir -p "$(SRC_DIR)/build"
|
|
@stamp="$(SRC_DIR)/build/.last_target"; \
|
|
prev=$$(cat "$$stamp" 2>/dev/null || echo ""); \
|
|
if [ "$$prev" != "$(1)" ]; then \
|
|
[ -n "$$prev" ] && echo "switching NuttX target $$prev -> $(1): wiping submodule state"; \
|
|
git -C "$(SRC_DIR)/platforms/nuttx/NuttX/nuttx" clean -dXfq 2>/dev/null || true; \
|
|
git -C "$(SRC_DIR)/platforms/nuttx/NuttX/apps" clean -dXfq 2>/dev/null || true; \
|
|
echo "$(1)" > "$$stamp"; \
|
|
fi
|
|
@# 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
|
|
|
|
# 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
|
|
|
|
COLOR_BLUE = \033[0;94m
|
|
NO_COLOR = \033[m
|
|
|
|
define colorecho
|
|
+@echo -e '${COLOR_BLUE}${1} ${NO_COLOR}'
|
|
endef
|
|
|
|
# Get a list of all config targets boards/*/*.px4board
|
|
ALL_CONFIG_TARGETS := $(shell find boards -maxdepth 3 -mindepth 3 -name '*.px4board' -print | sed -e 's|boards\/||' | sed -e 's|\.px4board||' | sed -e 's|\/|_|g' | sort)
|
|
|
|
# ADD CONFIGS HERE
|
|
# --------------------------------------------------------------------
|
|
# Do not put any spaces between function arguments.
|
|
|
|
# All targets.
|
|
$(ALL_CONFIG_TARGETS):
|
|
@$(call cmake-build,$@$(BUILD_DIR_SUFFIX))
|
|
|
|
# Filter for only default targets to allow omiting the "_default" postfix
|
|
CONFIG_TARGETS_DEFAULT := $(patsubst %_default,%,$(filter %_default,$(ALL_CONFIG_TARGETS)))
|
|
$(CONFIG_TARGETS_DEFAULT):
|
|
@$(call cmake-build,$@_default$(BUILD_DIR_SUFFIX))
|
|
|
|
# Multi-processor boards: build all processor targets together
|
|
# VOXL2 apps processor (default) depends on SLPI DSP being built first
|
|
modalai_voxl2_default: modalai_voxl2_slpi
|
|
modalai_voxl2: modalai_voxl2_slpi
|
|
modalai_voxl2_deb: modalai_voxl2_slpi
|
|
|
|
all_config_targets: $(ALL_CONFIG_TARGETS)
|
|
all_default_targets: $(CONFIG_TARGETS_DEFAULT)
|
|
|
|
# DEB package targets: builds _default config, then runs cpack.
|
|
# Multi-processor boards (e.g. VOXL2) chain companion builds automatically
|
|
# via existing cmake prerequisites.
|
|
%_deb:
|
|
@$(call cmake-build,$(subst _deb,_default,$@)$(BUILD_DIR_SUFFIX))
|
|
@cd "$(SRC_DIR)/build/$(subst _deb,_default,$@)" && cpack -G DEB
|
|
|
|
updateconfig:
|
|
@./Tools/kconfig/updateconfig.py
|
|
|
|
# board reorganization deprecation warnings (2018-11-22)
|
|
define deprecation_warning
|
|
$(warning $(1) has been deprecated and will be removed, please use $(2)!)
|
|
endef
|
|
|
|
# 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
|
|
|
|
# Other targets
|
|
# --------------------------------------------------------------------
|
|
|
|
.PHONY: qgc_firmware px4fmu_firmware misc_qgc_extra_firmware
|
|
|
|
# QGroundControl flashable NuttX firmware
|
|
qgc_firmware: px4fmu_firmware misc_qgc_extra_firmware
|
|
|
|
# px4fmu NuttX firmware
|
|
px4fmu_firmware: \
|
|
check_px4_io-v2_default \
|
|
check_px4_fmu-v2_default \
|
|
check_px4_fmu-v3_default \
|
|
check_px4_fmu-v4_default \
|
|
check_px4_fmu-v4pro_default \
|
|
check_px4_fmu-v5_default \
|
|
check_px4_fmu-v5x_default \
|
|
sizes
|
|
|
|
misc_qgc_extra_firmware: \
|
|
check_nxp_fmuk66-v3_default \
|
|
check_mro_x21_default \
|
|
check_bitcraze_crazyflie_default \
|
|
check_bitcraze_crazyflie21_default \
|
|
check_airmind_mindpx-v2_default \
|
|
sizes
|
|
|
|
.PHONY: sizes check quick_check uorb_graphs
|
|
|
|
sizes:
|
|
@-find build -name *.elf -type f | xargs size 2> /dev/null || :
|
|
|
|
# All default targets that don't require a special build environment
|
|
check: check_px4_sitl_default px4fmu_firmware misc_qgc_extra_firmware tests check_format
|
|
|
|
# quick_check builds a single nuttx and SITL target, runs testing, and checks the style
|
|
quick_check: check_px4_sitl_test check_px4_fmu-v5_default tests check_format
|
|
|
|
check_%:
|
|
@echo
|
|
$(call colorecho,'Building' $(subst check_,,$@))
|
|
@$(MAKE) --no-print-directory $(subst check_,,$@)
|
|
@echo
|
|
|
|
all_variants_%:
|
|
@echo 'Building all $(subst all_variants_,,$@) variants:' $(filter $(subst all_variants_,,$@)_%, $(ALL_CONFIG_TARGETS))
|
|
@echo
|
|
$(foreach a,$(filter $(subst all_variants_,,$@)_%, $(ALL_CONFIG_TARGETS)), $(call cmake-build,$(a)$(BUILD_DIR_SUFFIX)))
|
|
|
|
uorb_graphs:
|
|
@./Tools/uorb_graph/create.py --src-path src --exclude-path src/examples --exclude-path src/lib/parameters --merge-depends --file Tools/uorb_graph/graph_full
|
|
@./Tools/uorb_graph/create.py --src-path src --exclude-path src/examples --exclude-path src/lib/parameters --exclude-path src/modules/mavlink --merge-depends --file Tools/uorb_graph/graph_full_no_mavlink
|
|
@$(MAKE) --no-print-directory px4_fmu-v2_default uorb_graph
|
|
@$(MAKE) --no-print-directory px4_fmu-v4_default uorb_graph
|
|
@$(MAKE) --no-print-directory px4_fmu-v5_default uorb_graph
|
|
@$(MAKE) --no-print-directory px4_fmu-v5x_default uorb_graph
|
|
@$(MAKE) --no-print-directory px4_fmu-v6x_default uorb_graph
|
|
@$(MAKE) --no-print-directory px4_sitl_default uorb_graph
|
|
|
|
px4io_update:
|
|
@$(MAKE) --no-print-directory px4_io-v2_default
|
|
@$(MAKE) --no-print-directory cubepilot_io-v2_default
|
|
# px4_io-v2_default
|
|
cp build/px4_io-v2_default/px4_io-v2_default.bin boards/ark/fmu-v6x/extras/px4_io-v2_default.bin
|
|
cp build/px4_io-v2_default/px4_io-v2_default.bin boards/holybro/durandal-v1/extras/px4_io-v2_default.bin
|
|
cp build/px4_io-v2_default/px4_io-v2_default.bin boards/holybro/pix32v5/extras/px4_io-v2_default.bin
|
|
cp build/px4_io-v2_default/px4_io-v2_default.bin boards/mro/x21/extras/px4_io-v2_default.bin
|
|
cp build/px4_io-v2_default/px4_io-v2_default.bin boards/mro/x21-777/extras/px4_io-v2_default.bin
|
|
cp build/px4_io-v2_default/px4_io-v2_default.bin boards/px4/fmu-v2/extras/px4_io-v2_default.bin
|
|
cp build/px4_io-v2_default/px4_io-v2_default.bin boards/px4/fmu-v3/extras/px4_io-v2_default.bin
|
|
cp build/px4_io-v2_default/px4_io-v2_default.bin boards/px4/fmu-v4pro/extras/px4_io-v2_default.bin
|
|
cp build/px4_io-v2_default/px4_io-v2_default.bin boards/px4/fmu-v5/extras/px4_io-v2_default.bin
|
|
cp build/px4_io-v2_default/px4_io-v2_default.bin boards/px4/fmu-v5x/extras/px4_io-v2_default.bin
|
|
cp build/px4_io-v2_default/px4_io-v2_default.bin boards/px4/fmu-v6x/extras/px4_io-v2_default.bin
|
|
cp build/px4_io-v2_default/px4_io-v2_default.bin boards/px4/fmu-v6c/extras/px4_io-v2_default.bin
|
|
# cubepilot_io-v2_default
|
|
cp build/cubepilot_io-v2_default/cubepilot_io-v2_default.bin boards/cubepilot/cubeorange/extras/cubepilot_io-v2_default.bin
|
|
cp build/cubepilot_io-v2_default/cubepilot_io-v2_default.bin boards/cubepilot/cubeorangeplus/extras/cubepilot_io-v2_default.bin
|
|
cp build/cubepilot_io-v2_default/cubepilot_io-v2_default.bin boards/cubepilot/cubeyellow/extras/cubepilot_io-v2_default.bin
|
|
git status
|
|
|
|
bootloaders_update: \
|
|
3dr_ctrl-n1_bootloader \
|
|
3dr_ctrl-zero-h7-oem-revg_bootloader \
|
|
ark_fmu-v6x_bootloader \
|
|
ark_fpv_bootloader \
|
|
ark_pi6x_bootloader \
|
|
auterion_fmu-v6s_bootloader \
|
|
auterion_fmu-v6x_bootloader \
|
|
cuav_nora_bootloader \
|
|
cuav_x7pro_bootloader \
|
|
cuav_7-nano_bootloader \
|
|
cuav_fmu-v6x_bootloader \
|
|
cuav_x25-evo_bootloader \
|
|
cuav_x25-super_bootloader \
|
|
cubepilot_cubeorange_bootloader \
|
|
cubepilot_cubeorangeplus_bootloader \
|
|
hkust_nxt-dual_bootloader \
|
|
hkust_nxt-v1_bootloader \
|
|
holybro_durandal-v1_bootloader \
|
|
holybro_kakuteh7_bootloader \
|
|
holybro_kakuteh7mini_bootloader \
|
|
holybro_kakuteh7v2_bootloader \
|
|
matek_h743_bootloader \
|
|
matek_h743-mini_bootloader \
|
|
matek_h743-slim_bootloader \
|
|
micoair_h743_bootloader \
|
|
micoair_h743-aio_bootloader \
|
|
micoair_h743-v2_bootloader \
|
|
micoair_h743-lite_bootloader \
|
|
modalai_fc-v2_bootloader \
|
|
mro_ctrl-zero-classic_bootloader \
|
|
mro_ctrl-zero-h7_bootloader \
|
|
mro_ctrl-zero-h7-oem_bootloader \
|
|
mro_pixracerpro_bootloader \
|
|
narinfc_h7_bootloader \
|
|
px4_fmu-v6c_bootloader \
|
|
px4_fmu-v6u_bootloader \
|
|
px4_fmu-v6x_bootloader \
|
|
px4_fmu-v6xrt_bootloader \
|
|
siyi_n7_bootloader
|
|
git status
|
|
|
|
.PHONY: coverity_scan
|
|
|
|
coverity_scan: px4_sitl_default
|
|
|
|
# Documentation
|
|
# --------------------------------------------------------------------
|
|
.PHONY: parameters_metadata airframe_metadata module_documentation extract_events px4_metadata
|
|
|
|
parameters_metadata:
|
|
@$(MAKE) --no-print-directory px4_sitl_default metadata_parameters ver_gen
|
|
|
|
airframe_metadata:
|
|
@$(MAKE) --no-print-directory px4_sitl_default metadata_airframes ver_gen
|
|
|
|
module_documentation:
|
|
@$(MAKE) --no-print-directory px4_sitl_default metadata_module_documentation
|
|
|
|
extract_events:
|
|
@$(MAKE) --no-print-directory px4_sitl_default metadata_extract_events ver_gen
|
|
|
|
px4_metadata: parameters_metadata airframe_metadata module_documentation extract_events
|
|
|
|
# Style
|
|
# --------------------------------------------------------------------
|
|
.PHONY: check_format format format_changed check_newlines
|
|
|
|
check_format:
|
|
$(call colorecho,'Checking formatting with astyle')
|
|
@"$(SRC_DIR)"/Tools/astyle/check_code_style_all.sh
|
|
@cd "$(SRC_DIR)" && git diff --check
|
|
|
|
format:
|
|
$(call colorecho,'Formatting with astyle')
|
|
@"$(SRC_DIR)"/Tools/astyle/check_code_style_all.sh --fix
|
|
|
|
format_changed:
|
|
$(call colorecho,'Formatting changed files with astyle')
|
|
@"$(SRC_DIR)"/Tools/astyle/check_code_style_all.sh --fix --diff-only
|
|
|
|
check_newlines:
|
|
$(call colorecho,'Checking for missing or duplicate newlines at the end of files')
|
|
@"$(SRC_DIR)"/Tools/astyle/check_newlines.sh
|
|
|
|
# Testing
|
|
# --------------------------------------------------------------------
|
|
.PHONY: tests tests_vtest_moving tests_coverage tests_mission tests_mission_coverage tests_offboard
|
|
.PHONY: rostest python_coverage
|
|
|
|
tests:
|
|
$(eval override CMAKE_ARGS += -DTESTFILTER=$(TESTFILTER))
|
|
$(eval ARGS += test_results)
|
|
$(eval ASAN_OPTIONS += color=always:check_initialization_order=1:detect_stack_use_after_return=1)
|
|
$(eval UBSAN_OPTIONS += color=always)
|
|
$(call cmake-build,px4_sitl_test)
|
|
|
|
tests_vtest_moving:
|
|
$(eval override CMAKE_ARGS += -DTESTFILTER=$(if $(TESTFILTER),$(TESTFILTER),VTE))
|
|
$(eval override CMAKE_ARGS += -DCMAKE_TESTING=ON)
|
|
$(eval ARGS += test_results)
|
|
$(eval ASAN_OPTIONS += color=always:check_initialization_order=1:detect_stack_use_after_return=1)
|
|
$(eval UBSAN_OPTIONS += color=always)
|
|
$(call cmake-build,px4_sitl_vtest-moving)
|
|
|
|
# work around lcov bug #316; remove once lcov is fixed (see https://github.com/linux-test-project/lcov/issues/316)
|
|
LCOBUG = --ignore-errors mismatch,negative
|
|
tests_coverage:
|
|
@$(MAKE) clean
|
|
@$(MAKE) --no-print-directory tests PX4_CMAKE_BUILD_TYPE=Coverage
|
|
@mkdir -p coverage
|
|
@lcov --directory build/px4_sitl_test \
|
|
--base-directory build/px4_sitl_test \
|
|
--gcov-tool gcov \
|
|
--capture \
|
|
$(LCOBUG) \
|
|
-o coverage/lcov.info
|
|
|
|
|
|
rostest: px4_sitl_default
|
|
@$(MAKE) --no-print-directory px4_sitl_default sitl_gazebo-classic
|
|
|
|
tests_integration: px4_sitl_default
|
|
@$(MAKE) --no-print-directory px4_sitl_default sitl_gazebo-classic
|
|
@$(MAKE) --no-print-directory px4_sitl_default mavsdk_tests
|
|
@"$(SRC_DIR)"/test/mavsdk_tests/mavsdk_test_runner.py --speed-factor 20 test/mavsdk_tests/configs/sitl.json
|
|
|
|
tests_integration_coverage:
|
|
@$(MAKE) clean
|
|
@$(MAKE) --no-print-directory px4_sitl_default PX4_CMAKE_BUILD_TYPE=Coverage
|
|
@$(MAKE) --no-print-directory px4_sitl_default sitl_gazebo-classic
|
|
@$(MAKE) --no-print-directory px4_sitl_default mavsdk_tests
|
|
@"$(SRC_DIR)"/test/mavsdk_tests/mavsdk_test_runner.py --speed-factor 20 test/mavsdk_tests/configs/sitl.json
|
|
@mkdir -p coverage
|
|
@lcov --directory build/px4_sitl_default --base-directory build/px4_sitl_default --gcov-tool gcov --capture -o coverage/lcov.info
|
|
|
|
tests_mission: rostest
|
|
@"$(SRC_DIR)"/test/rostest_px4_run.sh mavros_posix_tests_missions.test
|
|
|
|
rostest_run: px4_sitl_default
|
|
@$(MAKE) --no-print-directory px4_sitl_default sitl_gazebo-classic
|
|
@"$(SRC_DIR)"/test/rostest_px4_run.sh $(TEST_FILE) mission:=$(TEST_MISSION) vehicle:=$(TEST_VEHICLE)
|
|
|
|
tests_mission_coverage:
|
|
@$(MAKE) clean
|
|
@$(MAKE) --no-print-directory px4_sitl_default PX4_CMAKE_BUILD_TYPE=Coverage
|
|
@$(MAKE) --no-print-directory px4_sitl_default sitl_gazebo-classic PX4_CMAKE_BUILD_TYPE=Coverage
|
|
@"$(SRC_DIR)"/test/rostest_px4_run.sh mavros_posix_test_mission.test mission:=VTOL_mission_1 vehicle:=standard_vtol
|
|
@$(MAKE) --no-print-directory px4_sitl_default generate_coverage
|
|
|
|
tests_offboard: rostest
|
|
@"$(SRC_DIR)"/test/rostest_px4_run.sh mavros_posix_tests_offboard_attctl.test
|
|
@"$(SRC_DIR)"/test/rostest_px4_run.sh mavros_posix_tests_offboard_posctl.test
|
|
@"$(SRC_DIR)"/test/rostest_px4_run.sh mavros_posix_tests_offboard_rpyrt_ctl.test
|
|
|
|
python_coverage:
|
|
@mkdir -p "$(SRC_DIR)"/build/python_coverage
|
|
@cd "$(SRC_DIR)"/build/python_coverage && cmake "$(SRC_DIR)" $(CMAKE_ARGS) -G"$(PX4_CMAKE_GENERATOR)" -DCONFIG=px4_sitl_default -DPYTHON_COVERAGE=ON
|
|
@$(PX4_MAKE) -C "$(SRC_DIR)"/build/python_coverage
|
|
@$(PX4_MAKE) -C "$(SRC_DIR)"/build/python_coverage metadata_airframes
|
|
@$(PX4_MAKE) -C "$(SRC_DIR)"/build/python_coverage metadata_parameters
|
|
#@$(PX4_MAKE) -C "$(SRC_DIR)"/build/python_coverage module_documentation # TODO: fix within coverage.py
|
|
@coverage combine `find . -name .coverage\*`
|
|
@coverage report -m
|
|
|
|
|
|
# static analyzers (scan-build, clang-tidy, cppcheck)
|
|
# --------------------------------------------------------------------
|
|
.PHONY: scan-build px4_sitl_default-clang px4_sitl_default-clang-test clang-ci clang-tidy clang-tidy-fix
|
|
.PHONY: cppcheck shellcheck_all validate_module_configs
|
|
|
|
scan-build:
|
|
@export CCC_CC=clang
|
|
@export CCC_CXX=clang++
|
|
@rm -rf "$(SRC_DIR)"/build/px4_sitl_default-scan-build
|
|
@rm -rf "$(SRC_DIR)"/build/scan-build/report_latest
|
|
@mkdir -p "$(SRC_DIR)"/build/px4_sitl_default-scan-build
|
|
@cd "$(SRC_DIR)"/build/px4_sitl_default-scan-build && scan-build cmake "$(SRC_DIR)" -GNinja -DCONFIG=px4_sitl_default
|
|
@scan-build -o "$(SRC_DIR)"/build/scan-build cmake --build "$(SRC_DIR)"/build/px4_sitl_default-scan-build
|
|
@find "$(SRC_DIR)"/build/scan-build -maxdepth 1 -mindepth 1 -type d -exec cp -r "{}" "$(SRC_DIR)"/build/scan-build/report_latest \;
|
|
|
|
px4_sitl_default-clang:
|
|
@mkdir -p "$(SRC_DIR)"/build/px4_sitl_default-clang
|
|
@cd "$(SRC_DIR)"/build/px4_sitl_default-clang && cmake "$(SRC_DIR)" $(CMAKE_ARGS) -G"$(PX4_CMAKE_GENERATOR)" -DCONFIG=px4_sitl_default -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
|
|
@$(PX4_MAKE) -C "$(SRC_DIR)"/build/px4_sitl_default-clang
|
|
|
|
# Clang SITL configure with BUILD_TESTING=ON so test files land in
|
|
# compile_commands.json with resolved gtest/fuzztest includes. Used by CI
|
|
# to produce a compilation database for diff-based clang-tidy that can
|
|
# lint test files. Configure only: we don't build the test binaries here,
|
|
# just generate the database.
|
|
px4_sitl_default-clang-test:
|
|
@mkdir -p "$(SRC_DIR)"/build/px4_sitl_default-clang-test
|
|
@cd "$(SRC_DIR)"/build/px4_sitl_default-clang-test && cmake "$(SRC_DIR)" $(CMAKE_ARGS) -G"$(PX4_CMAKE_GENERATOR)" -DCONFIG=px4_sitl_default -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_TESTING=ON
|
|
|
|
# CI-oriented target that prepares both clang build directories used by
|
|
# the Static Analysis workflow:
|
|
# - px4_sitl_default-clang: full build, BUILD_TESTING=OFF.
|
|
# Used by `make clang-tidy` (push-to-main) and run-clang-tidy-pr.py.
|
|
# - px4_sitl_default-clang-test: configure-only, BUILD_TESTING=ON.
|
|
# Used by clang-tidy-diff-18.py so test files are in the
|
|
# compilation database with resolved gtest/fuzztest includes.
|
|
# Running one target ensures both dirs exist before any clang-tidy
|
|
# variant runs, and keeps the workflow free of raw cmake invocations.
|
|
clang-ci: px4_sitl_default-clang px4_sitl_default-clang-test
|
|
|
|
# Paths to exclude from clang-tidy (auto-generated from .gitmodules + manual additions):
|
|
# - All submodules (external code we consume, not edit)
|
|
# - Test code (allowed looser style)
|
|
# - Example code (educational, not production)
|
|
# - Vendored third-party code (e.g., CMSIS_5)
|
|
# - NuttX-only drivers excluded at CMake level (mcp_common); I2C-dependent libs excluded here (smbus)
|
|
# - GPIO excluded here (NuttX platform headers)
|
|
# - Emscripten failsafe web build: source path + Unity build path (failsafe_test.dir)
|
|
# because CMake Unity Builds merge sources into a generated .cxx under build/
|
|
#
|
|
# To add manual exclusions, append to CLANG_TIDY_EXCLUDE_EXTRA below.
|
|
# Submodules are automatically excluded - no action needed when adding new ones.
|
|
CLANG_TIDY_SUBMODULES := $(shell git config --file .gitmodules --get-regexp path | awk '{print $$2}' | tr '\n' '|' | sed 's/|$$//')
|
|
CLANG_TIDY_EXCLUDE_EXTRA := src/systemcmds/tests|src/examples|src/modules/gyro_fft/CMSIS_5|src/lib/drivers/smbus|src/drivers/gpio|src/modules/commander/failsafe/emscripten|failsafe_test\.dir|\.pb\.cc
|
|
CLANG_TIDY_EXCLUDE := $(CLANG_TIDY_SUBMODULES)|$(CLANG_TIDY_EXCLUDE_EXTRA)
|
|
|
|
clang-tidy: px4_sitl_default-clang
|
|
@cd "$(SRC_DIR)"/build/px4_sitl_default-clang && "$(SRC_DIR)"/Tools/run-clang-tidy.py -header-filter=".*\.hpp" -j$(j_clang_tidy) -exclude="$(CLANG_TIDY_EXCLUDE)" -p .
|
|
|
|
# to automatically fix a single check at a time, eg modernize-redundant-void-arg
|
|
# % run-clang-tidy-4.0.py -fix -j4 -checks=-\*,modernize-redundant-void-arg -p .
|
|
clang-tidy-fix: px4_sitl_default-clang
|
|
@cd "$(SRC_DIR)"/build/px4_sitl_default-clang && "$(SRC_DIR)"/Tools/run-clang-tidy.py -header-filter=".*\.hpp" -j$(j_clang_tidy) -exclude="$(CLANG_TIDY_EXCLUDE)" -fix -p .
|
|
|
|
# TODO: Fix cppcheck errors then try --enable=warning,performance,portability,style,unusedFunction or --enable=all
|
|
cppcheck: px4_sitl_default
|
|
@mkdir -p "$(SRC_DIR)"/build/cppcheck
|
|
@cppcheck -i"$(SRC_DIR)"/src/examples --enable=performance --std=c++14 --std=c99 --std=posix --project="$(SRC_DIR)"/build/px4_sitl_default/compile_commands.json --xml-version=2 2> "$(SRC_DIR)"/build/cppcheck/cppcheck-result.xml > /dev/null
|
|
@cppcheck-htmlreport --source-encoding=ascii --file="$(SRC_DIR)"/build/cppcheck/cppcheck-result.xml --report-dir="$(SRC_DIR)"/build/cppcheck --source-dir="$(SRC_DIR)"/src/
|
|
|
|
shellcheck_all:
|
|
@"$(SRC_DIR)"/Tools/run-shellcheck.sh "$(SRC_DIR)"/ROMFS/px4fmu_common/
|
|
@make px4_fmu-v5_default shellcheck
|
|
|
|
validate_module_configs:
|
|
@find "$(SRC_DIR)"/src/modules "$(SRC_DIR)"/src/drivers "$(SRC_DIR)"/src/lib -name *.yaml -type f \
|
|
-not -path "$(SRC_DIR)/src/lib/mixer_module/*" \
|
|
-not -path "$(SRC_DIR)/src/modules/uxrce_dds_client/dds_topics.yaml" \
|
|
-not -path "$(SRC_DIR)/src/modules/zenoh/dds_topics.yaml" \
|
|
-not -path "$(SRC_DIR)/src/modules/zenoh/zenoh-pico/*" \
|
|
-not -path "$(SRC_DIR)/src/lib/events/libevents/*" \
|
|
-not -path "$(SRC_DIR)/src/lib/cdrstream/*" \
|
|
-not -path "$(SRC_DIR)/src/lib/crypto/libtommath/*" \
|
|
-not -path "$(SRC_DIR)/src/lib/tensorflow_lite_micro/*" -print0 | \
|
|
xargs -0 "$(SRC_DIR)"/Tools/validate_yaml.py --schema-file "$(SRC_DIR)"/validation/module_schema.yaml
|
|
|
|
# Cleanup
|
|
# --------------------------------------------------------------------
|
|
.PHONY: clean submodulesclean submodulesupdate distclean
|
|
|
|
clean:
|
|
@[ ! -d "$(SRC_DIR)/build" ] || find "$(SRC_DIR)/build" -mindepth 1 -maxdepth 1 -type d -exec sh -c "echo {}; cmake --build {} -- clean || rm -rf {}" \; # use generated build system to clean, wipe build directory if it fails
|
|
@git submodule foreach git clean -dX --force # some submodules generate build artifacts in source
|
|
|
|
submodulesclean:
|
|
@git submodule foreach --quiet --recursive git clean -ff -x -d
|
|
@git submodule update --quiet --init --recursive --force || true
|
|
@git submodule sync --recursive
|
|
@git submodule update --init --recursive --force --jobs 4
|
|
|
|
submodulesupdate:
|
|
@git submodule update --quiet --init --recursive --jobs 4 || true
|
|
@git submodule sync --recursive
|
|
@git submodule update --init --recursive --jobs 4
|
|
@git fetch --all --tags --recurse-submodules=yes --jobs=4
|
|
|
|
distclean:
|
|
@git submodule deinit --force $(SRC_DIR)
|
|
@rm -rf "$(SRC_DIR)/build"
|
|
@git clean --force -X "$(SRC_DIR)/msg/" "$(SRC_DIR)/platforms/" "$(SRC_DIR)/posix-configs/" "$(SRC_DIR)/ROMFS/" "$(SRC_DIR)/src/" "$(SRC_DIR)/test/" "$(SRC_DIR)/Tools/"
|
|
|
|
# Help / Error / Misc
|
|
# --------------------------------------------------------------------
|
|
|
|
# All other targets are handled by PX4_MAKE. Add a rule here to avoid printing an error.
|
|
%:
|
|
$(if $(filter $(FIRST_ARG),$@), \
|
|
$(error "Make target $@ not found. It either does not exist or $@ cannot be the first argument. Use '$(MAKE) list_config_targets' to get a list of all possible [configuration] targets."),@#)
|
|
|
|
# Print a list of non-config targets (based on http://stackoverflow.com/a/26339924/1487069)
|
|
help:
|
|
@echo "Usage: $(MAKE) <target>"
|
|
@echo "Where <target> is one of:"
|
|
@$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | \
|
|
awk -v RS= -F: '/(^|\n)# Files(\n|$$)/,/(^|\n)# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | \
|
|
egrep -v -e '^[^[:alnum:]]' -e '^($(subst $(space),|,$(ALL_CONFIG_TARGETS)))$$' -e '_default$$' -e '^(Makefile)'
|
|
@echo
|
|
@echo "Or, $(MAKE) <config_target> [<make_target(s)>]"
|
|
@echo "Use '$(MAKE) list_config_targets' for a list of configuration targets."
|
|
|
|
# Print a list of all config targets.
|
|
list_config_targets:
|
|
@for targ in $(patsubst %_default,%[_default],$(ALL_CONFIG_TARGETS)); do echo $$targ; done
|
|
|
|
check_nuttx : $(call make_list,nuttx) \
|
|
sizes
|
|
|
|
check_linux : $(call make_list,linux) \
|
|
sizes
|
|
|
|
check_px4: $(call make_list,nuttx,"px4") \
|
|
sizes
|
|
|
|
check_nxp: $(call make_list,nuttx,"nxp") \
|
|
sizes
|
|
|
|
# helpers for running olddefconfig (nuttx) and px4_savedefconfig on all boards
|
|
.PHONY: all_oldconfig all_px4_savedefconfig
|
|
all_oldconfig:
|
|
@for targ in $(ALL_CONFIG_TARGETS); do $(MAKE) $$targ oldconfig; done
|
|
|
|
all_px4_savedefconfig:
|
|
@for targ in $(ALL_CONFIG_TARGETS); do $(MAKE) $$targ px4_savedefconfig; done
|
|
|
|
.PHONY: failsafe_web run_failsafe_web_server
|
|
failsafe_web:
|
|
@if ! command -v emcc; then echo -e "Install emscripten first: https://emscripten.org/docs/getting_started/downloads.html\nAnd source the env: source <path>/emsdk_env.sh"; exit 1; fi
|
|
@$(MAKE) --no-print-directory px4_sitl_default failsafe_test parameters_xml \
|
|
PX4_CMAKE_BUILD_TYPE=Release BUILD_DIR_SUFFIX=_failsafe_web \
|
|
CMAKE_ARGS="-DCMAKE_CXX_COMPILER=em++ -DCMAKE_C_COMPILER=emcc"
|
|
run_failsafe_web_server: failsafe_web
|
|
@cd build/px4_sitl_default_failsafe_web && \
|
|
python3 -m http.server
|
|
|
|
# Generate reference documentation for uORB messages
|
|
.PHONY: msg_docs
|
|
msg_docs:
|
|
$(call colorecho,'Generating uORB message reference docs')
|
|
@mkdir -p build/msg_docs
|
|
@./Tools/msg/generate_msg_docs.py -d build/msg_docs
|