Tools: validate features are removed when we compile them out

This commit is contained in:
Peter Barker 2023-04-08 12:48:40 +10:00 committed by Peter Barker
parent 6941193cf0
commit 465e8839c8
2 changed files with 66 additions and 8 deletions

View File

@ -23,9 +23,13 @@ from __future__ import print_function
import fnmatch import fnmatch
import optparse import optparse
import os import os
import sys
from pysim import util from pysim import util
sys.path.insert(1, os.path.join(os.path.dirname(__file__), '..', 'scripts'))
import extract_features # noqa
class TestBuildOptionsResult(object): class TestBuildOptionsResult(object):
'''object to return results from a comparison''' '''object to return results from a comparison'''
@ -160,6 +164,29 @@ class TestBuildOptions(object):
self.test_compile_with_defines(defines) self.test_compile_with_defines(defines)
# if the feature is truly disabled then extract_features.py
# should say so:
for target in self.build_targets:
path = self.target_to_elf_path(target)
extracter = extract_features.ExtractFeatures(path)
(compiled_in_feature_defines, not_compiled_in_feature_defines) = extracter.extract()
for define in defines:
# the following defines are known not to work on some
# or all vehicles:
feature_define_whitelist = set([
'AP_RANGEFINDER_ENABLED', # only at vehicle level ATM
'AC_AVOID_ENABLED', # Rover doesn't obey this
'AC_OAPATHPLANNER_ENABLED', # Rover doesn't obey this
'BEACON_ENABLED', # Rover doesn't obey this (should also be AP_BEACON_ENABLED)
'WINCH_ENABLED', # Copter doesn't use this; should use AP_WINCH_ENABLED
])
if define in compiled_in_feature_defines:
error = f"feature gated by {define} still compiled into ({target}); extract_features.py bug?"
if define in feature_define_whitelist:
print("warn: " + error)
else:
raise ValueError(error)
def test_enable_feature(self, feature, options): def test_enable_feature(self, feature, options):
defines = self.get_enable_defines(feature, options) defines = self.get_enable_defines(feature, options)
@ -195,9 +222,9 @@ class TestBuildOptions(object):
(t,)) (t,))
raise raise
def find_build_sizes(self): def target_to_path(self, target, extension=None):
'''returns a hash with size of all build targets''' '''given a build target (e.g. copter), return expected path to .bin
ret = {} file for that target'''
target_to_binpath = { target_to_binpath = {
"copter": "arducopter", "copter": "arducopter",
"plane": "arduplane", "plane": "arduplane",
@ -206,8 +233,26 @@ class TestBuildOptions(object):
"sub": "ardusub", "sub": "ardusub",
"blimp": "blimp", "blimp": "blimp",
} }
filename = target_to_binpath[target]
if extension is not None:
filename += "." + extension
return os.path.join("build", self.board(), "bin", filename)
def target_to_bin_path(self, target):
'''given a build target (e.g. copter), return expected path to .bin
file for that target'''
return self.target_to_path(target, 'bin')
def target_to_elf_path(self, target):
'''given a build target (e.g. copter), return expected path to .elf
file for that target'''
return self.target_to_path(target)
def find_build_sizes(self):
'''returns a hash with size of all build targets'''
ret = {}
for target in self.build_targets: for target in self.build_targets:
path = os.path.join("build", self.board(), "bin", "%s.bin" % target_to_binpath[target]) path = self.target_to_bin_path(target)
ret[target] = os.path.getsize(path) ret[target] = os.path.getsize(path)
return ret return ret
@ -253,9 +298,15 @@ class TestBuildOptions(object):
options = list(filter(lambda x : fnmatch.fnmatch(x.define, self.match_glob), options)) options = list(filter(lambda x : fnmatch.fnmatch(x.define, self.match_glob), options))
count = 1 count = 1
for feature in sorted(options, key=lambda x : x.define): for feature in sorted(options, key=lambda x : x.define):
with open("/tmp/run-disable-in-turn-progress", "w") as f:
print(f.write(f"{count}/{len(options)} {feature.define}\n"))
# if feature.define < "WINCH_ENABLED":
# count += 1
# continue
if feature.define in self.must_have_defines_for_board(self._board): if feature.define in self.must_have_defines_for_board(self._board):
self.progress("Feature %s(%s) (%u/%u) is a MUST-HAVE" % self.progress("Feature %s(%s) (%u/%u) is a MUST-HAVE" %
(feature.label, feature.define, count, len(options))) (feature.label, feature.define, count, len(options)))
count += 1
continue continue
self.progress("Disabling feature %s(%s) (%u/%u)" % self.progress("Disabling feature %s(%s) (%u/%u)" %
(feature.label, feature.define, count, len(options))) (feature.label, feature.define, count, len(options)))

View File

@ -319,9 +319,8 @@ class ExtractFeatures(object):
return ret return ret
def create_string(self): def extract(self):
'''returns two sets - compiled_in and not_compiled_in'''
ret = ""
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])
@ -350,10 +349,18 @@ class ExtractFeatures(object):
continue continue
compiled_in_feature_defines.append(some_define) compiled_in_feature_defines.append(some_define)
remaining_build_options_defines.discard(some_define) remaining_build_options_defines.discard(some_define)
return (compiled_in_feature_defines, remaining_build_options_defines)
def create_string(self):
'''returns a string with compiled in and not compiled-in features'''
(compiled_in_feature_defines, not_compiled_in_feature_defines) = self.extract()
ret = ""
for compiled_in_feature_define in sorted(compiled_in_feature_defines): for compiled_in_feature_define in sorted(compiled_in_feature_defines):
ret += compiled_in_feature_define + "\n" ret += compiled_in_feature_define + "\n"
for remaining in sorted(remaining_build_options_defines): for remaining in sorted(not_compiled_in_feature_defines):
ret += "!" + remaining + "\n" ret += "!" + remaining + "\n"
return ret return ret