diff --git a/ets2panda/BUILD.gn b/ets2panda/BUILD.gn index 63d89774f94de4516bfdbba7beb56c46a6529b06..b116f3e1e2f3f4e02978b82c83c4772ea5d5d283 100644 --- a/ets2panda/BUILD.gn +++ b/ets2panda/BUILD.gn @@ -31,6 +31,10 @@ config("libes2panda_public_config") { ] } +action("check_build_system_consistency") { + script = "./scripts/check_build_system_consistency.py" +} + libes2panda_sources = [ "ast_verifier/ASTVerifier.cpp", "ast_verifier/helpers.cpp", @@ -490,6 +494,7 @@ libes2panda_sources = [ "util/path.cpp", "util/plugin.cpp", "util/ustring.cpp", + "test/utils/panda_executable_path_getter.cpp", "varbinder/ASBinder.cpp", "varbinder/ETSBinder.cpp", "varbinder/JSBinder.cpp", @@ -770,6 +775,8 @@ HEADERS_TO_BE_PARSED = [ "es2panda.h", "ast_verifier/ASTVerifier.h", "util/importPathManager.h", + "util/path.h", + "util/arktsconfig.h" ] ES2PANDA_API_GENERATED = [ @@ -1037,6 +1044,8 @@ ES2PANDA_API_GENERATED = [ "$LIBGEN_DIR/gen/headers/parser/program/program.yaml", "$LIBGEN_DIR/gen/headers/ast_verifier/ASTVerifier.yaml", "$LIBGEN_DIR/gen/headers/util/importPathManager.yaml", + "$LIBGEN_DIR/gen/headers/util/path.yaml", + "$LIBGEN_DIR/gen/headers/util/arktsconfig.yaml" ] ES2PANDA_API = [ diff --git a/ets2panda/CMakeLists.txt b/ets2panda/CMakeLists.txt index 5747b4a45f3d296ea92f34fe4ddfd5be7a7d72a9..7fb91b9fd4dc1a99abdf52fcd764d51692a90377 100644 --- a/ets2panda/CMakeLists.txt +++ b/ets2panda/CMakeLists.txt @@ -187,6 +187,16 @@ panda_gen( DESTINATION ${GENERATED_DIR} ) +find_package(Python3 REQUIRED) +execute_process( + COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/check_build_system_consistency.py + RESULT_VARIABLE result + OUTPUT_VARIABLE output +) +if(NOT result EQUAL 0) + message(FATAL_ERROR "Python script execution failed: ${output}") +endif() + set(ES2PANDA_LIB_SRC ast_verifier/ASTVerifier.cpp ast_verifier/helpers.cpp @@ -642,6 +652,7 @@ set(ES2PANDA_LIB_SRC util/helpers.cpp util/importPathManager.cpp util/path.cpp + util/plugin.cpp util/ustring.cpp test/utils/panda_executable_path_getter.cpp evaluate/debugInfoDeserialization/debugInfoDeserializer.cpp @@ -728,6 +739,7 @@ if(PANDA_TARGET_LINUX OR PANDA_TARGET_WINDOWS) add_subdirectory(${ES2PANDA_NAPI_LIB_DIR}) endif() + if(PANDA_WITH_TESTS) add_subdirectory(test) endif() diff --git a/ets2panda/scripts/check_build_system_consistency.py b/ets2panda/scripts/check_build_system_consistency.py new file mode 100644 index 0000000000000000000000000000000000000000..8a40c7e72a4aa058014764228a07cf1c3333f8a1 --- /dev/null +++ b/ets2panda/scripts/check_build_system_consistency.py @@ -0,0 +1,125 @@ +import os +import re +import fnmatch +from pathlib import Path + +def parse_cmake_file_list(text, patterns): + file_list = [] + file_dict = {} + for match in re.finditer(r'([^\'"]*\.[a-zA-Z]+)', text): + filename = match.group(0) + filename = filename.split('\n') + + for file in filename: + if(file.endswith(patterns)): + file_list.append(file.strip().split('/')[-1]) + file_dict[file.strip().split('/')[-1]] = file.strip() + return file_list, file_dict + +def parse_gn_file_list(text, patterns): + file_list = [] + file_dict = {} + for match in re.finditer(r'[\"]([^\'"]*\.[a-zA-Z]+)[\"]', text): + filename = match.group(1) + if any(fnmatch.fnmatch(filename, pat) for pat in patterns): + file_list.append(os.path.basename(filename)) + file_dict[os.path.basename(filename)] = filename + return file_list, file_dict + +def parse_cmake(file_path): + patterns = ('.cpp') + sources = [] + sources_dict = {} + + with open(file_path, 'r') as f: + content = f.read() + for match in re.finditer(r'set\s*\(\s*\w+\s+(.*?)\s*\)', content, re.DOTALL): + files, files_dict = parse_cmake_file_list(match.group(1), patterns) + for file in files: + if file.endswith('.cpp'): + sources.append(file) + sources_dict[file] = files_dict[file] + return sources, sources_dict + +def parse_public_cmake(file_path): + patterns = ('.h', '.yaml') + headers, yamls = [], [] + headers_dict, yamls_dict = {}, {} + + with open(file_path, 'r') as f: + content = f.read() + for match in re.finditer(r'set\s*\(\s*\w+\s+(.*?)\s*\)', content, re.DOTALL): + files, files_dict = parse_cmake_file_list(match.group(1), patterns) + for file in files: + if file.endswith('.h'): + headers.append(file) + headers_dict[file] = files_dict[file] + elif file.endswith('.yaml'): + yamls.append(file) + yamls_dict[file] = files_dict[file] + return headers, yamls, headers_dict, yamls_dict + +def parse_gn(file_path): + patterns = ['*.cpp', '*.h', '*.yaml'] + sources, headers, yamls = [], [], [] + sources_dict, headers_dict, yamls_dict = {}, {}, {} + + with open(file_path, 'r') as f: + content = f.read() + for match in re.finditer(r'(libes2panda_sources|HEADERS_TO_BE_PARSED|ES2PANDA_API_GENERATED|ES2PANDA_API|generated_headers)\s*=\s*\[(.*?)\]', content, re.DOTALL): + files, files_dict = parse_gn_file_list(match.group(2), patterns) + for file in files: + if file.endswith('.cpp'): + sources.append(file) + sources_dict[file] = files_dict[file] + elif file.endswith('.h'): + headers.append(file) + headers_dict[file] = files_dict[file] + elif file.endswith('.yaml'): + yamls.append(file) + yamls_dict[file] = files_dict[file] + return sources, sources_dict, headers, headers_dict, yamls, yamls_dict + +def compare_file_lists(cmake_files, cmake_files_dict, gn_files, gn_files_dict, file_type): + cmake_set = set(cmake_files) + gn_set = set(gn_files) + + only_in_cmake = cmake_set - gn_set + only_in_gn = gn_set - cmake_set + + if only_in_cmake: + only_in_cmake_path = [] + for file in only_in_cmake: + only_in_cmake_path.append(cmake_files_dict[file]) + print(f"{file_type} only exist in CMake file:", sorted(only_in_cmake_path)) + if only_in_gn: + only_in_gn_path = [] + for file in only_in_gn: + only_in_gn_path.append(gn_files_dict[file]) + print(f"{file_type} only exist in GN file:", sorted(only_in_gn_path)) + + return len(only_in_cmake) == 0 and len(only_in_gn) == 0 + +def main(): + current_dir = os.path.dirname(os.path.abspath(__file__)) + cmake_dir = os.path.join(current_dir, '../../../tools/es2panda/CMakeLists.txt') + public_cmake_dir = os.path.join(cmake_dir, '../public/CMakeLists.txt') + cmake_src, cmake_src_dict = parse_cmake(os.path.abspath(cmake_dir)) + cmake_hdr, cmake_yaml, cmake_hdr_dict, cmake_yaml_dict = parse_public_cmake(os.path.abspath(public_cmake_dir)) + + gn_dir = os.path.join(current_dir, '../../../tools/es2panda/BUILD.gn') + gn_src, gn_src_dict, gn_hdr, gn_hdr_dict, gn_yaml, gn_yaml_dict = parse_gn(os.path.abspath(gn_dir)) + + src_consistent = compare_file_lists(cmake_src, cmake_src_dict, gn_src, gn_src_dict, "source file(.cpp)") + hdr_consistent = compare_file_lists(cmake_hdr, cmake_hdr_dict, gn_hdr, gn_hdr_dict, "header file(.h)") + yaml_consistent = compare_file_lists(cmake_yaml, cmake_yaml_dict, gn_yaml, gn_yaml_dict, "YAML file(.yaml)") + + if src_consistent and hdr_consistent and yaml_consistent: + print("all file types are consistent beetween CMake and GN") + return 0 + else: + print("Warning! inconsistent file found beetween CMake and GN") + return 1 + +if __name__ == "__main__": + exit(main()) \ No newline at end of file