rewrite the lunabuild toolchain with enhanced feature
[lunaix-os.git] / lunaix-os / scripts / build-tools / shared / export.py
diff --git a/lunaix-os/scripts/build-tools/shared/export.py b/lunaix-os/scripts/build-tools/shared/export.py
new file mode 100644 (file)
index 0000000..b2c7bb0
--- /dev/null
@@ -0,0 +1,116 @@
+from lcfg2.config import ConfigEnvironment
+from lcfg2.common import NodeProperty
+from lib.utils import SourceLogger
+import json
+import re
+
+Identifier = re.compile(r"^[A-Za-z_][A-Za-z0-9_]+$")
+
+class Exporter:
+    def __init__(self, env: ConfigEnvironment):
+        self._env = env
+
+    def export(self, file):
+        lines = []
+
+        for node in self._env.terms():
+            for name, val in self.variants(node):
+                line = self._format_line(node, name, val)
+                lines.append(line)
+
+        with open(file, 'w') as f:
+            f.write('\n'.join(lines))
+
+    def _format_line(self, node, name, value):
+        return ""
+
+    def variants(self, node):
+        value    = self.get_value(node)
+        basename = f"CONFIG_{str.upper(node._name)}"
+
+        return [(basename, value)]
+    
+    def get_value(self, node):
+        return ""
+
+
+class ExportMakefileRules(Exporter):
+    def __init__(self, env: ConfigEnvironment):
+        super().__init__(env)
+
+    def _format_line(self, node, name, value):
+        if not node.enabled():
+            return f"# {name} is disabled"
+        else:
+            return f"{name} := {value}"
+
+    def get_value(self, node):
+        tok = NodeProperty.Token[node]
+        val = NodeProperty.Value[node]
+
+        if type(val) is str:
+            return val
+
+        if type(val) is int:
+            return val
+        
+        if type(val) is bool:
+            return ""
+        
+        SourceLogger.warn(node, tok, 
+            f"value: '{val}' can not mapped to makefile primitives")
+        
+        return "## ERROR ##"
+    
+class ExportHeaderFile(Exporter):
+    def __init__(self, env: ConfigEnvironment):
+        super().__init__(env)
+
+    def _format_line(self, node, name, value):
+        if not node.enabled():
+            return f"// {name} is disabled"
+        else:
+            return f"#define {name} {value}"
+
+    def get_value(self, node):
+        tok = NodeProperty.Token[node]
+        val = NodeProperty.Value[node]
+
+        if type(val) is str:
+            return f'"{val}"'
+
+        if type(val) is int:
+            return val
+        
+        if type(val) is bool:
+            return ""
+        
+        SourceLogger.warn(node, tok, 
+            f"value: '{val}' can not mapped to C primitives")
+        
+        return "// Error"
+
+class ExportJsonFile(Exporter):
+    def __init__(self, env):
+        super().__init__(env)
+
+    def export(self, file):
+        obj = {}
+        for n in self._env.terms():
+            obj[n._name] = NodeProperty.Value[n]
+        
+        with open(file, 'w') as f:
+            json.dump(obj, f)
+
+def restore_config_value(env: ConfigEnvironment, json_path):
+    with open(json_path) as f:
+        j = json.load(f)
+        for k, v in j.items():
+            node = env.get_node(k)
+            if node is None:
+                print(f"warning: missing node: '{node}', skipped")
+                continue
+
+            NodeProperty.Value[node] = v
+
+        env.refresh()
\ No newline at end of file