mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-03 03:31:41 +03:00
feat(tools): Added listing of CMake custom targets in idf.py --help
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
"""Policy for which phony CMake targets appear under ``CMake Custom Targets`` in ``idf.py --help``.
|
||||
|
||||
Exact-name suppression is in ``IDF_PY_HELP_SKIP_TARGETS``; CI asserts that list plus the shared shape policy
|
||||
(``help_phony_name_passes_shape_policy``: path chars, prefixes, suffixes, substrings) against real help output in
|
||||
``tools/test_build_system/test_common.py``. Adjust those rules when new classes of internal phony targets appear.
|
||||
|
||||
Note: ``PHONY_BUILD_LINE_RE`` is intentionally permissive; callers must still enforce the two-step contract of
|
||||
matching the line then checking the extracted rule equals ``phony`` (case-insensitive).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from collections.abc import Set
|
||||
|
||||
# ``cmake --build … --target help`` / ``ninja -t targets`` lines: ``name: phony`` (last ``:`` before rule).
|
||||
PHONY_BUILD_LINE_RE = re.compile(r'^(.+):\s*(\S+)\s*$')
|
||||
# ``build.ninja`` lines: ``build <name>: phony``.
|
||||
NINJA_BUILD_PHONY_RE = re.compile(r'^build\s+(.+?)\s*:\s*phony(?:\s|$)')
|
||||
|
||||
# ``cmake --build`` may still run generator checks; cap wall time for help-only invocations.
|
||||
CMAKE_BUILD_HELP_TIMEOUT_SEC = 15
|
||||
# ``ninja -t targets`` is a local metadata query; keep tight so ``idf.py --help`` stays responsive.
|
||||
NINJA_TARGETS_HELP_TIMEOUT_SEC = 5
|
||||
|
||||
# Targets whose names look like filesystem paths are never user-facing phony labels in this section.
|
||||
# Internal / generated prefixes from CMake, Ninja, ESP-IDF component graphs (not project-level custom commands).
|
||||
# Note: this also suppresses user-defined custom targets beginning with ``lib``.
|
||||
HELP_PHONY_NAME_PREFIXES: tuple[str, ...] = ('_', 'cmake_', 'gen_', 'lib', 'esp-idf')
|
||||
|
||||
# File-like / glue targets (``*_args``, ``.cmake``, etc.) that ``help`` lists but are not interactive commands.
|
||||
HELP_PHONY_NAME_SUFFIXES: tuple[str, ...] = (
|
||||
'_args',
|
||||
'_bin',
|
||||
'_preprocess',
|
||||
'_table',
|
||||
'.cmake',
|
||||
'.txt',
|
||||
'.json',
|
||||
'.ld',
|
||||
'.a',
|
||||
'.in',
|
||||
'.ninja',
|
||||
)
|
||||
|
||||
# Doc and partition-table helper phonys often register as top-level names; hide by substring, not exact match only.
|
||||
HELP_PHONY_NAME_SUBSTRINGS: tuple[str, ...] = ('apidoc', 'partition_table')
|
||||
|
||||
IDF_PY_HELP_SKIP_TARGETS = frozenset(
|
||||
{
|
||||
# Generic clean/rule placeholder from Make/Ninja help output, not a project custom target.
|
||||
'C',
|
||||
'app_check_size',
|
||||
'builtin',
|
||||
'custom_bundle',
|
||||
'edit_cache',
|
||||
'encrypted-bootloader-flash',
|
||||
'encrypted-partition-table-flash',
|
||||
'everest',
|
||||
'help',
|
||||
'install',
|
||||
'lib',
|
||||
'list_install_components',
|
||||
'mbedcrypto',
|
||||
'mbedtls',
|
||||
'mbedx509',
|
||||
'p256m',
|
||||
'rebuild_cache',
|
||||
'tfpsacrypto',
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def help_phony_name_passes_shape_policy(name: str) -> bool:
|
||||
"""True if ``name`` passes path / prefix / suffix / substring filters (no ``idf.py`` action or exact-skip check)."""
|
||||
if not name or '/' in name or '\\' in name:
|
||||
return False
|
||||
# Defensive: Ninja/CMake help text can contain tokens that are not real target names (e.g. separators like "|").
|
||||
# Target names in this section are expected to be single, whitespace-free identifiers.
|
||||
if any(c.isspace() for c in name) or '|' in name:
|
||||
return False
|
||||
if name.startswith(HELP_PHONY_NAME_PREFIXES):
|
||||
return False
|
||||
if name.endswith(HELP_PHONY_NAME_SUFFIXES):
|
||||
return False
|
||||
if any(s in name for s in HELP_PHONY_NAME_SUBSTRINGS):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def strip_cmake_help_listing_quotes(line: str) -> str:
|
||||
"""CMake/Make ``--target help`` sometimes wraps a target in matching quotes; unwrap one layer."""
|
||||
if len(line) >= 2 and line[0] in '\'"' and line[-1] == line[0]:
|
||||
return line[1:-1]
|
||||
return line
|
||||
|
||||
|
||||
def split_ninja_build_outputs(outputs: str) -> list[str]:
|
||||
"""Split a Ninja `build` output list (may be multi-output) into individual target names."""
|
||||
return [n for n in outputs.split() if n]
|
||||
|
||||
|
||||
def should_list_custom_target(name: str, defined: Set[str]) -> bool:
|
||||
"""Return True if ``name`` should be shown as a CMake custom target in ``idf.py --help``."""
|
||||
if not help_phony_name_passes_shape_policy(name):
|
||||
return False
|
||||
if name in defined or name in IDF_PY_HELP_SKIP_TARGETS:
|
||||
return False
|
||||
return True
|
||||
Reference in New Issue
Block a user