integrate C/LDFLAGS into LunaBuild flow
authorMinep <lunaixsky@qq.com>
Thu, 4 Jul 2024 18:44:47 +0000 (19:44 +0100)
committerMinep <lunaixsky@qq.com>
Thu, 4 Jul 2024 18:44:47 +0000 (19:44 +0100)
* allow LBuild framework to accept custom generation implementation
* allow LBuild framework to accept custom built-in function
* separate the compilation flags setting by arch

12 files changed:
lunaix-os/LBuild
lunaix-os/arch/i386/LBuild
lunaix-os/kernel.mk
lunaix-os/makefile
lunaix-os/makeinc/toolchain.mkinc
lunaix-os/scripts/build-tools/integration/build_gen.py [new file with mode: 0644]
lunaix-os/scripts/build-tools/lbuild/api.py
lunaix-os/scripts/build-tools/lbuild/common.py
lunaix-os/scripts/build-tools/lbuild/contract.py
lunaix-os/scripts/build-tools/lcfg/builtins.py
lunaix-os/scripts/build-tools/luna_build.py
lunaix-os/usr/makefile

index f4bb7c847da726eca3e1c1bd757b45ae9f9a0d8f..dcee304424dc51737ad7ee7b0b83604639f367cb 100644 (file)
@@ -6,4 +6,22 @@ use("hal")
 headers([
     "includes",
     "includes/usr"
+])
+
+# compliation setting
+
+compile_opts([
+    "-ffreestanding",
+    "-fno-pie"
+])
+
+linking_opts([
+    "-nostdlib", 
+    "-nolibc", 
+    "-z noexecstack", 
+    "-no-pie", 
+])
+
+linking_opts([
+    "-Wl,--build-id=none"
 ])
