]> rtime.felk.cvut.cz Git - omk.git/commitdiff
Initial support for NuttX user-space programs build.
authorPavel Pisa <ppisa@pikron.com>
Fri, 23 Aug 2019 14:27:11 +0000 (16:27 +0200)
committerPavel Pisa <ppisa@pikron.com>
Fri, 23 Aug 2019 14:27:11 +0000 (16:27 +0200)
bin_PROGRAMS and test_PROGRAMS are build in multiple variants:
 - they are build as standalone loadable ELF programs
   which start from program provided main() symbol
 - then each program is linked with NuttX libraries
   which for NuttX flat target creates complete
   system image, main() can be configured as startup
   symbol in CONFIG_USER_ENTRYPOINT

bin_PROGRAMS are in addition build as objects with
symbols stripped and main() renamed to program_name_main().
The objects are added into registry and if some of programs
specifies list of commands (prgram_name_PROGBUILTIN)
which should be linked into final executable then these
programs are available in binfs image. If the "all" symbol
is used instead of individual programs then all programs
from the build are linked into system image. External registry
can be specified as well by NUTTXREGISTRY define.

Signed-off-by: Pavel Pisa <ppisa@pikron.com>
snippets/Makefile.rules.nuttx [new file with mode: 0644]
snippets/base.omk
snippets/nuttx-bin.omk [new file with mode: 0644]
snippets/nuttx-compile.omk [new file with mode: 0644]

diff --git a/snippets/Makefile.rules.nuttx b/snippets/Makefile.rules.nuttx
new file mode 100644 (file)
index 0000000..ac8bbb1
--- /dev/null
@@ -0,0 +1,10 @@
+OMK_RULES_TYPE=nuttx
+include base.omk #omkbuild
+include nuttx-compile.omk #omkbuild
+include include.omk #omkbuild
+include sysless.omk #omkbuild
+include nuttx-bin.omk #omkbuild
+include cmetric.omk #omkbuild
+include config_h.omk #omkbuild
+include sources-list.omk #omkbuild
+include localeval.omk #omkbuild
index d43428f90dbb664a849bee04682f9702e8205025..e4e75be2a9e96d081a642abc9a477b758d1a4e25 100644 (file)
@@ -1,6 +1,7 @@
 #  Makefile.rules - OCERA make framework common project rules -*- makefile-gmake -*-
 #
 #  (C) Copyright 2003, 2006, 2007, 2008, 2009  by Pavel Pisa - OCERA team member
+#  (C) Copyright 2009, 2010, 2011, 2013, 2015, 2016, 2017, 2019 by Pavel Pisa - PiKRON.com
 #  (C) Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2013, 2015 by Michal Sojka - Czech Technical University, FEE, DCE
 #
 #  Homepage: http://rtime.felk.cvut.cz/omk/
