1*6777b538SAndroid Build Coastguard Worker# Copyright 2023 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker# found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker"""Python module to find feature names in source code. 5*6777b538SAndroid Build Coastguard Worker 6*6777b538SAndroid Build Coastguard WorkerThese functions are declared in a separate module to allow multiprocessing to 7*6777b538SAndroid Build Coastguard Workercorrectly unpickle the called functions again. 8*6777b538SAndroid Build Coastguard Worker""" 9*6777b538SAndroid Build Coastguard Worker 10*6777b538SAndroid Build Coastguard Workerimport glob 11*6777b538SAndroid Build Coastguard Workerimport itertools 12*6777b538SAndroid Build Coastguard Workerimport multiprocessing 13*6777b538SAndroid Build Coastguard Workerimport pathlib 14*6777b538SAndroid Build Coastguard Workerimport re 15*6777b538SAndroid Build Coastguard Worker 16*6777b538SAndroid Build Coastguard WorkerBASE_FEATURE_PATTERN = br"BASE_FEATURE\((.*?),(.*?),(.*?)\);" 17*6777b538SAndroid Build Coastguard WorkerBASE_FEATURE_RE = re.compile(BASE_FEATURE_PATTERN, flags=re.MULTILINE+re.DOTALL) 18*6777b538SAndroid Build Coastguard Worker 19*6777b538SAndroid Build Coastguard Worker# Only search these directories for flags. If your flag is outside these root 20*6777b538SAndroid Build Coastguard Worker# directories, then add the directory here. 21*6777b538SAndroid Build Coastguard WorkerDIRECTORIES_TO_SEARCH = [ 22*6777b538SAndroid Build Coastguard Worker "android_webview", 23*6777b538SAndroid Build Coastguard Worker "apps", 24*6777b538SAndroid Build Coastguard Worker "ash", 25*6777b538SAndroid Build Coastguard Worker "base", 26*6777b538SAndroid Build Coastguard Worker "cc", 27*6777b538SAndroid Build Coastguard Worker "chrome", 28*6777b538SAndroid Build Coastguard Worker "chromecast", 29*6777b538SAndroid Build Coastguard Worker "chromeos", 30*6777b538SAndroid Build Coastguard Worker "clank", 31*6777b538SAndroid Build Coastguard Worker "components", 32*6777b538SAndroid Build Coastguard Worker "content", 33*6777b538SAndroid Build Coastguard Worker "courgette", 34*6777b538SAndroid Build Coastguard Worker "crypto", 35*6777b538SAndroid Build Coastguard Worker "dbus", 36*6777b538SAndroid Build Coastguard Worker "device", 37*6777b538SAndroid Build Coastguard Worker "extensions", 38*6777b538SAndroid Build Coastguard Worker "fuchsia_web", 39*6777b538SAndroid Build Coastguard Worker "gin", 40*6777b538SAndroid Build Coastguard Worker "google_apis", 41*6777b538SAndroid Build Coastguard Worker "google_update", 42*6777b538SAndroid Build Coastguard Worker "gpu", 43*6777b538SAndroid Build Coastguard Worker "headless", 44*6777b538SAndroid Build Coastguard Worker "infra", 45*6777b538SAndroid Build Coastguard Worker "internal", 46*6777b538SAndroid Build Coastguard Worker "ios", 47*6777b538SAndroid Build Coastguard Worker "ipc", 48*6777b538SAndroid Build Coastguard Worker "media", 49*6777b538SAndroid Build Coastguard Worker "mojo", 50*6777b538SAndroid Build Coastguard Worker "native_client", 51*6777b538SAndroid Build Coastguard Worker "native_client_sdk", 52*6777b538SAndroid Build Coastguard Worker "net", 53*6777b538SAndroid Build Coastguard Worker "pdf", 54*6777b538SAndroid Build Coastguard Worker "ppapi", 55*6777b538SAndroid Build Coastguard Worker "printing", 56*6777b538SAndroid Build Coastguard Worker "remoting", 57*6777b538SAndroid Build Coastguard Worker "rlz", 58*6777b538SAndroid Build Coastguard Worker "sandbox", 59*6777b538SAndroid Build Coastguard Worker "services", 60*6777b538SAndroid Build Coastguard Worker "skia", 61*6777b538SAndroid Build Coastguard Worker "sql", 62*6777b538SAndroid Build Coastguard Worker "storage", 63*6777b538SAndroid Build Coastguard Worker # third_party/blink handled separately in FindDeclaredFeatures 64*6777b538SAndroid Build Coastguard Worker "ui", 65*6777b538SAndroid Build Coastguard Worker "url", 66*6777b538SAndroid Build Coastguard Worker "v8", 67*6777b538SAndroid Build Coastguard Worker "webkit", 68*6777b538SAndroid Build Coastguard Worker "weblayer", 69*6777b538SAndroid Build Coastguard Worker] 70*6777b538SAndroid Build Coastguard Worker 71*6777b538SAndroid Build Coastguard Workerdef _FindFeaturesInFile(filepath): 72*6777b538SAndroid Build Coastguard Worker # Work on bytes to avoid utf-8 decode errors outside feature declarations 73*6777b538SAndroid Build Coastguard Worker file_contents = pathlib.Path(filepath).read_bytes() 74*6777b538SAndroid Build Coastguard Worker matches = BASE_FEATURE_RE.finditer(file_contents) 75*6777b538SAndroid Build Coastguard Worker # Remove whitespace and surrounding " from the second argument 76*6777b538SAndroid Build Coastguard Worker # which is the feature name. 77*6777b538SAndroid Build Coastguard Worker return [m.group(2).strip().strip(b'"').decode("utf-8") for m in matches] 78*6777b538SAndroid Build Coastguard Worker 79*6777b538SAndroid Build Coastguard Worker 80*6777b538SAndroid Build Coastguard Workerdef FindDeclaredFeatures(input_api): 81*6777b538SAndroid Build Coastguard Worker """Finds all declared feature names in the source code. 82*6777b538SAndroid Build Coastguard Worker 83*6777b538SAndroid Build Coastguard Worker This function will scan all *.cc and *.mm files and look for features 84*6777b538SAndroid Build Coastguard Worker defined with the BASE_FEATURE macro. It will extract the feature names. 85*6777b538SAndroid Build Coastguard Worker 86*6777b538SAndroid Build Coastguard Worker Args: 87*6777b538SAndroid Build Coastguard Worker input_api: InputApi instance for opening files 88*6777b538SAndroid Build Coastguard Worker Returns: 89*6777b538SAndroid Build Coastguard Worker Set of defined feature names in the source tree. 90*6777b538SAndroid Build Coastguard Worker """ 91*6777b538SAndroid Build Coastguard Worker # Features are supposed to be defined in .cc files. 92*6777b538SAndroid Build Coastguard Worker # Iterate over the search folders in the root. 93*6777b538SAndroid Build Coastguard Worker root = pathlib.Path(input_api.change.RepositoryRoot()) 94*6777b538SAndroid Build Coastguard Worker glob_patterns = [str(p / pathlib.Path("**/*.cc")) for p in root.iterdir() if 95*6777b538SAndroid Build Coastguard Worker p.is_dir() and p.name in DIRECTORIES_TO_SEARCH] 96*6777b538SAndroid Build Coastguard Worker 97*6777b538SAndroid Build Coastguard Worker # blink is the only directory in third_party that should be searched. 98*6777b538SAndroid Build Coastguard Worker blink_glob = str(root / pathlib.Path("third_party/blink/**/*.cc")) 99*6777b538SAndroid Build Coastguard Worker glob_patterns.append(blink_glob) 100*6777b538SAndroid Build Coastguard Worker 101*6777b538SAndroid Build Coastguard Worker # Additional features for iOS can be found in mm files in the ios directory. 102*6777b538SAndroid Build Coastguard Worker mm_glob = str(root / pathlib.Path("ios/**/*.mm")) 103*6777b538SAndroid Build Coastguard Worker glob_patterns.append(mm_glob) 104*6777b538SAndroid Build Coastguard Worker 105*6777b538SAndroid Build Coastguard Worker # Create glob iterators that lazily go over the files to search 106*6777b538SAndroid Build Coastguard Worker glob_iterators = [glob.iglob(pattern, recursive=True) for pattern in 107*6777b538SAndroid Build Coastguard Worker glob_patterns] 108*6777b538SAndroid Build Coastguard Worker 109*6777b538SAndroid Build Coastguard Worker # Limit to 4 processes - the disk accesses becomes a bottleneck with just a 110*6777b538SAndroid Build Coastguard Worker # few processes, but splitting the searching across multiple CPUs does yield 111*6777b538SAndroid Build Coastguard Worker # a benefit of a few seconds. 112*6777b538SAndroid Build Coastguard Worker # The exact batch size does not seem to matter much, as long as it is >> 1. 113*6777b538SAndroid Build Coastguard Worker pool = multiprocessing.Pool(4) 114*6777b538SAndroid Build Coastguard Worker found_features = pool.imap_unordered(_FindFeaturesInFile, 115*6777b538SAndroid Build Coastguard Worker itertools.chain(*glob_iterators), 1000) 116*6777b538SAndroid Build Coastguard Worker pool.close() 117*6777b538SAndroid Build Coastguard Worker pool.join() 118*6777b538SAndroid Build Coastguard Worker 119*6777b538SAndroid Build Coastguard Worker feature_names = set() 120*6777b538SAndroid Build Coastguard Worker for feature_list in found_features: 121*6777b538SAndroid Build Coastguard Worker feature_names.update(feature_list) 122*6777b538SAndroid Build Coastguard Worker return feature_names 123