scripts: introduce footprint diffing

Very simple script to diff between two ram or rom reports generated by
size_report. When you call call the ram_report or rom_report targets you
end up with a json file in the build directory that can be used as input
for this script.

The output shows which symbols insreased and which decreased in size and
also tracked added/remove symbols as well.

Signed-off-by: Anas Nashif <anas.nashif@intel.com>
diff --git a/scripts/footprint/fpdiff.py b/scripts/footprint/fpdiff.py
new file mode 100755
index 0000000..3c4172b
--- /dev/null
+++ b/scripts/footprint/fpdiff.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python3
+# Copyright (c) 2021 Intel Corporation
+#
+# SPDX-License-Identifier: Apache-2.0
+
+# A script to diff between two ram or rom reports generated by
+# size_report. When you call call the ram_report or rom_report targets you
+# end up with a json file in the build directory that can be used as input
+# for this script.
+
+# The output shows which symbols insreased and which decreased in size and
+# also tracked added/remove symbols as well.
+
+# Example:
+#    ./scripts/footprint/fpdiff.py ram1.json ram2.json
+
+from anytree.importer import DictImporter
+from anytree import PreOrderIter
+from anytree.search  import find
+
+from colorama import Fore
+import json
+import argparse
+
+importer = DictImporter()
+
+def parse_args():
+    parser = argparse.ArgumentParser(
+                description="Compare footprint sizes of two builds.")
+    parser.add_argument("file1", help="First file")
+    parser.add_argument("file2", help="Second file")
+
+    return parser.parse_args()
+
+def main():
+    args = parse_args()
+
+    with open(args.file1, "r") as f:
+        data = json.load(f)
+        root1 = importer.import_(data['symbols'])
+
+    with open(args.file2, "r") as f:
+        data = json.load(f)
+        root2 = importer.import_(data['symbols'])
+
+    for node in PreOrderIter(root1):
+        # pylint: disable=undefined-loop-variable
+        n = find(root2, lambda node2: node2.identifier == node.identifier)
+        if n:
+            if n.size != node.size:
+                diff = n.size - node.size
+                if diff == 0:
+                    continue
+                if not n.children or not n.parent:
+                    if diff < 0:
+                        print(f"{n.identifier} -> {Fore.GREEN}{diff}{Fore.RESET}")
+                    else:
+                        print(f"{n.identifier} -> {Fore.RED}+{diff}{Fore.RESET}")
+
+        else:
+            if not node.children:
+                print(f"{node.identifier} ({Fore.GREEN}-{node.size}{Fore.RESET}) disappeared.")
+
+    for node in PreOrderIter(root2):
+        n = find(root1, lambda node2: node2.identifier == node.identifier)
+        if not n:
+            if not node.children and node.size != 0:
+                print(f"{node.identifier} ({Fore.RED}+{node.size}{Fore.RESET}) is new.")
+
+
+if __name__ == "__main__":
+    main()