Tools: extract_features.py: add option to find feature by string-present-in-codebase
sometimes a features isn't represented by a symbol, but can be found with a specific string....
This commit is contained in:
parent
a04bfff957
commit
e5613de586
@ -24,9 +24,14 @@ else:
|
|||||||
|
|
||||||
class ExtractFeatures(object):
|
class ExtractFeatures(object):
|
||||||
|
|
||||||
def __init__(self, filename, nm="arm-none-eabi-nm"):
|
class FindString(object):
|
||||||
|
def __init__(self, string):
|
||||||
|
self.string = string
|
||||||
|
|
||||||
|
def __init__(self, filename, nm="arm-none-eabi-nm", strings="strings"):
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
self.nm = nm
|
self.nm = nm
|
||||||
|
self.strings = strings
|
||||||
|
|
||||||
# feature_name should match the equivalent feature in
|
# feature_name should match the equivalent feature in
|
||||||
# build_options.py ('FEATURE_NAME', 'EXPECTED_SYMBOL').
|
# build_options.py ('FEATURE_NAME', 'EXPECTED_SYMBOL').
|
||||||
@ -130,7 +135,7 @@ class ExtractFeatures(object):
|
|||||||
('AC_AVOID_ENABLED', 'AC_Avoid::AC_Avoid',),
|
('AC_AVOID_ENABLED', 'AC_Avoid::AC_Avoid',),
|
||||||
('AC_OAPATHPLANNER_ENABLED', 'AP_OAPathPlanner::AP_OAPathPlanner',),
|
('AC_OAPATHPLANNER_ENABLED', 'AP_OAPathPlanner::AP_OAPathPlanner',),
|
||||||
('AC_PAYLOAD_PLACE_ENABLED', 'PayloadPlace::start_descent'),
|
('AC_PAYLOAD_PLACE_ENABLED', 'PayloadPlace::start_descent'),
|
||||||
|
('AP_MISSION_NAV_PAYLOAD_PLACE_ENABLED', ExtractFeatures.FindString('PayloadPlace')),
|
||||||
('AP_ICENGINE_ENABLED', 'AP_ICEngine::AP_ICEngine',),
|
('AP_ICENGINE_ENABLED', 'AP_ICEngine::AP_ICEngine',),
|
||||||
('HAL_EFI_ENABLED', 'AP_RPM_EFI::AP_RPM_EFI',),
|
('HAL_EFI_ENABLED', 'AP_RPM_EFI::AP_RPM_EFI',),
|
||||||
('AP_EFI_NWPWU_ENABLED', r'AP_EFI_NWPMU::update\b',),
|
('AP_EFI_NWPWU_ENABLED', r'AP_EFI_NWPMU::update\b',),
|
||||||
@ -365,36 +370,53 @@ class ExtractFeatures(object):
|
|||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
def extract_strings_from_elf(self, filename):
|
||||||
|
"""Runs strings on filename, returns as a list"""
|
||||||
|
text_output = self.run_program('EF', [
|
||||||
|
self.strings,
|
||||||
|
filename
|
||||||
|
], show_output=False)
|
||||||
|
return text_output.split("\n")
|
||||||
|
|
||||||
def extract(self):
|
def extract(self):
|
||||||
'''returns two sets - compiled_in and not_compiled_in'''
|
'''returns two sets - compiled_in and not_compiled_in'''
|
||||||
|
|
||||||
build_options_defines = set([x.define for x in build_options.BUILD_OPTIONS])
|
build_options_defines = set([x.define for x in build_options.BUILD_OPTIONS])
|
||||||
|
|
||||||
symbols = self.extract_symbols_from_elf(self.filename)
|
symbols = self.extract_symbols_from_elf(self.filename)
|
||||||
|
strings = self.extract_strings_from_elf(self.filename)
|
||||||
|
|
||||||
remaining_build_options_defines = build_options_defines
|
remaining_build_options_defines = build_options_defines
|
||||||
compiled_in_feature_defines = []
|
compiled_in_feature_defines = []
|
||||||
for (feature_define, symbol) in self.features:
|
for (feature_define, symbol) in self.features:
|
||||||
some_dict = symbols.dict_for_symbol(symbol)
|
if isinstance(symbol, ExtractFeatures.FindString):
|
||||||
# look for symbols without arguments
|
if symbol.string in strings:
|
||||||
# print("Looking for (%s)" % str(name))
|
some_define = feature_define
|
||||||
for s in some_dict.keys():
|
if some_define not in build_options_defines:
|
||||||
m = re.match(symbol, s)
|
continue
|
||||||
# print("matching %s with %s" % (symbol, s))
|
compiled_in_feature_defines.append(some_define)
|
||||||
if m is None:
|
remaining_build_options_defines.discard(some_define)
|
||||||
continue
|
else:
|
||||||
d = m.groupdict()
|
some_dict = symbols.dict_for_symbol(symbol)
|
||||||
for key in d.keys():
|
# look for symbols without arguments
|
||||||
d[key] = d[key].upper()
|
# print("Looking for (%s)" % str(name))
|
||||||
# filter to just the defines present in
|
for s in some_dict.keys():
|
||||||
# build_options.py - otherwise we end up with (e.g.)
|
m = re.match(symbol, s)
|
||||||
# AP_AIRSPEED_BACKEND_ENABLED, even 'though that
|
# print("matching %s with %s" % (symbol, s))
|
||||||
# doesn't exist in the ArduPilot codebase.
|
if m is None:
|
||||||
some_define = feature_define.format(**d)
|
continue
|
||||||
if some_define not in build_options_defines:
|
d = m.groupdict()
|
||||||
continue
|
for key in d.keys():
|
||||||
compiled_in_feature_defines.append(some_define)
|
d[key] = d[key].upper()
|
||||||
remaining_build_options_defines.discard(some_define)
|
# filter to just the defines present in
|
||||||
|
# build_options.py - otherwise we end up with (e.g.)
|
||||||
|
# AP_AIRSPEED_BACKEND_ENABLED, even 'though that
|
||||||
|
# doesn't exist in the ArduPilot codebase.
|
||||||
|
some_define = feature_define.format(**d)
|
||||||
|
if some_define not in build_options_defines:
|
||||||
|
continue
|
||||||
|
compiled_in_feature_defines.append(some_define)
|
||||||
|
remaining_build_options_defines.discard(some_define)
|
||||||
return (compiled_in_feature_defines, remaining_build_options_defines)
|
return (compiled_in_feature_defines, remaining_build_options_defines)
|
||||||
|
|
||||||
def create_string(self):
|
def create_string(self):
|
||||||
|
Loading…
Reference in New Issue
Block a user