1#!/usr/bin/env python3 2# 3# Copyright (c) 2021, The OpenThread Authors. 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions are met: 8# 1. Redistributions of source code must retain the above copyright 9# notice, this list of conditions and the following disclaimer. 10# 2. Redistributions in binary form must reproduce the above copyright 11# notice, this list of conditions and the following disclaimer in the 12# documentation and/or other materials provided with the distribution. 13# 3. Neither the name of the copyright holder nor the 14# names of its contributors may be used to endorse or promote products 15# derived from this software without specific prior written permission. 16# 17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 21# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27# POSSIBILITY OF SUCH DAMAGE. 28# 29 30# This script updates different make/build files (CMakeLists.txt, BUILD.gn, 31# Andriod.mk, Andriod.bp, auto-make) in OpenThread repo based on the 32# current files present in `./src/core/` & `./include/openthread/` 33# folders. This script MUST be called from openthread root folder. 34 35import os 36 37#---------------------------------------------------------------------------------------------- 38# Helper functions 39 40 41def get_file_list(path, extension): 42 """Get a sorted list of full file names (with path) in a given `path` folder having a given `extension`""" 43 return sorted([ 44 "{}/{}".format(dir_path, file_name)[2:] 45 for dir_path, dir_names, file_names in os.walk(path) 46 for file_name in file_names 47 if file_name.endswith(extension) 48 ]) 49 50 51def read_txt_file(file_name): 52 """Read the content of a text file with name `file_name` and return content as a list of lines""" 53 with open(file_name, 'r') as file: 54 lines = file.readlines() 55 return lines 56 57 58def write_txt_file(file_name, lines): 59 """Write a text file with name `file_name` with the content given as a list of `lines`""" 60 with open(file_name, 'w') as file: 61 file.writelines(lines) 62 63 64def update_build_file(file_name, start_string, end_string, new_list, search_string=None): 65 """ 66 Update the file given by `file_name` by replacing the list after the first occurrence of `start_string` up to 67 `end_string` with the `new_list`. If `search_string` is given, then the search for `start_string` only starts 68 after seeing the `search_string` line in the file. 69 """ 70 STATE_SEARCH = 1 71 STATE_MATCH_START = 2 72 STATE_MATCH_END = 3 73 STATE_DONE = 4 74 75 lines = read_txt_file(file_name) 76 new_lines = [] 77 state = STATE_SEARCH if search_string else STATE_MATCH_START 78 79 for line in lines: 80 if state == STATE_SEARCH: 81 new_lines.append(line) 82 if line.startswith(search_string): 83 state = STATE_MATCH_START 84 elif state == STATE_MATCH_START: 85 new_lines.append(line) 86 if line.startswith(start_string): 87 new_lines.extend(new_list) 88 state = STATE_MATCH_END 89 elif state == STATE_MATCH_END: 90 if line.startswith(end_string): 91 new_lines.append(line) 92 state = STATE_DONE 93 else: 94 new_lines.append(line) 95 96 if state != STATE_DONE: 97 raise RuntimeError('failed to update build file: {}'.format(file_name)) 98 99 if new_lines != lines: 100 write_txt_file(file_name, new_lines) 101 102 103#---------------------------------------------------------------------------------------------- 104 105# Get the list of hpp/h/cpp files in different folders. 106 107src_core_path = "./src/core" 108core_h_files = get_file_list(src_core_path, '.h') 109core_hpp_files = get_file_list(src_core_path, '.hpp') 110core_cpp_files = get_file_list(src_core_path, '.cpp') 111core_cpp_files = [item for item in core_cpp_files if not item.endswith("extension_example.cpp")] 112core_hpp_cpp_files = sorted(core_hpp_files + core_cpp_files) 113core_h_hpp_files = sorted(core_h_files + core_hpp_files) 114 115include_path = "./include/openthread" 116include_h_files = get_file_list(include_path, '.h') 117include_ot_h_files = [name[8:] for name in include_h_files if not name.startswith("include/openthread/platform")] 118include_platform_h_files = [name[8:] for name in include_h_files if name.startswith("include/openthread/platform")] 119 120#---------------------------------------------------------------------------------------------- 121# Update CMakeLists.txt files 122 123core_cmakelist_txt_file = "./src/core/CMakeLists.txt" 124 125formatted_list = [" {}\n".format(file_name[9:]) for file_name in core_cpp_files] 126update_build_file(core_cmakelist_txt_file, "set(COMMON_SOURCES\n", ")\n", formatted_list) 127 128print("Updated " + core_cmakelist_txt_file) 129 130#---------------------------------------------------------------------------------------------- 131# Update Build.gn files 132 133core_build_gn_file = "./src/core/BUILD.gn" 134 135formatted_list = [" \"{}\",\n".format(file_name[9:]) for file_name in core_hpp_cpp_files] 136update_build_file(core_build_gn_file, "openthread_core_files = [\n", "]\n", formatted_list) 137 138formatted_list = [" \"{}\",\n".format(file_name[9:]) for file_name in core_h_files] 139update_build_file(core_build_gn_file, " public = [\n", " ]\n", formatted_list) 140 141print("Updated " + core_build_gn_file) 142 143include_build_gn_file = "./include/openthread/BUILD.gn" 144 145formatted_list = [" \"{}\",\n".format(file_name[19:]) for file_name in include_h_files] 146update_build_file(include_build_gn_file, " public = [\n", " ]\n", formatted_list) 147 148print("Updated " + include_build_gn_file) 149 150#---------------------------------------------------------------------------------------------- 151# Update Android.mk file 152 153android_mk_file = "./Android.mk" 154 155formatted_list = [" {:<63} \\\n".format(file_name) for file_name in core_cpp_files] 156start_string = "LOCAL_SRC_FILES := \\\n" 157end_string = " src/lib/hdlc/hdlc.cpp" 158update_build_file(android_mk_file, start_string, end_string, formatted_list) 159 160print("Updated " + android_mk_file) 161 162#---------------------------------------------------------------------------------------------- 163# Update Makefile.am files 164 165core_makefile_am_file = "./src/core/Makefile.am" 166 167formatted_list = [" {:<45} \\\n".format(file_name[9:]) for file_name in core_cpp_files] 168start_string = "SOURCES_COMMON = \\\n" 169end_string = " $(NULL)\n" 170update_build_file(core_makefile_am_file, start_string, end_string, formatted_list) 171 172formatted_list = [" {:<45} \\\n".format(file_name[9:]) for file_name in core_h_hpp_files] 173start_string = "HEADERS_COMMON = \\\n" 174end_string = " $(NULL)\n" 175update_build_file(core_makefile_am_file, start_string, end_string, formatted_list) 176 177print("Updated " + core_makefile_am_file) 178 179include_makefile_am_file = "./include/Makefile.am" 180 181formatted_list = [" {:<37} \\\n".format(file_name) for file_name in include_ot_h_files] 182start_string = "openthread_headers = \\\n" 183end_string = " $(NULL)\n" 184update_build_file(include_makefile_am_file, start_string, end_string, formatted_list) 185 186formatted_list = [" {:<37} \\\n".format(file_name) for file_name in include_platform_h_files] 187start_string = "ot_platform_headers = \\\n" 188end_string = " $(NULL)\n" 189update_build_file(include_makefile_am_file, start_string, end_string, formatted_list) 190 191print("Updated " + include_makefile_am_file) 192