Merge "Identify modules ready to be converted to Soong" am: c6bada8acd
am: 6596082d00
Change-Id: I2e814051643c339054ccc02ae2823a6c2fd80e46
This commit is contained in:
commit
52438f9fcf
4 changed files with 175 additions and 0 deletions
|
@ -394,6 +394,22 @@ $(BUILD_SYSTEM_STATS):
|
|||
@$(foreach s,$(STATS.SOONG_MODULE_TYPE),echo "modules_type_soong,$(s),$(STATS.SOONG_MODULE_TYPE.$(s))" >>$@;)
|
||||
$(call dist-for-goals,droidcore,$(BUILD_SYSTEM_STATS))
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# Modules ready to be converted to Soong, ordered by how many
|
||||
# modules depend on them.
|
||||
SOONG_CONV := $(sort $(SOONG_CONV))
|
||||
SOONG_CONV_DATA := $(call intermediates-dir-for,PACKAGING,soong_conversion)/soong_conv_data
|
||||
$(SOONG_CONV_DATA):
|
||||
@rm -f $@
|
||||
@$(foreach s,$(SOONG_CONV),echo "$(s),$(sort $(SOONG_CONV.$(s).PROBLEMS)),$(sort $(filter-out $(SOONG_ALREADY_CONV),$(SOONG_CONV.$(s).DEPS)))" >>$@;)
|
||||
|
||||
SOONG_TO_CONVERT_SCRIPT := build/tools/soong_to_convert.py
|
||||
SOONG_TO_CONVERT := $(PRODUCT_OUT)/soong_to_convert.txt
|
||||
$(SOONG_TO_CONVERT): $(SOONG_CONV_DATA) $(SOONG_TO_CONVERT_SCRIPT)
|
||||
@rm -f $@
|
||||
$(hide) $(SOONG_TO_CONVERT_SCRIPT) $< >$@
|
||||
$(call dist-for-goals,droidcore,$(SOONG_TO_CONVERT))
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# The dev key is used to sign this package, and as the key required
|
||||
# for future OTA packages installed by this system. Actual product
|
||||
|
|
|
@ -30,6 +30,8 @@ else
|
|||
endif
|
||||
endif
|
||||
|
||||
my_soong_problems :=
|
||||
|
||||
# The following LOCAL_ variables will be modified in this file.
|
||||
# Because the same LOCAL_ variables may be used to define modules for both 1st arch and 2nd arch,
|
||||
# we can't modify them in place.
|
||||
|
@ -416,6 +418,16 @@ ifeq (,$(LOCAL_SDK_VERSION)$(WITHOUT_LIBCOMPILER_RT))
|
|||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(filter ../%,$(my_src_files)),)
|
||||
my_soong_problems += dotdot_srcs
|
||||
endif
|
||||
ifneq ($(foreach i,$(my_c_includes),$(filter %/..,$(i))$(findstring /../,$(i))),)
|
||||
my_soong_problems += dotdot_incs
|
||||
endif
|
||||
ifneq ($(filter %.arm,$(my_src_files)),)
|
||||
my_soong_problems += srcs_dotarm
|
||||
endif
|
||||
|
||||
####################################################
|
||||
## Add FDO flags if FDO is turned on and supported
|
||||
## Please note that we will do option filtering during FDO build.
|
||||
|
@ -698,6 +710,7 @@ ALL_GENERATED_SOURCES += $(my_generated_sources)
|
|||
renderscript_sources := $(filter %.rs %.fs,$(my_src_files))
|
||||
|
||||
ifneq (,$(renderscript_sources))
|
||||
my_soong_problems += rs
|
||||
|
||||
renderscript_sources_fullpath := $(addprefix $(LOCAL_PATH)/, $(renderscript_sources))
|
||||
RenderScript_file_stamp := $(intermediates)/RenderScriptCPP.stamp
|
||||
|
@ -777,6 +790,7 @@ endif
|
|||
###########################################################
|
||||
proto_sources := $(filter %.proto,$(my_src_files))
|
||||
ifneq ($(proto_sources),)
|
||||
my_soong_problems += proto
|
||||
proto_gen_dir := $(generated_sources_dir)/proto
|
||||
proto_sources_fullpath := $(addprefix $(LOCAL_PATH)/, $(proto_sources))
|
||||
|
||||
|
@ -859,6 +873,7 @@ endif # $(proto_sources) non-empty
|
|||
dbus_definitions := $(filter %.dbus-xml,$(my_src_files))
|
||||
dbus_generated_headers :=
|
||||
ifneq ($(dbus_definitions),)
|
||||
my_soong_problems += dbus
|
||||
|
||||
dbus_definition_paths := $(addprefix $(LOCAL_PATH)/,$(dbus_definitions))
|
||||
dbus_service_config := $(filter %dbus-service-config.json,$(my_src_files))
|
||||
|
@ -914,6 +929,7 @@ endif # $(dbus_definitions) non-empty
|
|||
aidl_src := $(strip $(filter %.aidl,$(my_src_files)))
|
||||
aidl_gen_cpp :=
|
||||
ifneq ($(aidl_src),)
|
||||
my_soong_problems += aidl
|
||||
|
||||
# Use the intermediates directory to avoid writing our own .cpp -> .o rules.
|
||||
aidl_gen_cpp_root := $(intermediates)/aidl-generated/src
|
||||
|
@ -946,6 +962,7 @@ endif # $(aidl_src) non-empty
|
|||
vts_src := $(strip $(filter %.vts,$(my_src_files)))
|
||||
vts_gen_cpp :=
|
||||
ifneq ($(vts_src),)
|
||||
my_soong_problems += vts
|
||||
|
||||
# Use the intermediates directory to avoid writing our own .cpp -> .o rules.
|
||||
vts_gen_cpp_root := $(intermediates)/vts-generated/src
|
||||
|
@ -1208,6 +1225,7 @@ objc_objects := $(addprefix $(intermediates)/,$(objc_sources:.m=.o))
|
|||
$(call track-src-file-obj,$(objc_sources),$(objc_objects))
|
||||
|
||||
ifneq ($(strip $(objc_objects)),)
|
||||
my_soong_problems += objc
|
||||
$(objc_objects): $(intermediates)/%.o: $(TOPDIR)$(LOCAL_PATH)/%.m \
|
||||
$(my_additional_dependencies)
|
||||
$(transform-$(PRIVATE_HOST)m-to-o)
|
||||
|
@ -1223,6 +1241,7 @@ objcpp_objects := $(addprefix $(intermediates)/,$(objcpp_sources:.mm=.o))
|
|||
$(call track-src-file-obj,$(objcpp_sources),$(objcpp_objects))
|
||||
|
||||
ifneq ($(strip $(objcpp_objects)),)
|
||||
my_soong_problems += objc
|
||||
$(objcpp_objects): $(intermediates)/%.o: $(TOPDIR)$(LOCAL_PATH)/%.mm \
|
||||
$(my_additional_dependencies)
|
||||
$(transform-$(PRIVATE_HOST)mm-to-o)
|
||||
|
@ -1737,3 +1756,15 @@ endif
|
|||
|
||||
# Make sure export_includes gets generated when you are running mm/mmm
|
||||
$(LOCAL_BUILT_MODULE) : | $(export_includes) $(my_link_type)
|
||||
|
||||
ifneq ($(LOCAL_MODULE_MAKEFILE),$(SOONG_ANDROID_MK))
|
||||
SOONG_CONV.$(LOCAL_MODULE).PROBLEMS := \
|
||||
$(SOONG_CONV.$(LOCAL_MODULE).PROBLEMS) $(my_soong_problems)
|
||||
SOONG_CONV.$(LOCAL_MODULE).DEPS := \
|
||||
$(SOONG_CONV.$(LOCAL_MODULE).DEPS) \
|
||||
$(my_static_libraries) \
|
||||
$(my_whole_static_libraries) \
|
||||
$(my_shared_libraries) \
|
||||
$(my_system_shared_libraries)
|
||||
SOONG_CONV := $(SOONG_CONV) $(LOCAL_MODULE)
|
||||
endif
|
||||
|
|
|
@ -79,6 +79,12 @@ else
|
|||
prebuilt_module_is_a_library :=
|
||||
endif
|
||||
|
||||
ifeq ($(LOCAL_MODULE_MAKEFILE),$(SOONG_ANDROID_MK))
|
||||
ifeq ($(prebuilt_module_is_a_library),true)
|
||||
SOONG_ALREADY_CONV := $(SOONG_ALREADY_CONV) $(LOCAL_MODULE)
|
||||
endif
|
||||
endif
|
||||
|
||||
# Don't install static libraries by default.
|
||||
ifndef LOCAL_UNINSTALLABLE_MODULE
|
||||
ifeq (STATIC_LIBRARIES,$(LOCAL_MODULE_CLASS))
|
||||
|
|
122
tools/soong_to_convert.py
Executable file
122
tools/soong_to_convert.py
Executable file
|
@ -0,0 +1,122 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 The Android Open Source Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""Tool to prioritize which modules to convert to Soong.
|
||||
|
||||
Generally, you'd use this through the make integration, which automatically
|
||||
generates the CSV input file that this tool expects:
|
||||
|
||||
$ m $OUT/soong_to_convert.txt
|
||||
$ less $OUT/soong_to_convert.txt
|
||||
|
||||
The output is a list of modules that are probably ready to convert to Soong:
|
||||
|
||||
# Blocked on Module (potential problems)
|
||||
283 libEGL (srcs_dotarm)
|
||||
246 libicuuc (dotdot_incs dotdot_srcs)
|
||||
221 libspeexresampler
|
||||
215 libcamera_metadata
|
||||
...
|
||||
0 zram-perf (dotdot_incs)
|
||||
|
||||
The number at the beginning of the line shows how many native modules depend
|
||||
on that module.
|
||||
|
||||
All of their dependencies have been satisfied, and any potential problems
|
||||
that Make can detect are listed in parenthesis after the module:
|
||||
|
||||
dotdot_srcs: LOCAL_SRC_FILES contains paths outside $(LOCAL_PATH)
|
||||
dotdot_incs: LOCAL_C_INCLUDES contains paths include '..'
|
||||
srcs_dotarm: LOCAL_SRC_FILES contains source files like <...>.c.arm
|
||||
aidl: LOCAL_SRC_FILES contains .aidl sources
|
||||
dbus: LOCAL_SRC_FILES contains .dbus-xml sources
|
||||
objc: LOCAL_SRC_FILES contains Objective-C sources
|
||||
proto: LOCAL_SRC_FILES contains .proto sources
|
||||
rs: LOCAL_SRC_FILES contains renderscript sources
|
||||
vts: LOCAL_SRC_FILES contains .vts sources
|
||||
|
||||
Not all problems can be discovered, but this is a starting point.
|
||||
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import csv
|
||||
import sys
|
||||
|
||||
def count_deps(depsdb, module, seen):
|
||||
"""Based on the depsdb, count the number of transitive dependencies.
|
||||
|
||||
You can pass in an reversed dependency graph to conut the number of
|
||||
modules that depend on the module."""
|
||||
count = 0
|
||||
seen.append(module)
|
||||
if module in depsdb:
|
||||
for dep in depsdb[module]:
|
||||
if dep in seen:
|
||||
continue
|
||||
count += 1 + count_deps(depsdb, dep, seen)
|
||||
return count
|
||||
|
||||
def process(reader):
|
||||
"""Read the input file and produce a list of modules ready to move to Soong
|
||||
"""
|
||||
problems = dict()
|
||||
deps = dict()
|
||||
reverse_deps = dict()
|
||||
|
||||
for (module, problem, dependencies) in reader:
|
||||
problems[module] = problem
|
||||
deps[module] = [d for d in dependencies.strip().split(' ') if d != ""]
|
||||
for dep in deps[module]:
|
||||
if not dep in reverse_deps:
|
||||
reverse_deps[dep] = []
|
||||
reverse_deps[dep].append(module)
|
||||
|
||||
results = []
|
||||
for module in problems:
|
||||
# Only display actionable conversions, ones without missing dependencies
|
||||
if len(deps[module]) != 0:
|
||||
continue
|
||||
|
||||
extra = ""
|
||||
if len(problems[module]) > 0:
|
||||
extra = " ({})".format(problems[module])
|
||||
results.append((count_deps(reverse_deps, module, []), module + extra))
|
||||
|
||||
return sorted(results, key=lambda result: (-result[0], result[1]))
|
||||
|
||||
def display(results):
|
||||
"""Displays the results"""
|
||||
count_header = "# Blocked on"
|
||||
count_width = len(count_header)
|
||||
print("{} Module (potential problems)".format(count_header))
|
||||
for (count, module) in results:
|
||||
print("{:>{}} {}".format(count, count_width, module))
|
||||
|
||||
def main(filename):
|
||||
"""Read the CSV file, print the results"""
|
||||
with open(filename, 'rb') as csvfile:
|
||||
results = process(csv.reader(csvfile))
|
||||
|
||||
display(results)
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) != 2:
|
||||
print("usage: soong_conversion.py <file>", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
main(sys.argv[1])
|
Loading…
Reference in a new issue