2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#!/usr/bin/env python
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								# Checks all public headers in IDF in the ci
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#
							 | 
						
					
						
							
								
									
										
										
										
											2024-02-20 18:37:38 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								# SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-21 10:32:52 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								# SPDX-License-Identifier: Apache-2.0
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								import argparse
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								import fnmatch
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								import json
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								import os
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								import queue
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								import re
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								import subprocess
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								import tempfile
							 | 
						
					
						
							
								
									
										
										
										
											2024-02-20 18:37:38 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								from threading import Event
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								from threading import Thread
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								from typing import List
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								from typing import Optional
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								from typing import Set
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								from typing import Tuple
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								from typing import Union
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								class HeaderFailed(Exception):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    """Base header failure exeption"""
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    pass
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								class HeaderFailedSdkconfig(HeaderFailed):
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-28 19:00:12 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def __str__(self) -> str:
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        return 'Sdkconfig Error'
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								class HeaderFailedBuildError(HeaderFailed):
							 | 
						
					
						
							
								
									
										
										
										
											2023-08-09 14:12:21 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def __init__(self, compiler: str):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.compiler = compiler
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-28 19:00:12 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def __str__(self) -> str:
							 | 
						
					
						
							
								
									
										
										
										
											2023-08-09 14:12:21 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        return 'Header Build Error with {}'.format(self.compiler)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								class HeaderFailedPreprocessError(HeaderFailed):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    def __str__(self) -> str:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        return 'Header Procecessing Error'
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								class HeaderFailedCppGuardMissing(HeaderFailed):
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-28 19:00:12 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def __str__(self) -> str:
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        return 'Header Missing C++ Guard'
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								class HeaderFailedContainsCode(HeaderFailed):
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-28 19:00:12 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def __str__(self) -> str:
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        return 'Header Produced non-zero object'
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-13 13:28:10 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								class HeaderFailedContainsStaticAssert(HeaderFailed):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    def __str__(self) -> str:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        return 'Header uses _Static_assert or static_assert instead of ESP_STATIC_ASSERT'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#   Creates a temp file and returns both output as a string and a file name
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-28 19:00:12 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								def exec_cmd_to_temp_file(what: List, suffix: str='') -> Tuple[int, str, str, str, str]:
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    out_file = tempfile.NamedTemporaryFile(suffix=suffix, delete=False)
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-21 11:27:03 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    rc, out, err, cmd = exec_cmd(what, out_file)
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    with open(out_file.name, 'r', encoding='utf-8') as f:
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        out = f.read()
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-21 11:27:03 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    return rc, out, err, out_file.name, cmd
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-27 10:34:21 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								def exec_cmd(what: List, out_file: Union['tempfile._TemporaryFileWrapper[bytes]', int]=subprocess.PIPE) -> Tuple[int, str, str, str]:
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    p = subprocess.Popen(what, stdin=subprocess.PIPE, stdout=out_file, stderr=subprocess.PIPE)
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-28 19:00:12 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    output_b, err_b = p.communicate()
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    rc = p.returncode
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-27 11:04:50 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    output: str = output_b.decode('utf-8') if output_b is not None else ''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    err: str = err_b.decode('utf-8') if err_b is not None else ''
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-21 11:27:03 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    return rc, output, err, ' '.join(what)
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								class PublicHeaderChecker:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # Intermediate results
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    COMPILE_ERR_REF_CONFIG_HDR_FAILED = 1  # -> Cannot compile and failed with injected SDKCONFIG #error (header FAILs)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    COMPILE_ERR_ERROR_MACRO_HDR_OK = 2     # -> Cannot compile, but failed with "#error" directive (header seems OK)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    COMPILE_ERR_HDR_FAILED = 3             # -> Cannot compile with another issue, logged if verbose (header FAILs)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    PREPROC_OUT_ZERO_HDR_OK = 4            # -> Both preprocessors produce zero out (header file is OK)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    PREPROC_OUT_SAME_HRD_FAILED = 5        # -> Both preprocessors produce the same, non-zero output (header file FAILs)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    PREPROC_OUT_DIFFERENT_WITH_EXT_C_HDR_OK = 6    # -> Both preprocessors produce different, non-zero output with extern "C" (header seems OK)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    PREPROC_OUT_DIFFERENT_NO_EXT_C_HDR_FAILED = 7  # -> Both preprocessors produce different, non-zero output without extern "C" (header fails)
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-13 13:28:10 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    HEADER_CONTAINS_STATIC_ASSERT = 8      # -> Header file contains _Static_assert instead of static_assert or ESP_STATIC_ASSERT
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-28 19:00:12 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def log(self, message: str, debug: bool=False) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2020-04-07 14:43:33 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        if self.verbose or debug:
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            print(message)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-28 19:00:12 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def __init__(self, verbose: bool=False, jobs: int=1, prefix: Optional[str]=None) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self.gcc = '{}gcc'.format(prefix)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.gpp = '{}g++'.format(prefix)
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.verbose = verbose
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.jobs = jobs
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.prefix = prefix
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.extern_c = re.compile(r'extern "C"')
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.error_macro = re.compile(r'#error')
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self.error_orphan_kconfig = re.compile(r'#error CONFIG_VARS_USED_WHILE_SDKCONFIG_NOT_INCLUDED')
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.kconfig_macro = re.compile(r'\bCONFIG_[A-Z0-9_]+')
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-13 13:28:10 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self.static_assert = re.compile(r'(_Static_assert|static_assert)')
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.defines_assert = re.compile(r'#define[ \t]+ESP_STATIC_ASSERT')
							 | 
						
					
						
							
								
									
										
										
										
											2024-02-20 18:37:38 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self.auto_soc_header = re.compile(r'components/soc/esp[a-z0-9_]+(?:/\w+)?/include(?:/rev[0-9]+)?/(soc|modem)/[a-zA-Z0-9_]+.h')
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-29 22:48:16 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self.assembly_nocode = r'^\s*(\.file|\.text|\.ident|\.option|\.attribute).*$'
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-28 19:00:12 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self.check_threads: List[Thread] = []
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-28 19:00:12 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self.job_queue: queue.Queue = queue.Queue()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.failed_queue: queue.Queue = queue.Queue()
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.terminate = Event()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-28 19:00:12 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def __enter__(self) -> 'PublicHeaderChecker':
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        for i in range(self.jobs):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            t = Thread(target=self.check_headers, args=(i, ))
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            self.check_threads.append(t)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            t.start()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        return self
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-28 19:00:12 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def __exit__(self, exc_type: str, exc_value: str, traceback: str) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.terminate.set()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        for t in self.check_threads:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            t.join()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # thread function process incoming header file from a queue
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-28 19:00:12 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def check_headers(self, num: int) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        while not self.terminate.is_set():
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if not self.job_queue.empty():
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                task = self.job_queue.get()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if task is None:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    self.terminate.set()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                else:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    try:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        self.check_one_header(task, num)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    except HeaderFailed as e:
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        self.failed_queue.put('{}: Failed! {}'.format(task, e))
							 | 
						
					
						
							
								
									
										
										
										
											2020-06-09 10:12:15 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    except Exception as e:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        # Makes sure any unexpected exceptions causes the program to terminate
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        self.failed_queue.put('{}: Failed! {}'.format(task, e))
							 | 
						
					
						
							
								
									
										
										
										
											2020-06-09 10:12:15 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        self.terminate.set()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        raise
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-28 19:00:12 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def get_failed(self) -> List:
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        return list(self.failed_queue.queue)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-28 19:00:12 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def join(self) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        for t in self.check_threads:
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-26 10:44:20 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            while t.is_alive() and not self.terminate.is_set():
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                t.join(1)  # joins with timeout to respond to keyboard interrupt
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # Checks one header calling:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # - preprocess_one_header() to test and compare preprocessor outputs
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # - check_no_code() to test if header contains some executable code
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # Procedure
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # 1) Preprocess the include file with C preprocessor and with CPP preprocessor
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    #   - Pass the test if the preprocessor outputs are the same and whitespaces only (#define only header)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    #   - Fail the test if the preprocessor outputs are the same (but with some code)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    #   - If outputs different, continue with 2)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # 2) Strip out all include directives to generate "temp.h"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # 3) Preprocess the temp.h the same way in (1)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    #   - Pass the test if the preprocessor outputs are the same and whitespaces only (#include only header)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    #   - Fail the test if the preprocessor outputs are the same (but with some code)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    #   - If outputs different, pass the test
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # 4) If header passed the steps 1) and 3) test that it produced zero assembly code
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-28 19:00:12 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def check_one_header(self, header: str, num: int) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        res = self.preprocess_one_header(header, num)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if res == self.COMPILE_ERR_REF_CONFIG_HDR_FAILED:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            raise HeaderFailedSdkconfig()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        elif res == self.COMPILE_ERR_ERROR_MACRO_HDR_OK:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            return self.compile_one_header(header)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        elif res == self.COMPILE_ERR_HDR_FAILED:
							 | 
						
					
						
							
								
									
										
										
										
											2023-08-09 14:12:21 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            raise HeaderFailedPreprocessError()
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        elif res == self.PREPROC_OUT_ZERO_HDR_OK:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            return self.compile_one_header(header)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        elif res == self.PREPROC_OUT_SAME_HRD_FAILED:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            raise HeaderFailedCppGuardMissing()
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-13 13:28:10 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        elif res == self.HEADER_CONTAINS_STATIC_ASSERT:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            raise HeaderFailedContainsStaticAssert()
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        else:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            self.compile_one_header(header)
							 | 
						
					
						
							
								
									
										
										
										
											2020-06-09 10:12:15 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            temp_header = None
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            try:
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-21 11:27:03 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                _, _, _, temp_header, _ = exec_cmd_to_temp_file(['sed', '/#include/d; /#error/d', header], suffix='.h')
							 | 
						
					
						
							
								
									
										
										
										
											2023-02-01 12:52:37 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                res = self.preprocess_one_header(temp_header, num, ignore_common_issues=True)
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if res == self.PREPROC_OUT_SAME_HRD_FAILED:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    raise HeaderFailedCppGuardMissing()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                elif res == self.PREPROC_OUT_DIFFERENT_NO_EXT_C_HDR_FAILED:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    raise HeaderFailedCppGuardMissing()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            finally:
							 | 
						
					
						
							
								
									
										
										
										
											2020-06-09 10:12:15 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                if temp_header:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    os.unlink(temp_header)
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-28 19:00:12 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def compile_one_header(self, header: str) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2023-08-09 14:12:21 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self.compile_one_header_with(self.gcc, header)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.compile_one_header_with(self.gpp, header)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    def compile_one_header_with(self, compiler: str, header: str) -> None:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        rc, out, err, cmd = exec_cmd([compiler, '-S', '-o-', '-include', header, self.main_c] + self.include_dir_flags)
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if rc == 0:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if not re.sub(self.assembly_nocode, '', out, flags=re.M).isspace():
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                raise HeaderFailedContainsCode()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            return  # Header OK: produced zero code
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self.log('{}: FAILED: compilation issue'.format(header), True)
							 | 
						
					
						
							
								
									
										
										
										
											2020-04-07 14:43:33 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self.log(err, True)
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-21 11:27:03 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self.log('\nCompilation command failed:\n{}\n'.format(cmd), True)
							 | 
						
					
						
							
								
									
										
										
										
											2023-08-09 14:12:21 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        raise HeaderFailedBuildError(compiler)
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-02-01 12:52:37 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def preprocess_one_header(self, header: str, num: int, ignore_common_issues: bool=False) -> int:
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        all_compilation_flags = ['-w', '-P', '-E', '-DESP_PLATFORM', '-include', header, self.main_c] + self.include_dir_flags
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-13 13:28:10 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        # just strip comments to check for CONFIG_... macros or static asserts
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        rc, out, err, _ = exec_cmd([self.gcc, '-fpreprocessed', '-dD',  '-P',  '-E', header] + self.include_dir_flags)
							 | 
						
					
						
							
								
									
										
										
										
											2023-02-01 12:52:37 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        if not ignore_common_issues:    # We ignore issues on sdkconfig and static asserts, as we're looking at "preprocessed output"
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if re.search(self.kconfig_macro, out):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # enable defined #error if sdkconfig.h not included
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                all_compilation_flags.append('-DIDF_CHECK_SDKCONFIG_INCLUDED')
							 | 
						
					
						
							
								
									
										
										
										
											2023-02-01 12:52:37 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            # If the file contain _Static_assert or static_assert, make sure it does't not define ESP_STATIC_ASSERT and that it
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # is not an automatically generated soc header file
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            grp = re.search(self.static_assert, out)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # Normalize the potential A//B, A/./B, A/../A, from the name
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            normalized_path = os.path.normpath(header)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if grp and not re.search(self.defines_assert, out) and not re.search(self.auto_soc_header, normalized_path):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                self.log('{}: FAILED: contains {}. Please use ESP_STATIC_ASSERT'.format(header, grp.group(1)), True)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                return self.HEADER_CONTAINS_STATIC_ASSERT
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        try:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # compile with C++, check for errors, outputs for a temp file
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-21 11:27:03 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            rc, cpp_out, err, cpp_out_file, cmd = exec_cmd_to_temp_file([self.gpp, '--std=c++17'] + all_compilation_flags)
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if rc != 0:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if re.search(self.error_macro, err):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    if re.search(self.error_orphan_kconfig, err):
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        self.log('{}: CONFIG_VARS_USED_WHILE_SDKCONFIG_NOT_INCLUDED'.format(header), True)
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        return self.COMPILE_ERR_REF_CONFIG_HDR_FAILED
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    self.log('{}: Error directive failure: OK'.format(header))
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    return self.COMPILE_ERR_ERROR_MACRO_HDR_OK
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                self.log('{}: FAILED: compilation issue'.format(header), True)
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-21 10:32:52 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                self.log(err, True)
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-21 11:27:03 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                self.log('\nCompilation command failed:\n{}\n'.format(cmd), True)
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                return self.COMPILE_ERR_HDR_FAILED
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # compile with C compiler, outputs to another temp file
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-21 11:27:03 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            rc, _, err, c99_out_file, _ = exec_cmd_to_temp_file([self.gcc, '--std=c99'] + all_compilation_flags)
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if rc != 0:
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                self.log('{} FAILED should never happen'.format(header))
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                return self.COMPILE_ERR_HDR_FAILED
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # diff the two outputs
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-21 11:27:03 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            rc, diff, err, _ = exec_cmd(['diff', c99_out_file, cpp_out_file])
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if not diff or diff.isspace():
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if not cpp_out or cpp_out.isspace():
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    self.log('{} The same, but empty out - OK'.format(header))
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    return self.PREPROC_OUT_ZERO_HDR_OK
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                self.log('{} FAILED C and C++ preprocessor output is the same!'.format(header), True)
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                return self.PREPROC_OUT_SAME_HRD_FAILED
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if re.search(self.extern_c, diff):
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                self.log('{} extern C present - OK'.format(header))
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                return self.PREPROC_OUT_DIFFERENT_WITH_EXT_C_HDR_OK
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            self.log('{} Different but no extern C - FAILED'.format(header), True)
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            return self.PREPROC_OUT_DIFFERENT_NO_EXT_C_HDR_FAILED
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        finally:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            os.unlink(cpp_out_file)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            try:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                os.unlink(c99_out_file)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            except Exception:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                pass
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # Get compilation data from an example to list all public header files
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-28 19:00:12 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def list_public_headers(self, ignore_dirs: List, ignore_files: Union[List, Set], only_dir: str=None) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        idf_path = os.getenv('IDF_PATH')
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-28 19:00:12 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        if idf_path is None:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            raise RuntimeError("Environment variable 'IDF_PATH' wasn't set.")
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        project_dir = os.path.join(idf_path, 'examples', 'get-started', 'blink')
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-29 22:47:02 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        build_dir = tempfile.mkdtemp()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        sdkconfig = os.path.join(build_dir, 'sdkconfig')
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        try:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            os.unlink(os.path.join(project_dir, 'sdkconfig'))
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        except FileNotFoundError:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            pass
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        subprocess.check_call(['idf.py', '-B', build_dir, f'-DSDKCONFIG={sdkconfig}', 'reconfigure'], cwd=project_dir)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        build_commands_json = os.path.join(build_dir, 'compile_commands.json')
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        with open(build_commands_json, 'r', encoding='utf-8') as f:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            build_command = json.load(f)[0]['command'].split()
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        include_dir_flags = []
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        include_dirs = []
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # process compilation flags (includes and defines)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        for item in build_command:
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            if item.startswith('-I'):
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                include_dir_flags.append(item)
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                if 'components' in item:
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    include_dirs.append(item[2:])  # Removing the leading "-I"
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            if item.startswith('-D'):
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                include_dir_flags.append(item.replace('\\',''))  # removes escaped quotes, eg: -DMBEDTLS_CONFIG_FILE=\\\"mbedtls/esp_config.h\\\"
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-29 22:47:02 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        include_dir_flags.append('-I' + os.path.join(build_dir, 'config'))
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        include_dir_flags.append('-DCI_HEADER_CHECK')
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-29 22:47:02 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        sdkconfig_h = os.path.join(build_dir, 'config', 'sdkconfig.h')
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # prepares a main_c file for easier sdkconfig checks and avoid compilers warning when compiling headers directly
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        with open(sdkconfig_h, 'a') as f:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            f.write('#define IDF_SDKCONFIG_INCLUDED')
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-29 22:47:02 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        main_c = os.path.join(build_dir, 'compile.c')
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        with open(main_c, 'w') as f:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            f.write('#if defined(IDF_CHECK_SDKCONFIG_INCLUDED) && ! defined(IDF_SDKCONFIG_INCLUDED)\n'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    '#error CONFIG_VARS_USED_WHILE_SDKCONFIG_NOT_INCLUDED\n'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    '#endif')
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # processes public include dirs, removing ignored files
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        all_include_files = []
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        files_to_check = []
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        for d in include_dirs:
							 | 
						
					
						
							
								
									
										
										
										
											2023-08-09 14:12:21 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            if only_dir is not None and not os.path.relpath(d, idf_path).startswith(os.path.relpath(only_dir, idf_path)):
							 | 
						
					
						
							
								
									
										
										
										
											2020-04-07 14:43:33 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                self.log('{} - directory ignored (not in "{}")'.format(d, only_dir))
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                continue
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if os.path.relpath(d, idf_path).startswith(tuple(ignore_dirs)):
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                self.log('{} - directory ignored'.format(d))
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                continue
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            for root, dirnames, filenames in os.walk(d):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                for filename in fnmatch.filter(filenames, '*.h'):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    all_include_files.append(os.path.join(root, filename))
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.main_c = main_c
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.include_dir_flags = include_dir_flags
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        ignore_files = set(ignore_files)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # processes public include files, removing ignored files
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-28 19:00:12 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        for file_name in all_include_files:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            rel_path_file = os.path.relpath(file_name, idf_path)
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if any([os.path.commonprefix([d, rel_path_file]) == d for d in ignore_dirs]):
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-28 19:00:12 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                self.log('{} - file ignored (inside ignore dir)'.format(file_name))
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                continue
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if rel_path_file in ignore_files:
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-28 19:00:12 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                self.log('{} - file ignored'.format(file_name))
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                continue
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-28 19:00:12 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            files_to_check.append(file_name)
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # removes duplicates and places headers to a work queue
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-28 19:00:12 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        for file_name in set(files_to_check):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            self.job_queue.put(file_name)
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.job_queue.put(None)  # to indicate the last job
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-28 19:00:12 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								def check_all_headers() -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-21 11:27:03 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    parser = argparse.ArgumentParser('Public header checker file', formatter_class=argparse.RawDescriptionHelpFormatter, epilog='''\
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Tips for fixing failures reported by this script
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ------------------------------------------------
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    This checker validates all public headers to detect these types of issues:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    1) "Sdkconfig Error": Using SDK config macros without including "sdkconfig.h"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        * Check if the failing include file or any other included file uses "CONFIG_..." prefixed macros
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    2) "Header Build Error": Header itself is not compilable (missing includes, macros, types)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        * Check that all referenced macros, types are available (defined or included)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        * Check that all included header files are available (included in paths)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        * Check for possible compilation issues
							 | 
						
					
						
							
								
									
										
										
										
											2023-08-09 14:12:21 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        * If only the C++ compilation fails, check that the header is C++ compatible
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-21 11:27:03 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        * Try to compile only the offending header file
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    3) "Header Missing C++ Guard": Preprocessing the header by C and C++ should produce different output
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        * Check if the "#ifdef __cplusplus" header sentinels are present
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    4) "Header Produced non-zero object": Header contains some object, a definition
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        * Check if no definition is present in the offending header file
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-13 13:28:10 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    5) "Header contains _Static_assert or static_assert": Makes the use of _Static_assert or static_assert
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        functions instead of using ESP_STATIC_ASSERT macro
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-21 11:27:03 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Notes:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    * The script validates *all* header files (recursively) in public folders for all components.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    * The script locates include paths from running a default build of  "examples/get-started/blink'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    * The script does not support any other targets than esp32
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    General tips:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    * Use "-d" argument to make the script check only the offending header file
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    * Use "-v" argument to produce more verbose output
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    * Copy, paste and execute the compilation commands to reproduce build errors (script prints out
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      the entire compilation command line with absolute paths)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ''')
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    parser.add_argument('--verbose', '-v', help='enables verbose mode', action='store_true')
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    parser.add_argument('--jobs', '-j', help='number of jobs to run checker', default=1, type=int)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    parser.add_argument('--prefix', '-p', help='compiler prefix', default='xtensa-esp32-elf-', type=str)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    parser.add_argument('--exclude-file', '-e', help='exception file', default='check_public_headers_exceptions.txt', type=str)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    parser.add_argument('--only-dir', '-d', help='reduce the analysis to this directory only', default=None, type=str)
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    args = parser.parse_args()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # process excluded files and dirs
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    exclude_file = os.path.join(os.path.dirname(__file__), args.exclude_file)
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    with open(exclude_file, 'r', encoding='utf-8') as f:
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        lines = [line.rstrip() for line in f]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ignore_files = []
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ignore_dirs = []
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    for line in lines:
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        if not line or line.isspace() or line.startswith('#'):
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            continue
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if os.path.isdir(line):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            ignore_dirs.append(line)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        else:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            ignore_files.append(line)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # start header check
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    with PublicHeaderChecker(args.verbose, args.jobs, args.prefix) as header_check:
							 | 
						
					
						
							
								
									
										
										
										
											2020-04-07 14:43:33 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        header_check.list_public_headers(ignore_dirs, ignore_files, only_dir=args.only_dir)
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        try:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            header_check.join()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            failures = header_check.get_failed()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if len(failures) > 0:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                for failed in failures:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    print(failed)
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-21 11:27:03 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                print(parser.epilog)
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                exit(1)
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            print('No errors found')
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        except KeyboardInterrupt:
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            print('Keyboard interrupt')
							 | 
						
					
						
							
								
									
										
										
										
											2020-03-02 10:19:01 +01:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								if __name__ == '__main__':
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    check_all_headers()
							 |