Skip to content

Commit de5fb4f

Browse files
authored
Doxygen "group" fixes (#2591)
- Add missing libraries to docs/index.h - Remove duplicate libraries from docs/index.h - Add new script to match up doxygen groups with the PICO_CONFIG groups
1 parent 50b4a22 commit de5fb4f

File tree

2 files changed

+139
-5
lines changed

2 files changed

+139
-5
lines changed

docs/index.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* @{
1616
* \cond hardware_adc \defgroup hardware_adc hardware_adc \endcond
1717
* \cond hardware_base \defgroup hardware_base hardware_base \endcond
18-
* \cond hardware_bootlock \defgroup hardware_bootlock hardware_bootlock \endcond
18+
* \cond hardware_boot_lock \defgroup hardware_boot_lock hardware_boot_lock \endcond
1919
* \cond hardware_claim \defgroup hardware_claim hardware_claim \endcond
2020
* \cond hardware_clocks \defgroup hardware_clocks hardware_clocks \endcond
2121
* \cond hardware_divider \defgroup hardware_divider hardware_divider \endcond
@@ -32,7 +32,6 @@
3232
* \cond hardware_pll \defgroup hardware_pll hardware_pll \endcond
3333
* \cond hardware_powman \defgroup hardware_powman hardware_powman \endcond
3434
* \cond hardware_pwm \defgroup hardware_pwm hardware_pwm \endcond
35-
* \cond hardware_pwm \defgroup hardware_pwm hardware_pwm \endcond
3635
* \cond hardware_resets \defgroup hardware_resets hardware_resets \endcond
3736
* \cond hardware_riscv \defgroup hardware_riscv hardware_riscv \endcond
3837
* \cond hardware_riscv_platform_timer \defgroup hardware_riscv_platform_timer hardware_riscv_platform_timer \endcond
@@ -44,13 +43,11 @@
4443
* \cond hardware_ticks \defgroup hardware_ticks hardware_ticks \endcond
4544
* \cond hardware_timer \defgroup hardware_timer hardware_timer \endcond
4645
* \cond hardware_uart \defgroup hardware_uart hardware_uart \endcond
46+
* \cond hardware_usb \defgroup hardware_usb hardware_usb \endcond
4747
* \cond hardware_vreg \defgroup hardware_vreg hardware_vreg \endcond
4848
* \cond hardware_watchdog \defgroup hardware_watchdog hardware_watchdog \endcond
4949
* \cond hardware_xip_cache \defgroup hardware_xip_cache hardware_xip_cache \endcond
5050
* \cond hardware_xosc \defgroup hardware_xosc hardware_xosc \endcond
51-
* \cond hardware_powman \defgroup hardware_powman hardware_powman \endcond
52-
* \cond hardware_hazard3 \defgroup hardware_hazard3 hardware_hazard3 \endcond
53-
* \cond hardware_riscv \defgroup hardware_riscv hardware_riscv \endcond
5451
5552
* @}
5653
*
@@ -61,6 +58,7 @@
6158
* \cond pico_aon_timer \defgroup pico_aon_timer pico_aon_timer \endcond
6259
* \cond pico_async_context \defgroup pico_async_context pico_async_context \endcond
6360
* \cond pico_bootsel_via_double_reset \defgroup pico_bootsel_via_double_reset pico_bootsel_via_double_reset \endcond
61+
* \cond pico_fix \defgroup pico_fix pico_fix \endcond
6462
* \cond pico_flash \defgroup pico_flash pico_flash \endcond
6563
* \cond pico_i2c_slave \defgroup pico_i2c_slave pico_i2c_slave \endcond
6664
* \cond pico_multicore \defgroup pico_multicore pico_multicore \endcond

tools/check_all_groups.py

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
#!/usr/bin/env python3
2+
#
3+
# Copyright (c) 2025 Raspberry Pi Ltd
4+
#
5+
# SPDX-License-Identifier: BSD-3-Clause
6+
#
7+
#
8+
# Script to check that the "groups" in various contexts all match up. (like an enhanced version of check_doxygen_groups.py)
9+
# Note that it only reports the *first* instance of a missing group, not all occurrences.
10+
#
11+
# Usage:
12+
#
13+
# tools/check_all_groups.py <root of repo>
14+
# (you'll probably want to pipe the output through ` | grep -v cmsis` )
15+
16+
import re
17+
import sys
18+
import os
19+
20+
scandir = sys.argv[1]
21+
22+
DEFGROUP_NAME = r'\defgroup'
23+
DEFGROUP_RE = re.compile(r'{}\s+(\w+)'.format(re.escape(DEFGROUP_NAME)))
24+
INGROUP_NAME = r'\ingroup'
25+
INGROUP_RE = re.compile(r'{}\s+(\w+)'.format(re.escape(INGROUP_NAME)))
26+
DOCS_INDEX_HEADER = 'docs/index.h'
27+
28+
BASE_CONFIG_NAME = 'PICO_CONFIG'
29+
CONFIG_RE = re.compile(r'//\s+{}:\s+(\w+),\s+([^,]+)(?:,\s+(.*))?$'.format(BASE_CONFIG_NAME))
30+
BASE_CMAKE_CONFIG_NAME = 'PICO_CMAKE_CONFIG'
31+
CMAKE_CONFIG_RE = re.compile(r'#\s+{}:\s+([\w-]+),\s+([^,]+)(?:,\s+(.*))?$'.format(BASE_CMAKE_CONFIG_NAME))
32+
BASE_BUILD_DEFINE_NAME = 'PICO_BUILD_DEFINE'
33+
BUILD_DEFINE_RE = re.compile(r'#\s+{}:\s+(\w+),\s+([^,]+)(?:,\s+(.*))?$'.format(BASE_BUILD_DEFINE_NAME))
34+
BASE_GROUP_NAME = 'group='
35+
GROUP_RE = re.compile(r'\b{}(\w+)\b'.format(BASE_GROUP_NAME))
36+
37+
def_groups = {}
38+
in_groups = {}
39+
doc_groups = {}
40+
config_groups = {}
41+
cmake_config_groups = {}
42+
build_define_groups = {}
43+
any_errors = False
44+
45+
def get_group_from_config_attrs(attr_str):
46+
m = GROUP_RE.search(attr_str)
47+
if m:
48+
return m.group(1)
49+
50+
# Scan all .c and .h and .S and .cmake and CMakeLists.txt files in the specific path, recursively.
51+
52+
for dirpath, dirnames, filenames in os.walk(scandir):
53+
for filename in filenames:
54+
file_ext = os.path.splitext(filename)[1]
55+
if filename == 'CMakeLists.txt' or file_ext in ('.c', '.h', '.S', '.cmake'):
56+
file_path = os.path.join(dirpath, filename)
57+
with open(file_path) as fh:
58+
for line in fh.readlines():
59+
m = DEFGROUP_RE.search(line)
60+
if m:
61+
group = m.group(1)
62+
if file_path.endswith(DOCS_INDEX_HEADER):
63+
if group in doc_groups:
64+
any_errors = True
65+
print("{} uses {} {} but so does {}".format(doc_groups[group], DEFGROUP_NAME, group, file_path))
66+
else:
67+
doc_groups[group] = file_path
68+
else:
69+
if group in def_groups:
70+
any_errors = True
71+
print("{} uses {} {} but so does {}".format(def_groups[group], DEFGROUP_NAME, group, file_path))
72+
else:
73+
def_groups[group] = file_path
74+
else:
75+
m = INGROUP_RE.search(line)
76+
if m:
77+
group = m.group(1)
78+
if group not in in_groups:
79+
in_groups[group] = file_path
80+
else:
81+
m = CONFIG_RE.search(line)
82+
if m:
83+
group = get_group_from_config_attrs(m.group(3))
84+
if group not in config_groups:
85+
config_groups[group] = file_path
86+
else:
87+
m = CMAKE_CONFIG_RE.search(line)
88+
if m:
89+
group = get_group_from_config_attrs(m.group(3))
90+
if group not in cmake_config_groups:
91+
cmake_config_groups[group] = file_path
92+
else:
93+
m = BUILD_DEFINE_RE.search(line)
94+
if m:
95+
group = get_group_from_config_attrs(m.group(3))
96+
if group not in build_define_groups:
97+
build_define_groups[group] = file_path
98+
99+
seen_groups = set()
100+
for group, file_path in in_groups.items():
101+
seen_groups.add(group)
102+
if group not in def_groups and group not in doc_groups:
103+
any_errors = True
104+
print("{} uses {} {} which was never defined".format(file_path, INGROUP_NAME, group))
105+
for group, file_path in config_groups.items():
106+
seen_groups.add(group)
107+
if group not in def_groups and group not in doc_groups:
108+
any_errors = True
109+
print("{} uses {} {}{} which was never defined".format(file_path, BASE_CONFIG_NAME, BASE_GROUP_NAME, group))
110+
for group, file_path in cmake_config_groups.items():
111+
seen_groups.add(group)
112+
if group == 'build': # dummy group
113+
continue
114+
if group not in def_groups and group not in doc_groups:
115+
any_errors = True
116+
print("{} uses {} {}{} which was never defined".format(file_path, BASE_CMAKE_CONFIG_NAME, BASE_GROUP_NAME, group))
117+
for group, file_path in build_define_groups.items():
118+
seen_groups.add(group)
119+
if group == 'build': # dummy group
120+
continue
121+
if group not in def_groups and group not in doc_groups:
122+
any_errors = True
123+
print("{} uses {} {}{} which was never defined".format(file_path, BASE_BUILD_DEFINE_NAME, BASE_GROUP_NAME, group))
124+
125+
for group in doc_groups.keys():
126+
seen_groups.add(group)
127+
if group not in seen_groups and group not in def_groups:
128+
any_errors = True
129+
print("{} uses {} {} which doesn't appear anywhere else".format(DOCS_INDEX_HEADER, DEFGROUP_NAME, group))
130+
131+
unused_groups = set(def_groups.keys()) - seen_groups
132+
if unused_groups:
133+
any_errors = True
134+
print("The following groups were defined with {} but never referenced:\n{}".format(DEFGROUP_NAME, sorted(unused_groups)))
135+
136+
sys.exit(any_errors)

0 commit comments

Comments
 (0)