diff --git a/snippets/nuttx-bin.omk b/snippets/nuttx-bin.omk
new file mode 100644 (file)
index 0000000..3d14dbe
--- /dev/null
@@ -0,0 +1,30 @@
+
+# Final rules for NuttX binaries build requests preparation
+
+# Interface to other rules:
+
+# Input variables:
+# bin_PROGRAMS     .. list of the require binary programs
+# utils_PROGRAMS   .. list of the development utility programs
+# USER_BIN_DIR     .. directory to store final executables
+# USER_TESTS_DIR   .. directory to store test executables
+
+# Defined variables
+# USER_REGISTRY_DIR .. directory where registry for builtin applications is stored
+
+USER_REGISTRY_DIR = $(USER_COMPILED_DIR_NAME)/registry
+
+check-dir::
+       @$(call mkdir_def,$(USER_REGISTRY_DIR))
+
+$(foreach prog,$(bin_PROGRAMS),$(eval $(call ELF_template,$(prog),$(USER_BIN_DIR))))
+$(foreach prog,$(test_PROGRAMS),$(eval $(call ELF_template,$(prog),$(USER_TESTS_DIR))))
+
+binary-pass-local:  $(bin_PROGRAMS:%=$(USER_BIN_DIR)/%.elf) $(test_PROGRAMS:%=$(USER_TESTS_DIR)/%.elf)
+
+$(foreach prog,$(bin_PROGRAMS),$(eval $(call PROGBUILTIN_template,$(prog),$(USER_REGISTRY_DIR),$(USER_REGISTRY_DIR))))
+
+library-pass-local:  $(bin_PROGRAMS:%=$(USER_REGISTRY_DIR)/%.pbi)
+
+clean-local::
+       $(Q)rm -f $(bin_PROGRAMS:%=$(USER_REGISTRY_DIR)/%.*)
diff --git a/snippets/nuttx-compile.omk b/snippets/nuttx-compile.omk
new file mode 100644 (file)
index 0000000..a4a74d1
--- /dev/null
@@ -0,0 +1,302 @@
+
+# Rules for NuttX binaries compilation of C, C++ and assembler
+# sources using GNU toolchain.
+
+# Interface to other rules:
+
+# Input variables:
+# NUTTX_EXPORT - export directory of NuttX build
+#                it should contain subdirectories:
+#                arch  build  include  libs  registry  startup)
+# LIB_DIR - directory where compiled libraries are stored
+# OBJS_DIR - directory where intermediate files (.o, .map, ...) are stored
+# INCLUDE_DIR - where includes can be found
+# from config.omk or Makefile.omk
+# CROSS_COMPILE - target architecture tools prefix
+# TARGET_ARCH, DEBUG, OPTIMIZE, DEFS - forms CFLAGS
+# from base: SOURCES_DIR
+# from Makefile.omk: lib_LOADLIBES
+
+# Output variables:
+# SOURCES - all the source files that needs to be compiled (except for shared library sources)
+# SOLIB_SOURCES - all the source files that needs to be compiled for a shared library
+# OBJ_EXT - extension of object files
+# LIB_EXT - extension of library files
+# LIB_PREF - prefix for library files
+# ASM_EXT - extension of assembler sources
+
+# Templates:
+# COMPILER_DEFS_template - definitions that should be defined before
+# the following templates can be used. The input variables needs to be
+# defined before evaluating this template
+
+# COMPILE_c_o_template, COMPILE_cc_o_template, COMPILE_S_o_template -
+# templates that create rules for compilation of sources
+
+# PROGRAM_template, LIBRARY_template, SOLIB_template - templates that
+# create rules for compilation of a program, library and shared
+# library. The rules can use rules produced by COMPILE_xxx_template.
+
+define COMPILER_DEFS_template
+OBJ_EXT = .o
+LIB_EXT = .a
+LIB_PREF = lib
+ASM_EXT = .S
+
+CC = $(CROSS_COMPILE)gcc
+CXX = $(CROSS_COMPILE)g++
+LINK = $(CROSS_COMPILE)ld
+AR = $(CROSS_COMPILE)ar
+OBJCOPY = $(CROSS_COMPILE)objcopy
+NM = $(CROSS_COMPILE)nm
+
+CFLAGS += $(TARGET_ARCH) $(DEBUG) $(OPTIMIZE)
+CFLAGS += -Wall
+CFLAGS += -I$(SOURCES_DIR)
+CFLAGS += -I$(INCLUDE_DIR)
+
+LOADLIBES += -L$(LIB_DIR)
+LOADLIBES += $(lib_LOADLIBES:%=-l%)
+
+
+-include $(OBJS_DIR)/*.d
+
+SOURCES2OBJS = .o/.c .o/.cc .o/.cxx .o/.S .o/.s .o/.o
+
+SOURCES2OBJSLO = .lo/.c .lo/.cc .lo/.cxx .lo/.S .lo/.s .lo/.lo
+
+#%.lo: %.c
+#      $(CC) -o $@ $(LCFLAGS) -c $<
+
+c_o_COMPILE = $$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(OMK_CPPFLAGS) \
+       $(CPPFLAGS) $(OMK_CFLAGS) $$(CFLAGS)
+
+cc_o_COMPILE = $$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(OMK_CPPFLAGS) \
+       $(CPPFLAGS) $(CXXFLAGS) $(OMK_CFLAGS) $$(CFLAGS)
+
+S_o_COMPILE = $$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+       $(CPPFLAGS) $(OMK_CFLAGS) $$(CFLAGS) $(ASFLAGS)
+
+
+# Check GCC version for user build
+ifndef CC_MAJOR_VERSION
+CC_MAJOR_VERSION = $$(shell $$(CC) -dumpversion | $(SED4OMK) -e 's/\([^.]\)\..*/\1/')
+endif
+# Prepare suitable define for dependency building
+ifeq ($$(CC_MAJOR_VERSION),2)
+CC_DEPFLAGS = -Wp,-MD,"$$@.d.tmp"
+else
+CC_DEPFLAGS = -MT $$@ -MD -MP -MF "$$@.d.tmp"
+endif
+
+endef # COMPILER_DEFS_template
+
+
+# Syntax: $(call COMPILE_c_o_template,<source>,<target>,<additional c-flags>)
+define COMPILE_c_o_template
+$(2): $(1) $$(GEN_HEADERS)
+       @$(QUIET_CMD_ECHO) "  CC      $$@"
+       $(Q) if $$(c_o_COMPILE) $$(CC_DEPFLAGS) $(3) -o $$@ -c $$< ; \
+       then mv -f "$$@.d.tmp" "$$@.d" ; \
+       else rm -f "$$@.d.tmp" ; exit 1; \
+       fi
+endef
+
+
+# Syntax: $(call COMPILE_cc_o_template,<source>,<target>,<additional c-flags>)
+define COMPILE_cc_o_template
+$(2): $(1) $$(GEN_HEADERS)
+       @$(QUIET_CMD_ECHO) "  CXX     $$@"
+       $(Q) if $$(cc_o_COMPILE) $$(CC_DEPFLAGS) $(3) -o $$@ -c $$< ; \
+       then mv -f "$$@.d.tmp" "$$@.d" ; \
+       else rm -f "$$@.d.tmp" ; exit 1; \
+       fi
+endef
+
+# Syntax: $(call COMPILE_S_o_template,<source>,<target>,<additional c-flags>)
+define COMPILE_S_o_template
+$(2): $(1) $$(GEN_HEADERS)
+       @$(QUIET_CMD_ECHO) "  AS      $$@"
+       $(Q) if $$(S_o_COMPILE) -D__ASSEMBLY__ $$(CC_DEPFLAGS) $(3) -o $$@ -c $$< ; \
+       then if [ -e "$$@.d.tmp" ] ; then mv -f "$$@.d.tmp" "$$@.d" ; fi ; \
+       else rm -f "$$@.d.tmp" ; exit 1; \
+       fi
+endef
+
+# Syntax: $(call PROGRAM_template,<executable-name>,<dir>,<link-variant>)
+define PROGRAM_template
+
+GEN_SOURCES += $$($(1)_GEN_SOURCES)
+
+$(foreach x, $(SOURCES2OBJS),
+$(1)_OBJS += $$(patsubst %$(notdir $(x)),%$(dir $(x)),$$(filter %$(notdir $(x)),\
+               $$($(1)_SOURCES) $$($(1)_GEN_SOURCES)))
+)
+$(1)_OBJS := $$(sort $$($(1)_OBJS:%/=%))
+
+SOURCES += $$($(1)_SOURCES)
+
+ifneq ($$($(1)_PROGBUILTIN),)
+ifneq ($$($(1)_PROGBUILTIN),all)
+$(1)_PROGBUILTIN_LIST = $$($(1)_PROGBUILTIN)
+else
+$(1)_PROGBUILTIN_TMP = $$(wildcard $$(USER_COMPILED_DIR_NAME)/registry/*.pbi)
+$(1)_PROGBUILTIN_LIST = $$($(1)_PROGBUILTIN_TMP:$$(USER_COMPILED_DIR_NAME)/registry/%.pbi=%)
+endif
+#$$(warning $(1)_PROGBUILTIN_LIST=$$($(1)_PROGBUILTIN_LIST))
+
+$(1)_PROGBUILTIN_PBI=$$($(1)_PROGBUILTIN_LIST:%=$$(USER_COMPILED_DIR_NAME)/registry/%.pbi)
+$(1)_PROGBUILTIN_ldat=$$($(1)_PROGBUILTIN_LIST:%=$$(USER_COMPILED_DIR_NAME)/registry/%.ldat)
+$(1)_PROGBUILTIN_PDAT=$$($(1)_PROGBUILTIN_LIST:%=$$(USER_COMPILED_DIR_NAME)/registry/%.pdat) \
+       $$(wildcard $(NUTTXREGISTRY)/*.pdat)
+$(1)_PROGBUILTIN_BDAT=$$($(1)_PROGBUILTIN_LIST:%=$$(USER_COMPILED_DIR_NAME)/registry/%.bdat) \
+       $$(wildcard $(NUTTXREGISTRY)/*.bdat)
+
+ifneq ($$($(1)_PROGBUILTIN_PDAT),)
+$(1)_BUILTINTABLE = $(OBJS_DIR)/$(1)-builtintab.c
+
+$$($(1)_BUILTINTABLE): $$($(1)_PROGBUILTIN_PDAT) $$($(1)_PROGBUILTIN_BDAT)
+       $(Q) cat $$($(1)_PROGBUILTIN_PDAT) >$$@
+       $(Q) echo "#include <nuttx/config.h>" >>$$@
+       $(Q) echo "#include <nuttx/binfmt/builtin.h>" >>$$@
+       $(Q) echo "const struct builtin_s g_builtins[] = {" >>$$@
+       $(Q) cat $$($(1)_PROGBUILTIN_BDAT) >>$$@
+       $(Q) echo "{ NULL, 0, 0, 0 }};" >>$$@
+       $(Q) echo "const int g_builtin_count = sizeof(g_builtins) / sizeof(g_builtins[0]);" >>$$@
+
+GEN_SOURCES += $$($(1)_BUILTINTABLE)
+endif
+endif
+
+
+ifneq ($$(LD_SCRIPT$(3:%=-%)),)
+$(1)$(3:%=-%)_LD_SCRIPT_FN = $$(LD_SCRIPT$(3:%=-%))
+else
+$(1)$(3:%=-%)_LD_SCRIPT_FN = $$(LD_SCRIPT)
+endif
+
+$$(warning $(1)$(3:%=-%)_LD_SCRIPT_FN = $$($(1)$(3:%=-%)_LD_SCRIPT_FN))
+
+ifeq ($$(dir $$($(1)$(3:%=-%)_LD_SCRIPT_FN)),)
+$(1)$(3:%=-%)_LD_SCRIPT = $$(LIB_DIR)/$$($(1)$(3:%=-%)_LD_SCRIPT_FN)
+else
+$(1)$(3:%=-%)_LD_SCRIPT = $$($(1)$(3:%=-%)_LD_SCRIPT_FN)
+endif
+
+$(1)$(3:%=-%)_LDFLAGS = -Wl,-T,$$($(1)$(3:%=-%)_LD_SCRIPT)
+
+$$(warning $(1)$(3:%=-%)_LDFLAGS = $$($(1)$(3:%=-%)_LDFLAGS))
+
+$(2)/$(1)$(3:%=-%): $$($(1)_OBJS) $$($(1)_BUILTINTABLE:%.c=%.o) $$($(1)_PROGBUILTIN_ldat) $$($(1)$(3:%=-%)_LD_SCRIPT)
+       @$(QUIET_CMD_ECHO) "  LINK    $$@"
+       $(Q) if [ -n "$$($(1)_PROGBUILTIN_LIST)" ] ; then echo ; fi
+       $(Q) $$(if $$(filter %.cc,$$($(1)_SOURCES)) , \
+         $$(CXX) $$(CPPFLAGS) $$(OMK_CPPFLAGS) $$(OMK_CXXFLAGS) $$(CXXFLAGS) , \
+         $$(CC)  $$(CPPFLAGS) $$(OMK_CPPFLAGS) $$(OMK_CFLAGS)   $$(CFLAGS) ) \
+         $$(OMK_LDFLAGS) $$(LDFLAGS) $$($(1)$(3:%=-%)_LDFLAGS) -Wl,-Map,$(1)$(3:%=-%).map \
+         $$($(1)_OBJS) $$($(1)_MOREOBJS) $$($(1)_BUILTINTABLE:%.c=%.o) \
+         $$($(1)_PROGBUILTIN_PBI) $$(LOADLIBES) $$($(1)_LIBS:%=-l%) \
+         $$(shell for i in $$($(1)_PROGBUILTIN_ldat); do cat $$$$i ; done) $$(NUTTXLIBES) \
+         -o $$@
+       @echo "$(2)/$(1)$(3:%=-%): \\" >$(OBJS_DIR)/$(1)$(3:%=-%).exe.d
+       @$(SED4OMK) -n -e 's|^LOAD \(.*\)$$$$|  \1  \&|p' $(OBJS_DIR)/$(1)$(3:%=-%).map|tr '&' '\134'  >>$(OBJS_DIR)/$(1)$(3:%=-%).exe.d
+       @echo >>$(OBJS_DIR)/$(1).exe.d
+endef
+
+# Syntax: $(call ELF_template,<executable-name>,<dir>)
+define ELF_template
+
+$(2)/$(1).elf: $$($(1)_OBJS)
+       @$(QUIET_CMD_ECHO) "  ELF     $$@"
+       $(Q) $(LINK) \
+         -r -e main -T $(NUTTX_EXPORT)/build/gnu-elf.ld \
+         -Map $(1).elf.map \
+         $$($(1)_OBJS) $$($(1)_MOREOBJS) $$(LOADLIBES) $$($(1)_LIBS:%=-l%) \
+         -o $$@
+       @echo "$(2)/$(1).elf: \\" >$(OBJS_DIR)/$(1).elf.d
+       @echo "  $(NUTTX_EXPORT)/build/gnu-elf.ld \\" >>$(OBJS_DIR)/$(1).elf.d
+       @$(SED4OMK) -n -e 's|^LOAD \(.*\)$$$$|  \1  \&|p' $(OBJS_DIR)/$(1).elf.map|tr '&' '\134'  >>$(OBJS_DIR)/$(1).elf.d
+       @echo >>$(OBJS_DIR)/$(1).elf.d
+endef
+
+# Syntax: $(call PROGBUILTIN_template,<executable-name>,<dir>,<registry-dir>)
+define PROGBUILTIN_template
+
+$(1)_PRIORITY ?= SCHED_PRIORITY_DEFAULT
+$(1)_STACKSIZE ?= 2048
+
+$(2)/$(1).pbi: $$($(1)_OBJS)
+       @$(QUIET_CMD_ECHO) "  PROGMOD $$@"
+       $(Q) $(LINK) \
+         -r -x --defsym=$(1)_main=main \
+         -Map $(1).pbi.map \
+         $$($(1)_OBJS) $$($(1)_MOREOBJS) \
+         -o $(OBJS_DIR)/$(1).pbo
+       $(Q) $(OBJCOPY) --keep-global-symbol=$(1)_main $(OBJS_DIR)/$(1).pbo $$@
+       @echo "$(2)/$(1).pbi: \\" >$(OBJS_DIR)/$(1).pbi.d
+       @$(SED4OMK) -n -e 's|^LOAD \(.*\)$$$$|  \1  \&|p' $(OBJS_DIR)/$(1).pbi.map|tr '&' '\134'  >>$(OBJS_DIR)/$(1).pbi.d
+       @echo >>$(OBJS_DIR)/$(1).pbi.d
+       @echo "{ \"$1\", $$($(1)_PRIORITY), $$($(1)_STACKSIZE), $(1)_main }," >$(3)/$(1).bdat
+       @echo "int $(1)_main(int argc, char *argv[]);" >$(3)/$(1).pdat
+       @echo "$$(LOADLIBES) $$($(1)_LIBS:%=-l%)" >$(3)/$(1).ldat
+endef
+
+
+# Rules for other output formats (can be specified by OUTPUT_FORMATS)
+%.bin: %
+       @$(QUIET_CMD_ECHO) "  OBJCOPY $@"
+       $(Q) $(OBJCOPY)  --output-target=binary -S $< $@
+
+%.hex: %
+       @$(QUIET_CMD_ECHO) "  OBJCOPY $@"
+       $(Q) $(OBJCOPY)  --output-target=ihex -S $< $@
+
+%.srec: %
+       @$(QUIET_CMD_ECHO) "  OBJCOPY $@"
+       $(Q) $(OBJCOPY)  --output-target=srec -S $< $@
+
+# Syntax: $(call LIBRARY_template,<library-name>)
+define LIBRARY_template
+
+GEN_SOURCES += $$($(1)_GEN_SOURCES)
+
+$(foreach x, $(SOURCES2OBJS),
+$(1)_OBJS += $$(patsubst %$(notdir $(x)),%$(dir $(x)),$$(filter %$(notdir $(x)),\
+               $$($(1)_SOURCES) $$($(1)_GEN_SOURCES)))
+)
+$(1)_OBJS := $$(sort $$($(1)_OBJS:%/=%))
+
+SOURCES += $$($(1)_SOURCES)
+
+$(LIB_DIR)/lib$(1).a: $$($(1)_OBJS)
+       @$(QUIET_CMD_ECHO) "  AR      $$@"
+       $(Q) $(AR) rcs $$@ $$^
+endef
+
+
+# Syntax: $(call SOLIB_template,<library-name>)
+define SOLIB_template
+
+SOLIB_GEN_SOURCES += $$($(1)_GEN_SOURCES)
+
+$(foreach x, $(SOURCES2OBJSLO),
+$(1)_OBJSLO += $$(patsubst %$(notdir $(x)),%$(dir $(x)),$$(filter %$(notdir $(x)),\
+               $$($(1)_SOURCES) $$($(1)_GEN_SOURCES)))
+)
+$(1)_OBJSLO := $$(sort $$($(1)_OBJSLO:%/=%))
+
+SOLIB_OBJS  += $$($(1)_OBJSLO)
+SOLIB_SOURCES += $$($(1)_SOURCES)
+
+$(LIB_DIR)/lib$(1).so: $$($(1)_OBJSLO)
+       @$(QUIET_CMD_ECHO) "  LINK    $$@"
+       $(Q) $(LD) --shared --soname=lib$(1).so -o $$@ $$^
+endef
+
+ifneq ($(bin_PROGRAMS),)
+library-pass_HOOKS += force_builtin_library_hook
+
+.PHONY: force_builtin_library_hook
+force_builtin_library_hook:
+
+endif