Merge branch 'feature/ldgen_output_determinism_v4.1' into 'release/v4.1'

ldgen: determinism in mapping rule order (v4.1)

See merge request espressif/esp-idf!8661
This commit is contained in:
Angus Gratton 2020-05-13 11:30:32 +08:00
commit 8860c1b94c
2 changed files with 62 additions and 3 deletions

View file

@ -322,8 +322,6 @@ class GenerationModel:
return scheme_dictionary
def generate_rules(self, sections_infos):
placement_rules = collections.defaultdict(list)
scheme_dictionary = self._build_scheme_dictionary()
# Generate default rules
@ -353,14 +351,19 @@ class GenerationModel:
for mapping_rules in all_mapping_rules.values():
self._create_exclusions(mapping_rules, default_rules, sections_infos)
placement_rules = collections.defaultdict(list)
# Add the default rules grouped by target
for default_rule in default_rules:
existing_rules = placement_rules[default_rule.target]
if default_rule.get_section_names():
existing_rules.append(default_rule)
for mapping_rules in all_mapping_rules.values():
archives = sorted(all_mapping_rules.keys())
for archive in archives:
# Add the mapping rules grouped by target
mapping_rules = sorted(all_mapping_rules[archive], key=lambda m: (m.specificity, str(m)))
for mapping_rule in mapping_rules:
existing_rules = placement_rules[mapping_rule.target]
if mapping_rule.get_section_names():

View file

@ -1366,6 +1366,62 @@ entries:
self.compare_rules(expected, actual)
def test_rules_order(self):
# The fragments are structured such that ldgen will:
# - parse freertos2 mapping first
# - entry for prvCheckPendingReadyList is parsed first before prvCheckDelayedList
# We expect that despite this, ldgen will output rules in a set order:
# by increasing specificity and alphabetically
test = u"""
[mapping:freertos2]
archive: libfreertos2.a
entries:
croutine2 (noflash_text)
croutine (noflash_text)
[mapping:freertos]
archive: libfreertos.a
entries:
croutine:prvCheckPendingReadyList (noflash_text)
croutine:prvCheckDelayedList (noflash_text)
"""
self.add_fragments(test)
actual = self.model.generate_rules(self.sections_info)
expected = self.generate_default_rules()
flash_text_default = self.get_default("flash_text", expected)
iram0_text_E1 = PlacementRule("libfreertos2.a", "croutine2", None, self.model.sections["text"].entries, "iram0_text")
iram0_text_E2 = PlacementRule("libfreertos2.a", "croutine", None, self.model.sections["text"].entries, "iram0_text")
iram0_text_E3 = PlacementRule("libfreertos.a", "croutine", "prvCheckPendingReadyList", self.model.sections["text"].entries, "iram0_text")
iram0_text_E4 = PlacementRule("libfreertos.a", "croutine", "prvCheckDelayedList", self.model.sections["text"].entries, "iram0_text")
flash_text_extra = PlacementRule("libfreertos.a", "croutine", None, [".text.*", ".literal.*"], "flash_text")
# Add the exclusions
flash_text_default.add_exclusion(iram0_text_E1, self.sections_info)
flash_text_default.add_exclusion(iram0_text_E2, self.sections_info)
flash_text_default.add_exclusion(flash_text_extra, self.sections_info)
flash_text_extra.add_exclusion(iram0_text_E3, self.sections_info)
flash_text_extra.add_exclusion(iram0_text_E4, self.sections_info)
# Add the rules, arranged by expected order
expected["flash_text"].append(flash_text_extra)
expected["iram0_text"].append(iram0_text_E4)
expected["iram0_text"].append(iram0_text_E3)
expected["iram0_text"].append(iram0_text_E2)
expected["iram0_text"].append(iram0_text_E1)
# Perform general comparison for all sections
self.compare_rules(expected, actual)
# Perform ordered comparison
self.assertListEqual(actual["flash_text"], expected["flash_text"])
self.assertListEqual(actual["iram0_text"], expected["iram0_text"])
if __name__ == "__main__":
unittest.main()