Rewrite the lunabuild toolchain with enhanced feature (#60)
[lunaix-os.git] / lunaix-os / scripts / build-tools / shared / export.py
1 from lcfg2.config import ConfigEnvironment
2 from lcfg2.common import NodeProperty
3 from lib.utils import SourceLogger
4 import json
5 import re
6
7 Identifier = re.compile(r"^[A-Za-z_][A-Za-z0-9_]+$")
8
9 class Exporter:
10     def __init__(self, env: ConfigEnvironment):
11         self._env = env
12
13     def export(self, file):
14         lines = []
15
16         for node in self._env.terms():
17             for name, val in self.variants(node):
18                 line = self._format_line(node, name, val)
19                 lines.append(line)
20
21         with open(file, 'w') as f:
22             f.write('\n'.join(lines))
23
24     def _format_line(self, node, name, value):
25         return ""
26
27     def variants(self, node):
28         value    = self.get_value(node)
29         basename = f"CONFIG_{str.upper(node._name)}"
30
31         return [(basename, value)]
32     
33     def get_value(self, node):
34         return ""
35
36
37 class ExportMakefileRules(Exporter):
38     def __init__(self, env: ConfigEnvironment):
39         super().__init__(env)
40
41     def _format_line(self, node, name, value):
42         if not node.enabled():
43             return f"# {name} is disabled"
44         else:
45             return f"{name} := {value}"
46
47     def get_value(self, node):
48         tok = NodeProperty.Token[node]
49         val = NodeProperty.Value[node]
50
51         if type(val) is str:
52             return val
53
54         if type(val) is int:
55             return val
56         
57         if type(val) is bool:
58             return ""
59         
60         SourceLogger.warn(node, tok, 
61             f"value: '{val}' can not mapped to makefile primitives")
62         
63         return "## ERROR ##"
64     
65 class ExportHeaderFile(Exporter):
66     def __init__(self, env: ConfigEnvironment):
67         super().__init__(env)
68
69     def _format_line(self, node, name, value):
70         if not node.enabled():
71             return f"// {name} is disabled"
72         else:
73             return f"#define {name} {value}"
74
75     def get_value(self, node):
76         tok = NodeProperty.Token[node]
77         val = NodeProperty.Value[node]
78
79         if type(val) is str:
80             return f'"{val}"'
81
82         if type(val) is int:
83             return val
84         
85         if type(val) is bool:
86             return ""
87         
88         SourceLogger.warn(node, tok, 
89             f"value: '{val}' can not mapped to C primitives")
90         
91         return "// Error"
92
93 class ExportJsonFile(Exporter):
94     def __init__(self, env):
95         super().__init__(env)
96
97     def export(self, file):
98         obj = {}
99         for n in self._env.terms():
100             obj[n._name] = NodeProperty.Value[n]
101         
102         with open(file, 'w') as f:
103             json.dump(obj, f)
104
105 def restore_config_value(env: ConfigEnvironment, json_path):
106     with open(json_path) as f:
107         j = json.load(f)
108         for k, v in j.items():
109             node = env.get_node(k)
110             if node is None:
111                 print(f"warning: missing node: '{node}', skipped")
112                 continue
113
114             NodeProperty.Value[node] = v
115
116         env.refresh()