1*9e94795aSAndroid Build Coastguard Worker#!/usr/bin/env python3 2*9e94795aSAndroid Build Coastguard Worker# 3*9e94795aSAndroid Build Coastguard Worker# Copyright (C) 2016 The Android Open Source Project 4*9e94795aSAndroid Build Coastguard Worker# 5*9e94795aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 6*9e94795aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*9e94795aSAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*9e94795aSAndroid Build Coastguard Worker# 9*9e94795aSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*9e94795aSAndroid Build Coastguard Worker# 11*9e94795aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*9e94795aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 13*9e94795aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*9e94795aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*9e94795aSAndroid Build Coastguard Worker# limitations under the License. 16*9e94795aSAndroid Build Coastguard Worker 17*9e94795aSAndroid Build Coastguard Worker"""Tool to prioritize which modules to convert to Soong. 18*9e94795aSAndroid Build Coastguard Worker 19*9e94795aSAndroid Build Coastguard WorkerGenerally, you'd use this through the make integration, which automatically 20*9e94795aSAndroid Build Coastguard Workergenerates the CSV input file that this tool expects: 21*9e94795aSAndroid Build Coastguard Worker 22*9e94795aSAndroid Build Coastguard Worker $ m $OUT/soong_to_convert.txt 23*9e94795aSAndroid Build Coastguard Worker $ less $OUT/soong_to_convert.txt 24*9e94795aSAndroid Build Coastguard Worker 25*9e94795aSAndroid Build Coastguard WorkerThe output is a list of modules that are probably ready to convert to Soong: 26*9e94795aSAndroid Build Coastguard Worker 27*9e94795aSAndroid Build Coastguard Worker # Blocked on Module (potential problems) 28*9e94795aSAndroid Build Coastguard Worker 283 libEGL (srcs_dotarm) 29*9e94795aSAndroid Build Coastguard Worker 246 libicuuc (dotdot_incs dotdot_srcs) 30*9e94795aSAndroid Build Coastguard Worker 221 libspeexresampler 31*9e94795aSAndroid Build Coastguard Worker 215 libcamera_metadata 32*9e94795aSAndroid Build Coastguard Worker ... 33*9e94795aSAndroid Build Coastguard Worker 0 zram-perf (dotdot_incs) 34*9e94795aSAndroid Build Coastguard Worker 35*9e94795aSAndroid Build Coastguard WorkerThe number at the beginning of the line shows how many native modules depend 36*9e94795aSAndroid Build Coastguard Workeron that module. 37*9e94795aSAndroid Build Coastguard Worker 38*9e94795aSAndroid Build Coastguard WorkerAll of their dependencies have been satisfied, and any potential problems 39*9e94795aSAndroid Build Coastguard Workerthat Make can detect are listed in parenthesis after the module: 40*9e94795aSAndroid Build Coastguard Worker 41*9e94795aSAndroid Build Coastguard Worker dotdot_srcs: LOCAL_SRC_FILES contains paths outside $(LOCAL_PATH) 42*9e94795aSAndroid Build Coastguard Worker dotdot_incs: LOCAL_C_INCLUDES contains paths include '..' 43*9e94795aSAndroid Build Coastguard Worker srcs_dotarm: LOCAL_SRC_FILES contains source files like <...>.c.arm 44*9e94795aSAndroid Build Coastguard Worker aidl: LOCAL_SRC_FILES contains .aidl sources 45*9e94795aSAndroid Build Coastguard Worker objc: LOCAL_SRC_FILES contains Objective-C sources 46*9e94795aSAndroid Build Coastguard Worker proto: LOCAL_SRC_FILES contains .proto sources 47*9e94795aSAndroid Build Coastguard Worker rs: LOCAL_SRC_FILES contains renderscript sources 48*9e94795aSAndroid Build Coastguard Worker vts: LOCAL_SRC_FILES contains .vts sources 49*9e94795aSAndroid Build Coastguard Worker 50*9e94795aSAndroid Build Coastguard WorkerNot all problems can be discovered, but this is a starting point. 51*9e94795aSAndroid Build Coastguard Worker 52*9e94795aSAndroid Build Coastguard Worker""" 53*9e94795aSAndroid Build Coastguard Workerimport csv 54*9e94795aSAndroid Build Coastguard Workerimport sys 55*9e94795aSAndroid Build Coastguard Worker 56*9e94795aSAndroid Build Coastguard Workerdef count_deps(depsdb, module, seen): 57*9e94795aSAndroid Build Coastguard Worker """Based on the depsdb, count the number of transitive dependencies. 58*9e94795aSAndroid Build Coastguard Worker 59*9e94795aSAndroid Build Coastguard Worker You can pass in an reversed dependency graph to conut the number of 60*9e94795aSAndroid Build Coastguard Worker modules that depend on the module.""" 61*9e94795aSAndroid Build Coastguard Worker count = 0 62*9e94795aSAndroid Build Coastguard Worker seen.append(module) 63*9e94795aSAndroid Build Coastguard Worker if module in depsdb: 64*9e94795aSAndroid Build Coastguard Worker for dep in depsdb[module]: 65*9e94795aSAndroid Build Coastguard Worker if dep in seen: 66*9e94795aSAndroid Build Coastguard Worker continue 67*9e94795aSAndroid Build Coastguard Worker count += 1 + count_deps(depsdb, dep, seen) 68*9e94795aSAndroid Build Coastguard Worker return count 69*9e94795aSAndroid Build Coastguard Worker 70*9e94795aSAndroid Build Coastguard Workerdef process(reader): 71*9e94795aSAndroid Build Coastguard Worker """Read the input file and produce a list of modules ready to move to Soong 72*9e94795aSAndroid Build Coastguard Worker """ 73*9e94795aSAndroid Build Coastguard Worker problems = dict() 74*9e94795aSAndroid Build Coastguard Worker deps = dict() 75*9e94795aSAndroid Build Coastguard Worker reverse_deps = dict() 76*9e94795aSAndroid Build Coastguard Worker module_types = dict() 77*9e94795aSAndroid Build Coastguard Worker 78*9e94795aSAndroid Build Coastguard Worker for (module, module_type, problem, dependencies, makefiles, installed) in reader: 79*9e94795aSAndroid Build Coastguard Worker module_types[module] = module_type 80*9e94795aSAndroid Build Coastguard Worker problems[module] = problem 81*9e94795aSAndroid Build Coastguard Worker deps[module] = [d for d in dependencies.strip().split(' ') if d != ""] 82*9e94795aSAndroid Build Coastguard Worker for dep in deps[module]: 83*9e94795aSAndroid Build Coastguard Worker if not dep in reverse_deps: 84*9e94795aSAndroid Build Coastguard Worker reverse_deps[dep] = [] 85*9e94795aSAndroid Build Coastguard Worker reverse_deps[dep].append(module) 86*9e94795aSAndroid Build Coastguard Worker 87*9e94795aSAndroid Build Coastguard Worker results = [] 88*9e94795aSAndroid Build Coastguard Worker for module in problems: 89*9e94795aSAndroid Build Coastguard Worker # Only display actionable conversions, ones without missing dependencies 90*9e94795aSAndroid Build Coastguard Worker if len(deps[module]) != 0: 91*9e94795aSAndroid Build Coastguard Worker continue 92*9e94795aSAndroid Build Coastguard Worker 93*9e94795aSAndroid Build Coastguard Worker extra = "" 94*9e94795aSAndroid Build Coastguard Worker if len(problems[module]) > 0: 95*9e94795aSAndroid Build Coastguard Worker extra = " ({})".format(problems[module]) 96*9e94795aSAndroid Build Coastguard Worker results.append((count_deps(reverse_deps, module, []), module + extra, module_types[module])) 97*9e94795aSAndroid Build Coastguard Worker 98*9e94795aSAndroid Build Coastguard Worker return sorted(results, key=lambda result: (-result[0], result[1])) 99*9e94795aSAndroid Build Coastguard Worker 100*9e94795aSAndroid Build Coastguard Workerdef filter(results, module_type): 101*9e94795aSAndroid Build Coastguard Worker return [x for x in results if x[2] == module_type] 102*9e94795aSAndroid Build Coastguard Worker 103*9e94795aSAndroid Build Coastguard Workerdef display(results): 104*9e94795aSAndroid Build Coastguard Worker """Displays the results""" 105*9e94795aSAndroid Build Coastguard Worker count_header = "# Blocked on" 106*9e94795aSAndroid Build Coastguard Worker count_width = len(count_header) 107*9e94795aSAndroid Build Coastguard Worker print("{} Module (potential problems)".format(count_header)) 108*9e94795aSAndroid Build Coastguard Worker for (count, module, module_type) in results: 109*9e94795aSAndroid Build Coastguard Worker print("{:>{}} {}".format(count, count_width, module)) 110*9e94795aSAndroid Build Coastguard Worker 111*9e94795aSAndroid Build Coastguard Workerdef main(filename): 112*9e94795aSAndroid Build Coastguard Worker """Read the CSV file, print the results""" 113*9e94795aSAndroid Build Coastguard Worker with open(filename, 'r') as csvfile: 114*9e94795aSAndroid Build Coastguard Worker results = process(csv.reader(csvfile)) 115*9e94795aSAndroid Build Coastguard Worker 116*9e94795aSAndroid Build Coastguard Worker native_results = filter(results, "native") 117*9e94795aSAndroid Build Coastguard Worker java_results = filter(results, "java") 118*9e94795aSAndroid Build Coastguard Worker 119*9e94795aSAndroid Build Coastguard Worker print("native modules ready to convert") 120*9e94795aSAndroid Build Coastguard Worker display(native_results) 121*9e94795aSAndroid Build Coastguard Worker 122*9e94795aSAndroid Build Coastguard Worker print("") 123*9e94795aSAndroid Build Coastguard Worker print("java modules ready to convert") 124*9e94795aSAndroid Build Coastguard Worker display(java_results) 125*9e94795aSAndroid Build Coastguard Worker 126*9e94795aSAndroid Build Coastguard Workerif __name__ == "__main__": 127*9e94795aSAndroid Build Coastguard Worker if len(sys.argv) != 2: 128*9e94795aSAndroid Build Coastguard Worker print("usage: soong_conversion.py <file>", file=sys.stderr) 129*9e94795aSAndroid Build Coastguard Worker sys.exit(1) 130*9e94795aSAndroid Build Coastguard Worker 131*9e94795aSAndroid Build Coastguard Worker main(sys.argv[1]) 132