\ No newline at end of file
index d4c9a963357a74e39584d9fe2eb94358a3658b7b..8a7f155849086f93a2003ae5c3de0bd0f320dc76 100644 (file)
@@ -41,4 +41,12 @@ sources([
 
 headers([
     "includes"
+])
+
+compile_opts([
+    "-m32"
+])
+
+linking_opts([
+    "-m32"
 ])
\ No newline at end of file
index 9399e7154c0e26cf6db7800767f57d3468576a1c..dff0de2f326750c4bc230fad7c2bbb1b624ae8ab 100644 (file)
@@ -1,37 +1,35 @@
 include os.mkinc
 include toolchain.mkinc
 
-ksrc_files = $(shell cat .builder/sources.list)
-kinc_dirs  = $(shell cat .builder/includes.list)
-khdr_files = $(shell cat .builder/headers.list)
-khdr_files += .builder/configs.h
+include .builder/lbuild.mkinc
 
 kbin_dir := $(BUILD_DIR)
 kbin := $(BUILD_NAME)
 
-ksrc_objs := $(addsuffix .o,$(ksrc_files))
-ksrc_deps := $(addsuffix .d,$(ksrc_files))
-khdr_opts := $(addprefix -include ,$(khdr_files))
-kinc_opts := $(addprefix -I,$(kinc_dirs))
+ksrc_objs := $(addsuffix .o,$(_LBUILD_SRCS))
+ksrc_deps := $(addsuffix .d,$(_LBUILD_SRCS))
+khdr_opts := $(addprefix -include ,$(_LBUILD_HDRS))
+kinc_opts := $(addprefix -I,$(_LBUILD_INCS))
+config_h += -include.builder/configs.h
 
 tmp_kbin  := $(BUILD_DIR)/tmpk.bin
 ksymtable := lunaix_ksyms.o
 
-CFLAGS += $(khdr_opts)
+CFLAGS += $(khdr_opts) $(kinc_opts) $(config_h) -MMD -MP
 
 -include $(ksrc_deps)
 
 %.S.o: %.S $(khdr_files) kernel.mk
        $(call status_,AS,$<)
-       @$(CC) $(CFLAGS) $(kinc_opts) -MMD -MP -c $< -o $@
+       @$(CC) $(CFLAGS) -c $< -o $@
 
 %.c.o: %.c $(khdr_files) kernel.mk
        $(call status_,CC,$<)
-       @$(CC) $(CFLAGS) $(kinc_opts) -MMD -MP -c $< -o $@
+       @$(CC) $(CFLAGS) -c $< -o $@
 
 $(tmp_kbin): $(ksrc_objs)
        $(call status_,LD,$@)
-       @$(CC) -T link/linker.ld $(LDFLAGS) -o $@ $^
+       @$(CC) -T link/linker.ld $(config_h) $(LDFLAGS) -o $@ $^
 
 $(ksymtable): $(tmp_kbin)
        $(call status_,KSYM,$@)
@@ -41,7 +39,7 @@ $(ksymtable): $(tmp_kbin)
 .PHONY: __do_relink
 __do_relink: $(ksrc_objs) $(ksymtable)
        $(call status_,LD,$(kbin))
-       @$(CC) -T link/linker.ld $(LDFLAGS) -o $(kbin) $^
+       @$(CC) -T link/linker.ld $(config_h) $(LDFLAGS) -o $(kbin) $^
        @rm $(tmp_kbin)
 
 .PHONY: all
index 4e132117404662d024b12331de96a7be27eb3111..09ee4b997b64862035ba2659ad225e1ed03b99c2 100644 (file)
@@ -28,12 +28,6 @@ $(DEPS):
                echo "failed" && exit 1;\
        fi
 
-define builder_data
-       .builder/sources.list 
-       .builder/headers.list 
-       .builder/includes.list
-endef
-
 all_lconfigs = $(shell find . -name "LConfig")
 
 $(kbuild_dir):
@@ -48,13 +42,13 @@ $(kbuild_dir):
        @echo 
        @./scripts/build-tools/luna_build.py --config --lconfig-file LConfig -o $(@D)
 
-.builder/%.list: .builder/configs.h
+.builder/lbuild.mkinc: .builder/configs.h
        @./scripts/build-tools/luna_build.py LBuild --lconfig-file LConfig -o $(@D)
 
 .PHONY: kernel
 export BUILD_DIR=$(kbin_dir)
 export BUILD_NAME=$(kbin)
-kernel: $(builder_data)
+kernel: .builder/lbuild.mkinc
        $(call status,TASK,$(notdir $@))
        @$(MAKE) $(MKFLAGS) -I $(mkinc_dir) -f kernel.mk all
 
@@ -96,7 +90,7 @@ clean:
        @$(MAKE) -C usr clean -I $(mkinc_dir)
        @$(MAKE) -f kernel.mk clean -I $(mkinc_dir)
        @rm -rf $(kbuild_dir) || exit 1
-       @rm -f .builder/*.list || exit 1
+       @rm -f .builder/lbuild.mkinc || exit 1
 
 run: all
        @qemu-system-i386 $(call get_qemu_options,$(kimg))
index c9d085f9eca72d7c37ed9f90dc5fe92f669b5774..552c2fd3fcb87410383f3f1d16de61d14fad7de7 100644 (file)
@@ -3,10 +3,6 @@ CC := $(CX_PREFIX)gcc
 AS := $(CX_PREFIX)as
 AR := $(CX_PREFIX)ar
 
-STRIP_OSDEP_CC := -ffreestanding -fno-pie
-STRIP_OSDEP_LD := -nostdlib -nolibc -z noexecstack -no-pie -Wl,--build-id=none
-
-ARCH_OPT := -m32 -D__ARCH_IA32
 O := -O2
 W := -Wall -Wextra -Werror \
                -Wno-unknown-pragmas \
@@ -27,15 +23,15 @@ OFLAGS := -fno-gcse\
                  -fno-indirect-inlining\
                  -fno-omit-frame-pointer
 
-CFLAGS := $(ARCH_OPT) -std=gnu99 $(OFLAGS) $(W)
+CFLAGS := -std=gnu99 $(OFLAGS) $(W)
 
 ifeq ($(BUILD_MODE),debug)
        O = -Og
        CFLAGS += -g
 endif
 
-CFLAGS += $(O) $(STRIP_OSDEP_CC)
+CFLAGS += $(O)
 
-LDFLAGS := $(ARCH_OPT) $(O) $(STRIP_OSDEP_LD)
+LDFLAGS := $(O)
 
 MKFLAGS := --no-print-directory
\ No newline at end of file
diff --git a/lunaix-os/scripts/build-tools/integration/build_gen.py b/lunaix-os/scripts/build-tools/integration/build_gen.py
new file mode 100644 (file)
index 0000000..83c9904
--- /dev/null
@@ -0,0 +1,67 @@
+from lbuild.api import BuildGenerator
+from lbuild.common import BuildEnvironment
+from lib.utils import join_path
+from os import getenv
+
+class MakefileBuildGen(BuildGenerator):
+    def __init__(self, out_dir, name = "lbuild.mkinc") -> None:
+        self.__path = join_path(out_dir, name)
+    
+    def emit_makearray(self, name, values):
+        r = []
+        r.append(f"define {name}")
+        for v in values:
+            r.append(v)
+        r.append("endef")
+        return r
+
+    def generate(self, env: BuildEnvironment):
+        path = env.to_wspath(self.__path)
+        lines = []
+
+        opts = env.get_object("CC_OPTS", [])
+        lines.append("CFLAGS += %s"%(" ".join(opts)))
+        
+        opts = env.get_object("LD_OPTS", [])
+        lines.append("LDFLAGS += %s"%(" ".join(opts)))
+
+        arr = self.emit_makearray("_LBUILD_SRCS", env.srcs())
+        lines += arr
+
+        arr = self.emit_makearray("_LBUILD_HDRS", env.headers())
+        lines += arr
+
+        arr = self.emit_makearray("_LBUILD_INCS", env.includes())
+        lines += arr
+
+        with open(path, 'w') as f:
+            f.write("\n".join(lines))
+        
+
+def install_lbuild_functions(_env: BuildEnvironment):
+    def set_opts(env: BuildEnvironment, name, opts, override):
+        if not isinstance(opts, list):
+            opts = [opts]
+        
+        _opts = env.get_object(name, [])
+
+        if override:
+            _opts = opts
+        else:
+            _opts += opts
+
+        env.set_object(name, _opts)
+
+    def compile_opts(env: BuildEnvironment, opts, override=False):
+        set_opts(env, "CC_OPTS", opts, override)
+
+    def linking_opts(env: BuildEnvironment, opts, override=False):
+        set_opts(env, "LD_OPTS", opts, override)
+
+    def env(env, name, default=None):
+        return getenv(name, default)
+
+
+    _env.add_external_func(compile_opts)
+    _env.add_external_func(linking_opts)
+    _env.add_external_func(env)
\ No newline at end of file
index 2bc91fa9c4ebe1b47280f86bd30c5104ab3d3ff7..9f6f8d47f00e1b3f4cf24c42ae28f6e9b4bdbcd7 100644 (file)
@@ -6,4 +6,11 @@ class ConfigProvider:
         raise ValueError(f"config '{name}' is undefined or disabled")
     
     def has_config(self, name):
-        return False
\ No newline at end of file
+        return False
+    
+class BuildGenerator:
+    def __init__(self) -> None:
+        pass
+
+    def generate(self, env):
+        pass
\ No newline at end of file
index c559b0aab6bfd10dfc7d468153af216378efcd3a..a973760136bacc09dca68c6e56e4f47f0348c2af 100644 (file)
@@ -2,12 +2,15 @@ from lib.utils import join_path
 import os
 
 class BuildEnvironment:
-    def __init__(self, workspace_dir) -> None:
+    def __init__(self, workspace_dir, generator) -> None:
         self.__config_provider = None
         self.__sources = []
         self.__headers = []
         self.__inc_dir = []
         self.__ws_dir = workspace_dir
+        self.__ext_object = {}
+        self.__ext_function = {}
+        self.__generator = generator
 
     def set_config_provider(self, provider):
         self.__config_provider = provider
@@ -29,15 +32,28 @@ class BuildEnvironment:
         path = join_path(self.__ws_dir, file)
         return os.path.relpath(path, self.__ws_dir)
     
-    def export(self, out_dir):
-        path = os.path.join(out_dir, "sources.list")
-        with open(path, "w") as f:
-            f.write("\n".join(self.__sources))
-
-        path = os.path.join(out_dir, "headers.list")
-        with open(path, "w") as f:
-            f.write("\n".join(self.__headers))
-
-        path = os.path.join(out_dir, "includes.list")
-        with open(path, "w") as f:
-            f.write("\n".join(self.__inc_dir))
\ No newline at end of file
+    def export(self):
+        self.__generator.generate(self)
+
+    def get_object(self, key, _default=None):
+        return _default if key not in self.__ext_object else self.__ext_object[key]
+
+    def set_object(self, key, object):
+        self.__ext_object[key] = object
+
+    def srcs(self):
+        return list(self.__sources)
+    
+    def headers(self):
+        return list(self.__headers)
+    
+    def includes(self):
+        return list(self.__inc_dir)
+    
+    def add_external_func(self, function):
+        name = function.__name__
+        invk = lambda *args, **kwargs: function(self, *args, **kwargs)
+        self.__ext_function[name] = invk
+
+    def external_func_table(self):
+        return self.__ext_function
\ No newline at end of file
index 1b818ab6d82928cfc64b8da7b15b22bc45986471..643be143ee6aa0bffd0cc70c8931a5c038c6f8ab 100644 (file)
@@ -18,7 +18,8 @@ class LunaBuildFile(Sandbox):
             "config":
                 lambda name: self.read_config(name),
             "use":
-                lambda file: self.import_buildfile(file)
+                lambda file: self.import_buildfile(file),
+            **env.external_func_table()
         })
         
         self.__srcs = []
index 9eb616f59732856e2ba7e642da462c1dd734afcd..7a46699a0b30c9b3899deaa036c8c943f5d8553c 100644 (file)
@@ -29,4 +29,8 @@ def parent(env, caller, ref):
 
 @contextual(caller_type=[LCTermNode])
 def default(env, caller, val):
-    caller.set_default(val)
\ No newline at end of file
+    caller.set_default(val)
+
+@builtin()
+def env(env, key, default=None):
+    return os.getenv(key, default)
\ No newline at end of file
index 848ceb6b5e51e7fd1c7e36da81a1c5b7ac0b5a6a..3d7f21a92980ab35f3ca5f427017b697a1291ad8 100755 (executable)
@@ -7,6 +7,7 @@ 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
@@ -26,6 +27,7 @@ def prepare_lconfig_env(out_dir):
     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)
@@ -46,7 +48,10 @@ def do_buildfile_gen(opts, lcfg_env):
     ws_path = dirname(root_path)
     root_name = basename(root_path)
 
-    env = BuildEnvironment(ws_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)
@@ -59,7 +64,7 @@ def do_buildfile_gen(opts, lcfg_env):
         print("failed to resolve root build file")
         raise err
     
-    env.export(opts.out_dir)
+    env.export()
 
 def main():
     parser = ArgumentParser()
index e49d7d05ee68ffb5ef40046a86fa8a35c7112511..4dc8d0d67f4ac970673a48a1238bef86df7306c6 100644 (file)
@@ -3,6 +3,10 @@ include toolchain.mkinc
 
 task := all
 
+# TODO make this use LBuild
+CFLAGS += -m32 -ffreestanding -fno-pie
+LDFLAGS += -m32 -nostdlib -nolibc -z noexecstack -no-pie -Wl,--build-id=none
+
 sys_include := $(CURDIR)/includes
 build_dir := $(CURDIR)/build
 libc_name := liblunac