Rewrite the lunabuild toolchain with enhanced feature (#60)
[lunaix-os.git] / lunaix-os / scripts / build-tools / luna_build.py
index 3d7f21a92980ab35f3ca5f427017b697a1291ad8..0f96e3e4dfd5901e99bf01e5a0d66b353140aff2 100755 (executable)
 #!/usr/bin/env python 
-
-from lbuild.contract import LunaBuildFile
-from lbuild.common import BuildEnvironment
-
-from lcfg.common import LConfigEnvironment
-from integration.config_io import CHeaderConfigProvider
-from integration.lbuild_bridge import LConfigProvider
-from integration.render_ishell import InteractiveShell
-from integration.build_gen import MakefileBuildGen, install_lbuild_functions
-
-import lcfg.types as lcfg_type
-import lcfg.builtins as builtin
-
-from os import getcwd
-from os import mkdir
-from os.path import abspath, basename, dirname, exists
-from argparse import ArgumentParser
-from lib.utils import join_path
-
-def prepare_lconfig_env(out_dir):
-    provider = CHeaderConfigProvider(join_path(out_dir, "configs.h"))
-    env = LConfigEnvironment(getcwd(), provider)
-
-    env.register_builtin_func(builtin.v)
-    env.register_builtin_func(builtin.term_type)
-    env.register_builtin_func(builtin.parent)
-    env.register_builtin_func(builtin.default)
-    env.register_builtin_func(builtin.include)
-    env.register_builtin_func(builtin.env)
-
-    env.type_factory().regitser(lcfg_type.PrimitiveType)
-    env.type_factory().regitser(lcfg_type.MultipleChoiceType)
-
-    return env
-
-def do_config(lcfg_env):
-    shell = InteractiveShell(lcfg_env)
-    if not shell.render_loop():
-        print("Configuration aborted.")
-        exit(-1)
-
-    lcfg_env.export()
-    lcfg_env.save()
-
-def do_buildfile_gen(opts, lcfg_env):
-    root_path = abspath(opts.root)
-    ws_path = dirname(root_path)
-    root_name = basename(root_path)
-
-    mkgen = MakefileBuildGen(opts.out_dir)
-    env = BuildEnvironment(ws_path, mkgen)
-
-    install_lbuild_functions(env)
-
-    cfg_provider = LConfigProvider(lcfg_env)
-    env.set_config_provider(cfg_provider)
-
-    root = LunaBuildFile(env, root_name)
-
-    try:
-        root.resolve()
-    except Exception as err:
-        print("failed to resolve root build file")
-        raise err
+from argparse           import ArgumentParser
+from pathlib            import Path
+
+from lbuild.build       import BuildEnvironment
+from lbuild.scope       import ScopeProvider
+from lcfg2.builder      import NodeBuilder
+from lcfg2.config       import ConfigEnvironment
+from lcfg2.common       import ConfigNodeError
+
+from shared.export      import ExportJsonFile
+from shared.export      import ExportHeaderFile
+from shared.export      import ExportMakefileRules
+from shared.export      import restore_config_value
+from shared.scopes      import ConfigScope, EnvScope
+from shared.build_gen   import BuildScriptGenerator
+from shared.shconfig    import shconfig
+
+class LunaBuild:
+    def __init__(self, options):
+        self.__lbuilder = BuildEnvironment()
+        self.__lconfig  = ConfigEnvironment()
+        self.__opt = options
+
+        scope = ConfigScope(self.__lconfig)
+        self.__lbuilder.register_scope(scope)
+
+        scope = ScopeProvider("src")
+        scope.file_subscope("c")
+        scope.file_subscope("h")
+        self.__lbuilder.register_scope(scope)
+
+        scope = ScopeProvider("flag")
+        scope.subscope("cc")
+        scope.subscope("ld")
+        self.__lbuilder.register_scope(scope)
+
+        self.__lbuilder.register_scope(EnvScope())
+
+        self.__json  = ExportJsonFile(self.__lconfig)
+        self.__make  = ExportMakefileRules(self.__lconfig)
+        self.__headr = ExportHeaderFile(self.__lconfig)
+        self.__build = BuildScriptGenerator(self.__lbuilder)
+
+    def load(self):
+        file = self.__opt.lconfig
+        NodeBuilder.build(self.__lconfig, file)
+
+        file = self.__opt.lbuild
+        self.__lbuilder.load(file)
+
+        self.__lconfig.refresh()
+        self.__lbuilder.update()
     
-    env.export()
+    def restore(self):
+        save = self.__opt.save
+        if not Path(save).exists():
+            return False
+
+        restore_config_value(self.__lconfig, save)
+        return True
+
+    def save(self):
+        save = self.__opt.save
+        self.__json.export(save)
+        return True
+    
+    def generate(self):
+        outdir = Path(self.__opt.export_dir)
+        if not outdir.exists():
+            outdir.mkdir()
+
+        if self.__opt.gen_build:
+            self.__build.generate(outdir / "build.mkinc")
+
+        if self.__opt.gen_config:
+            self.__make.export(outdir / "config.mkinc")
+            self.__headr.export(outdir / "config.h")
+
+    def visual_config(self):
+        if not self.__lconfig.loaded():
+            print("no config file loaded, skipped interactive config")
+            return
+        
+        if not self.__opt.gen_config:
+            return
+        
+        if not shconfig(self.__lconfig):
+            print("configuration process aborted")
+            exit(1)
 
 def main():
     parser = ArgumentParser()
-    parser.add_argument("--config", action="store_true", default=False)
-    parser.add_argument("--lconfig-file", default="LConfig")
-    parser.add_argument("root", nargs="?", default="LBuild")
-    parser.add_argument("-o", "--out-dir", required=True)
+    parser.add_argument("--lconfig", default="LConfig")
+    parser.add_argument("--lbuild", default="LBuild")
+    parser.add_argument("--save", default=".config.json")
+    parser.add_argument("--gen-build", action="store_true", default=False)
+    parser.add_argument("--gen-config", action="store_true", default=False)
+    parser.add_argument("export_dir")
 
     opts = parser.parse_args()
-    out_dir = opts.out_dir
-    if not exists(out_dir):
-        mkdir(out_dir)
+    builder = LunaBuild(opts)
+
+    try:
+        builder.load()
+        builder.restore()
+    except ConfigNodeError as e:
+        print(e)
+        exit(1)
     
-    lcfg_env = prepare_lconfig_env(out_dir)
-    lcfg_env.resolve_module(opts.lconfig_file)
-    lcfg_env.update()
-    lcfg_env.load()
-
-    if opts.config:
-        do_config(lcfg_env)
-    else:
-        do_buildfile_gen(opts, lcfg_env)
+    builder.visual_config()
+    
+    builder.save()
+    builder.generate()
+
 
 if __name__ == "__main__":
     main()
\ No newline at end of file