mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
ci: check unstable soc headers wont be leaked by public api
This commit is contained in:
parent
d95b15c557
commit
3b371d2d64
@ -113,13 +113,14 @@ check_public_headers:
|
||||
script:
|
||||
- python tools/ci/check_public_headers.py --jobs 4 --prefix xtensa-esp32-elf-
|
||||
|
||||
check_soc_struct_headers:
|
||||
check_soc_component:
|
||||
extends:
|
||||
- .pre_check_base_template
|
||||
- .rules:build
|
||||
tags:
|
||||
- build
|
||||
script:
|
||||
- python tools/ci/check_soc_headers_leak.py
|
||||
- find ${IDF_PATH}/components/soc/*/include/soc/ -name "*_struct.h" -print0 | xargs -0 -n1 ./tools/ci/check_soc_struct_headers.py
|
||||
|
||||
check_esp_err_to_name:
|
||||
|
4
docs/doxygen/Doxyfile_esp32h2
Normal file
4
docs/doxygen/Doxyfile_esp32h2
Normal file
@ -0,0 +1,4 @@
|
||||
INPUT += \
|
||||
$(PROJECT_PATH)/components/driver/esp32h2/include/driver/temp_sensor.h \
|
||||
$(PROJECT_PATH)/components/esp_hw_support/include/soc/esp32h2/esp_ds.h \
|
||||
$(PROJECT_PATH)/components/esp_hw_support/include/soc/esp32h2/esp_hmac.h
|
112
tools/ci/check_soc_headers_leak.py
Normal file
112
tools/ci/check_soc_headers_leak.py
Normal file
@ -0,0 +1,112 @@
|
||||
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# This check script is used to ensure the public APIs won't expose the unstable soc files like register files
|
||||
# public API header files are those taken by doxygen and have full documented docs
|
||||
|
||||
import fnmatch
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import typing
|
||||
from string import Template
|
||||
|
||||
# The following header files in soc component is treated as stable, so is allowed to be used in any public header files
|
||||
allowed_soc_headers = (
|
||||
'soc/soc_caps.h',
|
||||
'soc/reset_reasons.h',
|
||||
'soc/reg_base.h',
|
||||
'soc/efuse_periph.h', # 'soc/efuse_periph.h' should not be allowed , remove it from the list in IDF-1256
|
||||
)
|
||||
|
||||
include_header_pattern = re.compile(r'[\s]*#[\s]*include ["<](.*)[">].*')
|
||||
doxyfile_target_pattern = re.compile(r'Doxyfile_(.*)')
|
||||
|
||||
|
||||
class PublicAPIVisits:
|
||||
def __init__(self, doxyfile_path: str, idf_path: str, target: str) -> None:
|
||||
self.doxyfile_path = doxyfile_path
|
||||
self._target = target
|
||||
self._idf_path = idf_path
|
||||
|
||||
def __iter__(self) -> typing.Generator:
|
||||
with open(self.doxyfile_path, 'r', encoding='utf8') as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if line.startswith('$(PROJECT_PATH)'):
|
||||
# $(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/uart_channel.h \
|
||||
# -> ${PROJECT_PATH}/components/soc/${IDF_TARGET}/include/soc/uart_channel.h
|
||||
line = line.replace('(', '{').replace(')', '}').rstrip('\\ ')
|
||||
file_path = Template(line).substitute(
|
||||
PROJECT_PATH=self._idf_path, IDF_TARGET=self._target
|
||||
)
|
||||
yield file_path
|
||||
|
||||
|
||||
def check_soc_not_in(
|
||||
idf_path: str,
|
||||
target: str,
|
||||
doxyfile_path: str,
|
||||
violation_dict: typing.Dict[str, set],
|
||||
) -> None:
|
||||
for file_path in PublicAPIVisits(
|
||||
os.path.join(idf_path, doxyfile_path), idf_path, target
|
||||
):
|
||||
with open(file_path, 'r', encoding='utf8') as f:
|
||||
for line in f:
|
||||
match_data = re.match(include_header_pattern, line)
|
||||
if match_data:
|
||||
header = match_data.group(1)
|
||||
if header.startswith('soc') and header not in allowed_soc_headers:
|
||||
if file_path not in violation_dict:
|
||||
violation_dict[file_path] = set()
|
||||
violation_dict[file_path].add(header)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
idf_path = os.environ.get('IDF_PATH', None)
|
||||
if idf_path is None:
|
||||
print('IDF_PATH must be set before running this script', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# list all doxyfiles
|
||||
doxyfiles = fnmatch.filter(
|
||||
os.listdir(os.path.join(idf_path, 'docs/doxygen')), 'Doxyfile*'
|
||||
)
|
||||
print(f'Found Doxyfiles:{doxyfiles}')
|
||||
|
||||
# targets are judged from Doxyfile name
|
||||
targets = []
|
||||
for file in doxyfiles:
|
||||
res = doxyfile_target_pattern.match(file)
|
||||
if res:
|
||||
targets.append(res.group(1))
|
||||
if not targets:
|
||||
print('No targets found', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
soc_violation_dict: typing.Dict[str, set] = {}
|
||||
for target in targets:
|
||||
check_soc_not_in(
|
||||
idf_path,
|
||||
target,
|
||||
os.path.join(idf_path, 'docs/doxygen/Doxyfile'),
|
||||
soc_violation_dict,
|
||||
)
|
||||
check_soc_not_in(
|
||||
idf_path,
|
||||
target,
|
||||
os.path.join(idf_path, f'docs/doxygen/Doxyfile_{target}'),
|
||||
soc_violation_dict,
|
||||
)
|
||||
|
||||
if len(soc_violation_dict) > 0:
|
||||
for file_path, headers_set in soc_violation_dict.items():
|
||||
print(f'{file_path} includes non-public soc header file: {headers_set}')
|
||||
sys.exit(1)
|
||||
else:
|
||||
print('No violation found')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
x
Reference in New Issue
Block a user