openvela系统构建脚本解析
参考资料:<u>https://mi.feishu.cn/wiki/BA2IwuWKFimKQfkos6scggLLnrb</u>
openvela支持很多芯片、支持很多单板,编译openvela后得到elf格式的文件“nuttx”,转换为二进制文件“nuttx.bin”。
“nuttx.bin”运行时,可能需要一些资源,比如字库、图片,这些资源可以单独存储在Flash上。
所以,单板的Flash上可能这样存储数据:
不同产品的Flash规划不一样,所以本课程里只讲解nuttx.bin的生成过程。
下面这个图是本章节的精华:
<img src="C:\Users\MeiHao\AppData\Local\Temp\dsh_docx\pandoc\media/media/image140.png" style="width:5.71181in;height:4.27014in" alt="yuque_diagram (5)" />
配置与编译总体流程
openvela里各个子目录可以看到Makefile、Make.defs、Make.dep,这3类文件的作用为:
-
Makefile:里面定义了编译的规则
-
Make.defs:用于管理参与编译的源文件列表
-
Make.dep:编译时生成的依赖规则,不用看
配置和编译的关键脚本:build.sh
对于本课程使用的开发板,执行如下命令进行环境变量的设置、并选择工程:
cd ~/vela-opensource/vendor/allwinnertech/lichee/
source vela_env.sh
source envsetup.sh
lunch_nuttx
You're building on Linux
Lunch menu... pick a combo:
1. r528s3-evb4
2. r528s3-velaevb1
Which would you like?: 2
然后就可以执行“m”来编译,或者执行“m menuconfig”进行配置。执行“m”命令进行编译时,它会使用默认的配置文件。
“m”是一个脚本函数,代码在“vendor/allwinnertech/lichee/ tools/scripts/envsetup.sh”中:

要编译时,它会调用同文件的“mnuttx”函数,代码如下:

所以,无论是编译还是配置,都调用源码根目录下的build.sh,如下:
# 配置
./build.sh vendor/allwinnertech/boards/r528/r528s3-velaevb1/configs/nsh/ menuconfig
# 编译
./build.sh vendor/allwinnertech/boards/r528/r528s3-velaevb1/configs/nsh/ -e -Werror -j32
配置过程
“build.sh”的关键函数为“build_board”:

“build_board”函数功能如下:

无论是执行“m”命令进行编译,还是执行“m menuconfig”进入配置界面,都可以分为4个步骤:
-
使用默认配置生成.config
把“vendor/allwinnertech/boards/r528/r528s3-velaevb1/configs/nsh/defconfig”整理后得到“nuttx/.config”。所谓整理就是把include的文件展开,去掉重复项等。 -
进入nuttx目录执行“make”或“make menuconfig”命令
-
把nuttx/.config整理为nuttx/defconfig:比如排序、去掉重复项
-
把nuttx/defconfig复制为默认配置文件:
“vendor/allwinnertech/boards/r528/r528s3-velaevb1/configs/nsh/defconfig”
编译过程
理解nuttx编译过程的关键字为“递归”。我们把nuttx的Makefile分为多个级别,如下:

-
在“顶层目录”nuttx下执行“make”
-
会分别进入第2层目录执行“make”:比如进入apps目录、sched目录分别执行“make”
-
在apps目录下执行“make”,又会进入第3层目录执行make:比如进入“apps/builtin”、“apps/examples/hello”目录下执行“make”
分析时,要从顶层“nuttx/Makefile”开始,它包含了很多文件,如下:

把“nuttx/Makefile”里面包含的文件展开,把流程的关键部分保留下来,代码如下:
include $(TOPDIR)/Make.defs
-include $(TOPDIR)/.version
CONFIG_APPS_DIR = ../apps
APPDIR := \$(realpath \${shell if \[ -r \$(CONFIG_APPS_DIR)/Makefile \]; then echo "\$(CONFIG_APPS_DIR)"; fi})
include tools/Directories.mk
include tools/FlatLibs.mk
# **********************************
# 在nuttx/tools/FlatLibs.mk里设置
NUTTXLIBS += staging/libsched.a staging/libapps.a ...
# **********************************
BIN = nuttx$(EXEEXT)
all: $(BIN)
include/nuttx/config.h: $(TOPDIR)/.config tools/mkconfig$(HOSTEXEEXT)
$(Q) tools/mkconfig $(TOPDIR) > $@.tmp
$(Q) $(call TESTANDREPLACEFILE, $@.tmp, $@)
# Link arch/<arch-name>/src/<chip-name> to arch/<arch-name>/src/chip
# Link arch/<arch-name>/include/<chip-name> to include/arch/chip
# 在 nuttx/tools/Directories.mk
# CONTEXTDIRS = boards drivers fs $(APPDIR) $(ARCH_SRC) mm
CONTEXTDIRS_DEPS = $(patsubst %,%/.context,$(CONTEXTDIRS))
context: tools/incdir$(HOSTEXEEXT) include/nuttx/config.h include/nuttx/version.h .dirlinks $(CONTEXTDIRS_DEPS) | staging
staging:
$(Q) mkdir -p $@
%.context: include/nuttx/config.h .dirlinks
$(Q) $(MAKE) -C $(patsubst %.context,%,$@) TOPDIR="$(TOPDIR)" context
$(Q) touch $@
include tools/LibTargets.mk
# **********************************
# 来自 tools/LibTargets.mk
sched$(DELIM)libsched$(LIBEXT): pass2dep
$(Q) $(MAKE) -C sched libsched$(LIBEXT) EXTRAFLAGS="$(KDEFINE) $(EXTRAFLAGS)"
staging$(DELIM)libsched$(LIBEXT): sched$(DELIM)libsched$(LIBEXT)
$(Q) $(call INSTALL_LIB,$<,$@)
$(APPDIR)$(DELIM)libapps$(LIBEXT): pass2dep
$(Q) $(MAKE) -C $(APPDIR) EXTRAFLAGS="$(EXTRAFLAGS)"
staging$(DELIM)libapps$(LIBEXT): $(APPDIR)$(DELIM)libapps$(LIBEXT)
$(Q) $(call INSTALL_LIB,$<,$@)
endif
# **********************************
pass1: $(USERLIBS)
pass2: $(NUTTXLIBS)
$(BIN): pass1 pass2
$(Q) $(MAKE) -C $(ARCH_SRC) EXTRA_OBJS="$(EXTRA_OBJS)" LINKLIBS="$(LINKLIBS)" APPDIR="$(APPDIR)" EXTRAFLAGS="$(KDEFINE) $(EXTRAFLAGS)" $(BIN)
pass2dep: context tools/mkdeps$(HOSTEXEEXT) tools/cnvwindeps$(HOSTEXEEXT)
menuconfig:
$(Q) $(MAKE) clean_context
$(Q) $(MAKE) apps_preconfig
$(Q) \${KCONFIG_ENV} \${KCONFIG_MENUCONFIG}
执行“m”命令编译时,会执行“make -C nuttx”,就是进入nuttx目录执行它里面Makefile的第1个目标“all”,这个目标的依赖关系为:

编译Nuttx时,本质是进入nuttx目录执行“make all”,nuttx由staging目录下的各个“.a”文件组成:
$ ls staging/
libapps.a libarch.a libbinfmt.a libboards.a libc.a libcrypto.a
libdrivers.a libfs.a libmm.a libsched.a libxx.a
所以要先生成这些“.a”文件。
以libapps.a为例。在apps目录的源码里,它需要包含“include/nuttx/config.h”文件,使用里面的宏进行作为源码的条件编译开关。所以要生成libapps.a,要先生成config.h,这被称为“context”(上下文)。
从顶层nuttx/Makefile开始,会进入apps目录、sched目录等目录,逐个编译出对应的“.a”文件,然后再把它们连接起来得到nuttx。
在编译apps等目录时,又会先处理“context”等目标,然后才开始才编译代码。这些操作,都依赖于各个目录下的Makefile,比如apps/Makefile、sched/Makefile。
这样,控制流程就从顶层nuttx/Makefile进入了下一级的Makefile。
sched的编译过程
shced目录的编译比apps简单,先分析它。它的Makefile包含了其他文件:

它的依赖关系如下:

它就是把sched下面各个子目录的“Make.defs”里使用ASRCS指定的汇编文件、使用CSRCS指定的C文件,都编译为.o,然后打包为libsched.a。
APPS的编译过程
分析APPS目录的编译过程,有一个关键变量“CONFIGURED_APPS”:它指定了“要编译哪些APP”,在里面指定了要编译哪些子目录,比如:

Makefile
“apps/Makefile”包含了很多文件,如下:

把“apps/Makefile”展开后,保留重要部分,代码如下:
export APPDIR = \$(CURDIR)
include $(APPDIR)/Make.defs
# ****************************************
TOPDIR ?= $(APPDIR)/import
-include $(TOPDIR)/Make.defs
# \${TOPDIR}/tools/Config.mk
# 定义了SDIR_template
define SDIR_template
$(1)_$(2):
+$(Q) $(MAKE) -C $(1) $(2) APPDIR="$(APPDIR)"
endef
SYMTABSRC = symtab_apps.c
SYMTABOBJ = $(SYMTABSRC:.c=$(OBJEXT))
# Application Directories
# BUILDIRS : apps/的子目录下有Make.defs文件的话, 就会记录进BUILDIRS
BUILDIRS := $(dir $(wildcard $(APPDIR)/*/Make.defs))
BUILDIRS := $(filter-out $(APPDIR)/import/,$(BUILDIRS))
CONFIGDIRS := $(filter-out $(APPDIR)/builtin/,$(BUILDIRS))
CONFIGDIRS := $(filter-out $(dir $(wildcard $(APPDIR)/*/Kconfig)),$(CONFIGDIRS))
CLEANDIRS := $(dir $(wildcard $(APPDIR)/*/Makefile))
CONFIGURED_APPS :=
define Add_Application
include $(1)Make.defs
endef
# 包含 BUILDIRS 目录下的Make.defs文件
# 这些文件构造了 CONFIGURED_APPS
$(foreach BDIR, $(BUILDIRS), $(eval $(call Add_Application,$(BDIR))))
BINDIR ?= $(APPDIR)$(DELIM)bin
BIN ?= $(APPDIR)$(DELIM)libapps$(LIBEXT)
# Tools
MKKCONFIG ?= $(APPDIR)$(DELIM)tools$(DELIM)mkkconfig.sh
# Builtin Registration
BUILTIN_REGISTRY ?= $(APPDIR)$(DELIM)builtin$(DELIM)registry
DEPCONFIG ?= $(TOPDIR)$(DELIM).config
define REGISTER
$(Q) echo "Register: $1"
$(Q) echo "{ \\\$1\\, \$2, \$3, \$4 }," \> "\$(BUILTIN_REGISTRY)\$(DELIM)\$1.bdat"
$(Q) if \[ ! -z \$4 \]; then \\
echo "int \$4(int argc, char \*argv\[\]);" \> "\$(BUILTIN_REGISTRY)\$(DELIM)\$1.pdat"; \\
fi;
$(Q) touch "$(BUILTIN_REGISTRY)$(DELIM).updated"
endef
# ****************************************
include $(APPDIR)/tools/Wasm.mk
all: $(BIN)
.PHONY: import install dirlinks export .depdirs preconfig depend clean distclean
.PHONY: context postinstall clean_context context_all postinstall_all register register_all
.PRECIOUS: $(BIN)
$(foreach SDIR, $(CONFIGURED_APPS), $(eval $(call SDIR_template,$(SDIR),all)))
# 对于CONFIGURED_APPS里每个目录都构造一个规则
# 假设 CONFIGURED_APPS = /.../apps/examples/hello ...
# 有如下规则
/.../apps/examples/hello_all:
$(Q) $(MAKE) -C /.../apps/examples/hello all APPDIR="/.../apps"
$(foreach SDIR, $(CONFIGURED_APPS), $(eval $(call SDIR_template,$(SDIR),install)))
$(foreach SDIR, $(CONFIGURED_APPS), $(eval $(call SDIR_template,$(SDIR),postinstall)))
$(foreach SDIR, $(CONFIGURED_APPS), $(eval $(call SDIR_template,$(SDIR),context)))
$(foreach SDIR, $(CONFIGURED_APPS), $(eval $(call SDIR_template,$(SDIR),register)))
# 对于CONFIGURED_APPS里每个目录都构造一个规则
# 假设 CONFIGURED_APPS = /.../apps/examples/hello ...
# 有如下规则
/.../apps/examples/hello_register:
$(Q) $(MAKE) -C /.../apps/examples/hello register APPDIR="/.../apps"
$(foreach SDIR, $(CONFIGURED_APPS), $(eval $(call SDIR_template,$(SDIR),depend)))
$(foreach SDIR, $(CLEANDIRS), $(eval $(call SDIR_template,$(SDIR),clean)))
$(foreach SDIR, $(CLEANDIRS), $(eval $(call SDIR_template,$(SDIR),distclean)))
$(MKDEP): $(TOPDIR)/tools/mkdeps.c
$(HOSTCC) $(HOSTINCLUDES) $(HOSTCFLAGS) $< -o $@
$(INCDIR): $(TOPDIR)/tools/incdir.c
$(HOSTCC) $(HOSTINCLUDES) $(HOSTCFLAGS) $< -o $@
IMPORT_TOOLS = $(MKDEP) $(INCDIR)
context_wasm:
$(SYMTABSRC): $(foreach SDIR, $(CONFIGURED_APPS), $(SDIR)_all)
$(Q) $(MAKE) install
$(Q) $(APPDIR)$(DELIM)tools$(DELIM)mksymtab.sh $(BINDIR) $(SYMTABEXT) >$@.tmp
$(Q) $(call TESTANDREPLACEFILE, $@.tmp, $@)
$(SYMTABOBJ): %$(OBJEXT): %.c
$(call COMPILE, $<, $@, -Onolink)
$(BIN): $(SYMTABOBJ)
$(call ARLOCK, $(call CONVERT_PATH,$(BIN)), $^)
$(call LINK_WASM)
dirlinks:
$(Q) $(MAKE) -C platform dirlinks
context_all: $(foreach SDIR, $(CONFIGURED_APPS), $(SDIR)_context)
register_all: $(foreach SDIR, $(CONFIGURED_APPS), $(SDIR)_register)
postinstall_all: $(foreach SDIR, $(CONFIGURED_APPS), $(SDIR)_postinstall)
staging:
$(Q) mkdir -p $@
context: | staging
$(Q) $(MAKE) context_all
$(Q) $(MAKE) register_all
$(Q) $(MAKE) context_wasm
依赖关系如下图:

进入下一级目录构建context
在顶层目录nuttx下执行make去编译libapps.a、libsched.a之前,都会先构建“context”。它会进入apps、sched目录使用它们的Makefile构建context:
make -C apps context
以“apps/Makefile”为例,它的context规则如下:
context: | staging
$(Q) $(MAKE) context_all
$(Q) $(MAKE) register_all
$(Q) $(MAKE) context_wasm
上述规则会再次进入“CONFIGURED_APPS”指定的下一级目录执行“make context”、“make register”等。
注意:apps目录下各个子目录的Makedefs里,定义了“CONFIGURED_APPS”变量,它的值大概是这样:
CONFIGURED_APPS = /.../apps/builtin /.../apps/examples/hello ...
所以,会使用类似下面命令进入下一级:
make -C /.../apps/builtin register
make -C /.../apps/examples/hello register
进入下一级目录构建.o
在顶层目录nuttx下执行make去编译libapps.a、libsched.a时,执行的是类似下面的命令(简化了):
make -C apps all
make -C sched all
就是:顶层Makefile进入下一级的目录,使用它们的Makefile去构建all目标。
当构建apps/Makefile里的all目标时,它确定了“CONFIGURED_APPS”后,又分别进入这个变量表示的下一级目录,使用它们的Makefile构建各自的all目标,比如:
make -C apps/builtin all
make -C apps/example/hello all
app/builtin的编译过程
“app/builtin/Makefile”是底层的Makefile,要真正做事情了。
它包含了很多文件,如下:

它的依赖关系如下:

展开的Makefile如下:
include $(APPDIR)/Make.defs
define AROBJSRULES
$(1) : $(2)
@ cp $(2) $(1)
endef
# Source and object files
CSRCS = builtin_list.c exec_builtin.c
# Registry entry lists
PDATLIST = $(strip $(call RWILDCARD, registry, *.pdat))
BDATLIST = $(strip $(call RWILDCARD, registry, *.bdat))
ifeq ($(CONFIG_WINDOWS_NATIVE),y)
PDATLIST := $(subst /,\$(PDATLIST))
BDATLIST := $(subst /,\$(BDATLIST))
endif
builtin_list.c: builtin_list.h builtin_proto.h
echo 100ask create $@
builtin_list.h: registry$(DELIM).updated
echo 100ask create $@
ifeq ($(BDATLIST),)
$(call DELFILE, builtin_list.h)
$(Q) touch builtin_list.h
else
$(shell echo '' > builtin_list.h)
$(call SPLITVARIABLE,BDA,$(BDATLIST),50) \
$(foreach BATCH, $(BDA_TOTAL), \
$(shell $(call CONFILE, builtin_list.h, $(BDA_$(BATCH)))) \
)
endif
builtin_proto.h: registry$(DELIM).updated
echo 100ask create $@
ifeq ($(PDATLIST),)
$(call DELFILE, builtin_proto.h)
$(Q) touch builtin_proto.h
else
$(shell echo '' > builtin_proto.h)
$(call SPLITVARIABLE,PDA,$(PDATLIST),50) \
$(foreach BATCH, $(PDA_TOTAL), \
$(shell $(call CONFILE, builtin_proto.h, $(PDA_$(BATCH)))) \
)
endif
include $(APPDIR)/Application.mk
PROGNAME := $(subst ",,$(PROGNAME))
# Add the static application library to the linked libraries.
LDLIBS += $(call CONVERT_PATH,$(BIN))
PREFIX ?=
# Object files
RASRCS = $(filter %.s,$(ASRCS))
CASRCS = $(filter %.S,$(ASRCS))
RAOBJS = $(RASRCS:%=$(PREFIX)%$(SUFFIX)$(OBJEXT))
CAOBJS = $(CASRCS:%=$(PREFIX)%$(SUFFIX)$(OBJEXT))
COBJS = $(CSRCS:%=$(PREFIX)%$(SUFFIX)$(OBJEXT))
CXXOBJS = $(CXXSRCS:%=$(PREFIX)%$(SUFFIX)$(OBJEXT))
RUSTOBJS = $(RUSTSRCS:%=$(PREFIX)%$(SUFFIX)$(OBJEXT))
ZIGOBJS = $(ZIGSRCS:%=$(PREFIX)%$(SUFFIX)$(OBJEXT))
DOBJS = $(DSRCS:%=$(PREFIX)%$(SUFFIX)$(OBJEXT))
SWIFTOBJS = $(SWIFTSRCS:%=$(PREFIX)%$(SUFFIX)$(OBJEXT))
AIDLOBJS = $(patsubst %$(AIDLEXT),%$(CXXEXT),$(AIDLSRCS))
MAINCXXSRCS = $(filter %$(CXXEXT),$(MAINSRC))
MAINCSRCS = $(filter %.c,$(MAINSRC))
MAINRUSTSRCS = $(filter %$(RUSTEXT),$(MAINSRC))
MAINZIGSRCS = $(filter %$(ZIGEXT),$(MAINSRC))
MAINDSRCS = $(filter %$(DEXT),$(MAINSRC))
MAINSWIFTSRCS = $(filter %$(SWIFTEXT),$(MAINSRC))
MAINCXXOBJ = $(MAINCXXSRCS:%=$(PREFIX)%$(SUFFIX)$(OBJEXT))
MAINCOBJ = $(MAINCSRCS:%=$(PREFIX)%$(SUFFIX)$(OBJEXT))
MAINRUSTOBJ = $(MAINRUSTSRCS:%=$(PREFIX)%$(SUFFIX)$(OBJEXT))
MAINZIGOBJ = $(MAINZIGSRCS:%=$(PREFIX)%$(SUFFIX)$(OBJEXT))
MAINDOBJ = $(MAINDSRCS:%=$(PREFIX)%$(SUFFIX)$(OBJEXT))
MAINSWIFTOBJ = $(MAINSWIFTSRCS:%=$(PREFIX)%$(SUFFIX)$(OBJEXT))
SRCS = $(ASRCS) $(CSRCS) $(CXXSRCS) $(MAINSRC)
OBJS = $(RAOBJS) $(CAOBJS) $(COBJS) $(CXXOBJS) $(RUSTOBJS) $(ZIGOBJS) $(DOBJS) $(SWIFTOBJS) $(EXTOBJS)
ifneq ($(BUILD_MODULE),y)
OBJS += $(MAINCOBJ) $(MAINCXXOBJ) $(MAINRUSTOBJ) $(MAINZIGOBJ) $(MAINDOBJ) $(MAINSWIFTOBJ)
endif
all:: $(PREFIX).built
@:
$(RAOBJS): $(PREFIX)%.s$(SUFFIX)$(OBJEXT): %.s
$(if $(and $(CONFIG_MODULES),$(MODAELFFLAGS)), \
$(call ELFASSEMBLE, $<, $@), $(call ASSEMBLE, $<, $@))
$(CAOBJS): $(PREFIX)%.S$(SUFFIX)$(OBJEXT): %.S
$(if $(and $(CONFIG_MODULES),$(MODAELFFLAGS)), \
$(call ELFASSEMBLE, $<, $@), $(call ASSEMBLE, $<, $@))
$(COBJS): $(PREFIX)%.c$(SUFFIX)$(OBJEXT): %.c
$(if $(and $(CONFIG_MODULES),$(MODCFLAGS)), \
$(call ELFCOMPILE, $<, $@), $(call COMPILE, $<, $@))
$(CXXOBJS): $(PREFIX)%$(CXXEXT)$(SUFFIX)$(OBJEXT): %$(CXXEXT)
$(if $(and $(CONFIG_MODULES),$(MODCXXFLAGS)), \
$(call ELFCOMPILEXX, $<, $@), $(call COMPILEXX, $<, $@))
$(RUSTOBJS): $(PREFIX)%$(RUSTEXT)$(SUFFIX)$(OBJEXT): %$(RUSTEXT)
$(if $(and $(CONFIG_MODULES),$(CELFFLAGS)), \
$(call ELFCOMPILERUST, $<, $@), $(call COMPILERUST, $<, $@))
$(ZIGOBJS): $(PREFIX)%$(ZIGEXT)$(SUFFIX)$(OBJEXT): %$(ZIGEXT)
$(if $(and $(CONFIG_MODULES), $(CELFFLAGS)), \
$(call ELFCOMPILEZIG, $<, $@), $(call COMPILEZIG, $<, $@))
$(DOBJS): $(PREFIX)%$(DEXT)$(SUFFIX)$(OBJEXT): %$(DEXT)
$(if $(and $(CONFIG_MODULES), $(CELFFLAGS)), \
$(call ELFCOMPILED, $<, $@), $(call COMPILED, $<, $@))
$(SWIFTOBJS): $(PREFIX)%$(SWIFTEXT)$(SUFFIX)$(OBJEXT): %$(SWIFTEXT)
$(if $(and $(CONFIG_MODULES), $(CELFFLAGS)), \
$(call ELFCOMPILESWIFT, $<, $@), $(call COMPILESWIFT, $<, $@))
$(AIDLOBJS): %$(CXXEXT): %$(AIDLEXT)
$(call COMPILEAIDL, $<)
AROBJS :=
ifneq ($(OBJS),)
SORTOBJS := $(sort $(OBJS))
$(eval $(call SPLITVARIABLE,OBJS_SPILT,$(SORTOBJS),100))
$(foreach BATCH, $(OBJS_SPILT_TOTAL), \
$(foreach obj, $(OBJS_SPILT_$(BATCH)), \
$(eval substitute := $(patsubst %$(OBJEXT),%_$(BATCH)$(OBJEXT),$(obj))) \
$(eval AROBJS += $(substitute)) \
$(eval $(call AROBJSRULES, $(substitute),$(obj))) \
) \
)
endif
$(PREFIX).built: $(AROBJS)
echo 100ask builtin: AROBJS = $(AROBJS)
$(call SPLITVARIABLE,ALL_OBJS,$(AROBJS),100)
$(foreach BATCH, $(ALL_OBJS_TOTAL), \
$(if $(strip $(ALL_OBJS_$(BATCH))), \
$(shell $(call ARLOCK, $(call CONVERT_PATH,$(BIN)), $(ALL_OBJS_$(BATCH)))) \
) \
)
$(Q) touch $@
ifeq ($(BUILD_MODULE),y)
$(MAINCXXOBJ): $(PREFIX)%$(CXXEXT)$(SUFFIX)$(OBJEXT): %$(CXXEXT)
$(if $(and $(CONFIG_MODULES),$(MODCXXFLAGS)), \
$(call ELFCOMPILEXX, $<, $@), $(call COMPILEXX, $<, $@))
$(MAINCOBJ): $(PREFIX)%.c$(SUFFIX)$(OBJEXT): %.c
$(if $(and $(CONFIG_MODULES),$(MODCFLAGS)), \
$(call ELFCOMPILE, $<, $@), $(call COMPILE, $<, $@))
$(MAINZIGOBJ): $(PREFIX)%$(ZIGEXT)$(SUFFIX)$(OBJEXT): %$(ZIGEXT)
$(if $(and $(CONFIG_MODULES),$(CELFFLAGS)), \
$(call ELFCOMPILEZIG, $<, $@), $(call COMPILEZIG, $<, $@))
$(MAINDOBJ): $(PREFIX)%$(DEXT)$(SUFFIX)$(OBJEXT): %$(DEXT)
$(if $(and $(CONFIG_MODULES),$(CELFFLAGS)), \
$(call ELFCOMPILED, $<, $@), $(call COMPILED, $<, $@))
$(MAINSWIFTOBJ): $(PREFIX)%$(SWIFTEXT)$(SUFFIX)$(OBJEXT): %$(SWIFTEXT)
$(if $(and $(CONFIG_MODULES),$(CELFFLAGS)), \
$(call ELFCOMPILESWIFT, $<, $@), $(call COMPILESWIFT, $<, $@))
$(PROGLIST): $(MAINCOBJ) $(MAINCXXOBJ) $(MAINRUSTOBJ) $(MAINZIGOBJ) $(MAINDOBJ) $(MAINSWIFTOBJ)
$(Q) mkdir -p $(BINDIR)
$(call ELFLD, $(PROGOBJ_$@), $(call CONVERT_PATH,$@))
$(Q) chmod +x $@
ifneq ($(CONFIG_DEBUG_SYMBOLS),y)
$(Q) $(MODULESTRIP) $@
endif
install:: $(PROGLIST)
@:
-include $(PREFIX)Make.dep
# Include Wasm specific definitions
include $(APPDIR)/tools/Wasm.mk
app/examples/hello的编译过程
“app/examples/hello”是底层的Makefile,要真正做事情了。
它包含了很多文件,如下:

它的依赖关系如下:

展开的Makefile为:
include $(APPDIR)/Make.defs
# include $(APPDIR)/Make.defs
define REGISTER
$(Q) echo "Register: $1"
$(Q) echo "{ \\\$1\\, \$2, \$3, \$4 }," \> "\$(BUILTIN_REGISTRY)\$(DELIM)\$1.bdat"
$(Q) if \[ ! -z \$4 \]; then \\
echo "int \$4(int argc, char \*argv\[\]);" \> "\$(BUILTIN_REGISTRY)\$(DELIM)\$1.pdat"; \\
fi;
$(Q) touch "$(BUILTIN_REGISTRY)$(DELIM).updated"
endef
# include $(APPDIR)/Make.defs
define AROBJSRULES
$(1) : $(2)
@ cp $(2) $(1)
endef
# Hello, World! built-in application info
PROGNAME = $(CONFIG_EXAMPLES_HELLO_PROGNAME)
PRIORITY = $(CONFIG_EXAMPLES_HELLO_PRIORITY)
STACKSIZE = $(CONFIG_EXAMPLES_HELLO_STACKSIZE)
MODULE = $(CONFIG_EXAMPLES_HELLO)
# Hello, World! Example
MAINSRC = hello_main.c
include $(APPDIR)/Application.mk
############################################################################
# apps/Application.mk
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership. The
# ASF licenses this file to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance with the
# License. You may obtain a copy of the License at
#
# http:#www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
############################################################################
# If this is an executable program (with MAINSRC), we must build it as a
# loadable module for the KERNEL build (always) or if the tristate module
# has the value "m"
ifneq ($(MAINSRC),)
ifeq ($(DYNLIB),y)
BUILD_MODULE = y
MODAELFFLAGS = $(CMODULELFFLAGS)
MODCFLAGS = $(CMODULEFLAGS)
MODCXXFLAGS = $(CXXMODULEFLAGS)
MODLDFLAGS = $(LDMODULEFLAGS)
else ifneq (\$(or \$(filter y,\$(CONFIG_BUILD_KERNEL)), \$(filter m,\$(MODULE))),)
BUILD_MODULE = y
MODAELFFLAGS = $(AELFFLAGS)
MODCFLAGS = $(CELFFLAGS)
MODCXXFLAGS = $(CXXELFFLAGS)
MODLDFLAGS = $(LDELFFLAGS)
endif
endif
# The GNU make CURDIR will always be a POSIX-like path with forward slashes
# as path segment separators. If we know that this is a native build, then
# we need to fix up the path so the DELIM will match the actual delimiter.
ifeq ($(CONFIG_WINDOWS_NATIVE),y)
CWD = \$(strip \${shell echo %CD% \| cut -d: -f2})
else
CWD = $(CURDIR)
endif
SUFFIX ?= $(subst $(DELIM),.,$(CWD))
PROGNAME := $(subst ",,$(PROGNAME))
# Add the static application library to the linked libraries.
LDLIBS += $(call CONVERT_PATH,$(BIN))
# When building a module, link with the compiler runtime.
# This should be linked after libapps. Consider that mbedtls in libapps
# uses __udivdi3.
ifeq ($(BUILD_MODULE),y)
# Revisit: This only works for gcc and clang.
# Do other compilers have similar?
COMPILER_RT_LIB = $(shell $(CC) $(ARCHCPUFLAGS) --print-libgcc-file-name)
ifeq ($(wildcard $(COMPILER_RT_LIB)),)
# if "--print-libgcc-file-name" unable to find the correct libgcc PATH
# then go ahead and try "--print-file-name"
COMPILER_RT_LIB := $(wildcard $(shell $(CC) $(ARCHCPUFLAGS) --print-file-name $(notdir $(COMPILER_RT_LIB))))
endif
LDLIBS += $(COMPILER_RT_LIB)
endif
# Apps compilation can achieve out-of-tree intermediate products
# by specifying "PREFIX" to a directory in its own Makefile.
# Default value is NULL,
# Make sure the out-of-tree directory exists and ends with $(DELIM) when setting it.
PREFIX ?=
# Object files
RASRCS = $(filter %.s,$(ASRCS))
CASRCS = $(filter %.S,$(ASRCS))
RAOBJS = $(RASRCS:%=$(PREFIX)%$(SUFFIX)$(OBJEXT))
CAOBJS = $(CASRCS:%=$(PREFIX)%$(SUFFIX)$(OBJEXT))
COBJS = $(CSRCS:%=$(PREFIX)%$(SUFFIX)$(OBJEXT))
CXXOBJS = $(CXXSRCS:%=$(PREFIX)%$(SUFFIX)$(OBJEXT))
RUSTOBJS = $(RUSTSRCS:%=$(PREFIX)%$(SUFFIX)$(OBJEXT))
ZIGOBJS = $(ZIGSRCS:%=$(PREFIX)%$(SUFFIX)$(OBJEXT))
DOBJS = $(DSRCS:%=$(PREFIX)%$(SUFFIX)$(OBJEXT))
SWIFTOBJS = $(SWIFTSRCS:%=$(PREFIX)%$(SUFFIX)$(OBJEXT))
AIDLOBJS = $(patsubst %$(AIDLEXT),%$(CXXEXT),$(AIDLSRCS))
MAINCXXSRCS = $(filter %$(CXXEXT),$(MAINSRC))
MAINCSRCS = $(filter %.c,$(MAINSRC))
MAINRUSTSRCS = $(filter %$(RUSTEXT),$(MAINSRC))
MAINZIGSRCS = $(filter %$(ZIGEXT),$(MAINSRC))
MAINDSRCS = $(filter %$(DEXT),$(MAINSRC))
MAINSWIFTSRCS = $(filter %$(SWIFTEXT),$(MAINSRC))
MAINCXXOBJ = $(MAINCXXSRCS:%=$(PREFIX)%$(SUFFIX)$(OBJEXT))
MAINCOBJ = $(MAINCSRCS:%=$(PREFIX)%$(SUFFIX)$(OBJEXT))
MAINRUSTOBJ = $(MAINRUSTSRCS:%=$(PREFIX)%$(SUFFIX)$(OBJEXT))
MAINZIGOBJ = $(MAINZIGSRCS:%=$(PREFIX)%$(SUFFIX)$(OBJEXT))
MAINDOBJ = $(MAINDSRCS:%=$(PREFIX)%$(SUFFIX)$(OBJEXT))
MAINSWIFTOBJ = $(MAINSWIFTSRCS:%=$(PREFIX)%$(SUFFIX)$(OBJEXT))
SRCS = $(ASRCS) $(CSRCS) $(CXXSRCS) $(MAINSRC)
OBJS = $(RAOBJS) $(CAOBJS) $(COBJS) $(CXXOBJS) $(RUSTOBJS) $(ZIGOBJS) $(DOBJS) $(SWIFTOBJS) $(EXTOBJS)
ifneq ($(BUILD_MODULE),y)
OBJS += $(MAINCOBJ) $(MAINCXXOBJ) $(MAINRUSTOBJ) $(MAINZIGOBJ) $(MAINDOBJ) $(MAINSWIFTOBJ)
endif
ifneq ($(strip $(PROGNAME)),)
PROGOBJ := $(MAINCOBJ) $(MAINCXXOBJ) $(MAINRUSTOBJ) $(MAINZIGOBJ) $(MAINDOBJ) $(MAINSWIFTOBJ)
PROGLIST := $(addprefix $(BINDIR)$(DELIM),$(PROGNAME))
REGLIST := $(addprefix $(BUILTIN_REGISTRY)$(DELIM),$(addsuffix .bdat,$(PROGNAME)))
NLIST := $(shell seq 1 $(words $(PROGNAME)))
$(foreach i, $(NLIST), \
$(eval PROGNAME_$(word $i,$(PROGOBJ)) := $(word $i,$(PROGNAME))) \
$(eval PROGOBJ_$(word $i,$(PROGLIST)) := $(word $i,$(PROGOBJ))) \
$(eval PRIORITY_$(word $i,$(REGLIST)) := \
$(if $(word $i,$(PRIORITY)),$(word $i,$(PRIORITY)),$(lastword $(PRIORITY)))) \
$(eval STACKSIZE_$(word $i,$(REGLIST)) := \
$(if $(word $i,$(STACKSIZE)),$(word $i,$(STACKSIZE)),$(lastword $(STACKSIZE)))) \
$(eval UID_$(word $i,$(REGLIST)) := \
$(if $(word $i,$(UID)),$(word $i,$(UID)),$(lastword $(UID)))) \
$(eval GID_$(word $i,$(REGLIST)) := \
$(if $(word $i,$(GID)),$(word $i,$(GID)),$(lastword $(GID)))) \
$(eval MODE_$(word $i,$(REGLIST)) := \
$(if $(word $i,$(MODE)),$(word $i,$(MODE)),$(lastword $(MODE)))) \
)
endif
# Condition flags
DO_REGISTRATION ?= y
ifeq ($(PROGNAME),)
DO_REGISTRATION = n
endif
ifeq ($(WASM_BUILD),y)
DO_REGISTRATION = n
endif
ifeq ($(DYNLIB),y)
DO_REGISTRATION = n
endif
# Compile flags, notice the default flags only suitable for flat build
ZIGELFFLAGS ?= $(ZIGFLAGS)
RUSTELFFLAGS ?= $(RUSTFLAGS)
DELFFLAGS ?= $(DFLAGS)
SWIFTELFFLAGS ?= $(SWIFTFLAGS)
DEPPATH += --dep-path .
DEPPATH += --obj-path .
VPATH += :.
# Targets follow
all:: $(PREFIX).built
@:
.PHONY: clean depend distclean
.PRECIOUS: $(BIN)
define ELFASSEMBLE
$(ECHO_BEGIN)"AS: $1 "
$(Q) $(MODULECC) -c $(MODAELFFLAGS) $($(strip $1)_AELFFLAGS) $1 -o $2
$(ECHO_END)
endef
define ELFCOMPILE
$(ECHO_BEGIN)"CC: $1 "
$(Q) $(MODULECC) -c $(MODCFLAGS) $($(strip $1)_CELFFLAGS) $1 -o $2
$(ECHO_END)
endef
define ELFCOMPILEXX
$(ECHO_BEGIN)"CXX: $1 "
$(Q) $(CXX) -c $(MODCXXFLAGS) $($(strip $1)_CXXELFFLAGS) $1 -o $2
$(ECHO_END)
endef
define ELFCOMPILERUST
$(ECHO_BEGIN)"RUSTC: $1 "
$(Q) $(RUSTC) --emit obj $(RUSTELFFLAGS) $($(strip $1)_RUSTELFFLAGS) $1 -o $2
$(ECHO_END)
endef
# Remove target suffix here since zig compiler add .o automatically
define ELFCOMPILEZIG
$(ECHO_BEGIN)"ZIG: $1 "
$(Q) $(ZIG) build-obj $(ZIGELFFLAGS) $($(strip $1)_ZIGELFFLAGS) --name $(basename $2) $1
$(ECHO_END)
endef
define ELFCOMPILED
$(ECHO_BEGIN)"DC: $1 "
$(Q) $(DC) -c $(DELFFLAGS) $($(strip $1)_DELFFLAGS) $1 -of $2
$(ECHO_END)
endef
define ELFCOMPILESWIFT
$(ECHO_BEGIN)"SWIFTC: $1 "
$(Q) $(SWIFTC) -c $(SWIFTELFFLAGS) $($(strip $1)_SWIFTELFFLAGS) $1 -o $2
$(ECHO_END)
endef
define ELFLD
$(ECHO_BEGIN)"LD: $2 "
$(Q) $(MODULELD) $(MODLDFLAGS) $(LDMAP) $(LDLIBPATH) $(ARCHCRT0OBJ) $1 $(LDSTARTGROUP) $(LDLIBS) $(LDENDGROUP) -o $2
$(ECHO_END)
endef
# rename "main()" in $1 to "xxx_main()" and save to $2
define RENAMEMAIN
$(ECHO_BEGIN)"Rename main() in $1 and save to $2"
$(Q) \${shell cat \$1 \| sed -e "s/fn\[ \]\\main/fn \$(addsuffix \_main,\$(PROGNAME\_\$@))/" \> \$2}
$(ECHO_END)
endef
define COMPILEAIDL
$(ECHO_BEGIN)"AIDL: $1 "
$(Q) $(AIDL) $(AIDLFLAGS) $($(strip $1)_AIDLFLAGS) $1
$(ECHO_END)
endef
define DELAIDLOUT
$(ECHO_BEGIN)"DELAIDLOUT: $1 "
$(Q) $(AIDL) $(AIDLFLAGS) $($(strip $1)_AIDLFLAGS) $1 --delete
$(ECHO_END)
endef
$(RAOBJS): $(PREFIX)%.s$(SUFFIX)$(OBJEXT): %.s
$(if $(and $(CONFIG_MODULES),$(MODAELFFLAGS)), \
$(call ELFASSEMBLE, $<, $@), $(call ASSEMBLE, $<, $@))
$(CAOBJS): $(PREFIX)%.S$(SUFFIX)$(OBJEXT): %.S
$(if $(and $(CONFIG_MODULES),$(MODAELFFLAGS)), \
$(call ELFASSEMBLE, $<, $@), $(call ASSEMBLE, $<, $@))
$(COBJS): $(PREFIX)%.c$(SUFFIX)$(OBJEXT): %.c
$(if $(and $(CONFIG_MODULES),$(MODCFLAGS)), \
$(call ELFCOMPILE, $<, $@), $(call COMPILE, $<, $@))
$(CXXOBJS): $(PREFIX)%$(CXXEXT)$(SUFFIX)$(OBJEXT): %$(CXXEXT)
$(if $(and $(CONFIG_MODULES),$(MODCXXFLAGS)), \
$(call ELFCOMPILEXX, $<, $@), $(call COMPILEXX, $<, $@))
$(RUSTOBJS): $(PREFIX)%$(RUSTEXT)$(SUFFIX)$(OBJEXT): %$(RUSTEXT)
$(if $(and $(CONFIG_MODULES),$(CELFFLAGS)), \
$(call ELFCOMPILERUST, $<, $@), $(call COMPILERUST, $<, $@))
$(ZIGOBJS): $(PREFIX)%$(ZIGEXT)$(SUFFIX)$(OBJEXT): %$(ZIGEXT)
$(if $(and $(CONFIG_MODULES), $(CELFFLAGS)), \
$(call ELFCOMPILEZIG, $<, $@), $(call COMPILEZIG, $<, $@))
$(DOBJS): $(PREFIX)%$(DEXT)$(SUFFIX)$(OBJEXT): %$(DEXT)
$(if $(and $(CONFIG_MODULES), $(CELFFLAGS)), \
$(call ELFCOMPILED, $<, $@), $(call COMPILED, $<, $@))
$(SWIFTOBJS): $(PREFIX)%$(SWIFTEXT)$(SUFFIX)$(OBJEXT): %$(SWIFTEXT)
$(if $(and $(CONFIG_MODULES), $(CELFFLAGS)), \
$(call ELFCOMPILESWIFT, $<, $@), $(call COMPILESWIFT, $<, $@))
$(AIDLOBJS): %$(CXXEXT): %$(AIDLEXT)
$(call COMPILEAIDL, $<)
AROBJS :=
ifneq ($(OBJS),)
SORTOBJS := $(sort $(OBJS))
$(eval $(call SPLITVARIABLE,OBJS_SPILT,$(SORTOBJS),100))
$(foreach BATCH, $(OBJS_SPILT_TOTAL), \
$(foreach obj, $(OBJS_SPILT_$(BATCH)), \
$(eval substitute := $(patsubst %$(OBJEXT),%_$(BATCH)$(OBJEXT),$(obj))) \
$(eval AROBJS += $(substitute)) \
$(eval $(call AROBJSRULES, $(substitute),$(obj))) \
) \
)
endif
$(PREFIX).built: $(AROBJS)
echo 100ask builtin: AROBJS = $(AROBJS)
$(call SPLITVARIABLE,ALL_OBJS,$(AROBJS),100)
$(foreach BATCH, $(ALL_OBJS_TOTAL), \
$(if $(strip $(ALL_OBJS_$(BATCH))), \
$(shell $(call ARLOCK, $(call CONVERT_PATH,$(BIN)), $(ALL_OBJS_$(BATCH)))) \
) \
)
$(Q) touch $@
ifeq ($(BUILD_MODULE),y)
$(MAINCXXOBJ): $(PREFIX)%$(CXXEXT)$(SUFFIX)$(OBJEXT): %$(CXXEXT)
$(if $(and $(CONFIG_MODULES),$(MODCXXFLAGS)), \
$(call ELFCOMPILEXX, $<, $@), $(call COMPILEXX, $<, $@))
$(MAINCOBJ): $(PREFIX)%.c$(SUFFIX)$(OBJEXT): %.c
$(if $(and $(CONFIG_MODULES),$(MODCFLAGS)), \
$(call ELFCOMPILE, $<, $@), $(call COMPILE, $<, $@))
$(MAINZIGOBJ): $(PREFIX)%$(ZIGEXT)$(SUFFIX)$(OBJEXT): %$(ZIGEXT)
$(if $(and $(CONFIG_MODULES),$(CELFFLAGS)), \
$(call ELFCOMPILEZIG, $<, $@), $(call COMPILEZIG, $<, $@))
$(MAINDOBJ): $(PREFIX)%$(DEXT)$(SUFFIX)$(OBJEXT): %$(DEXT)
$(if $(and $(CONFIG_MODULES),$(CELFFLAGS)), \
$(call ELFCOMPILED, $<, $@), $(call COMPILED, $<, $@))
$(MAINSWIFTOBJ): $(PREFIX)%$(SWIFTEXT)$(SUFFIX)$(OBJEXT): %$(SWIFTEXT)
$(if $(and $(CONFIG_MODULES),$(CELFFLAGS)), \
$(call ELFCOMPILESWIFT, $<, $@), $(call COMPILESWIFT, $<, $@))
$(PROGLIST): $(MAINCOBJ) $(MAINCXXOBJ) $(MAINRUSTOBJ) $(MAINZIGOBJ) $(MAINDOBJ) $(MAINSWIFTOBJ)
$(Q) mkdir -p $(BINDIR)
$(call ELFLD, $(PROGOBJ_$@), $(call CONVERT_PATH,$@))
$(Q) chmod +x $@
ifneq ($(CONFIG_DEBUG_SYMBOLS),y)
$(Q) $(MODULESTRIP) $@
endif
install:: $(PROGLIST)
@:
else
$(MAINCXXOBJ): $(PREFIX)%$(CXXEXT)$(SUFFIX)$(OBJEXT): %$(CXXEXT)
$(eval \$\<\_CXXFLAGS += \${shell \$(DEFINE) "\$(CXX)" main=\$(addsuffix \_main,\$(PROGNAME\_\$@))})
$(eval \$\<\_CXXELFFLAGS += \${shell \$(DEFINE) "\$(CXX)" main=\$(addsuffix \_main,\$(PROGNAME\_\$@))})
$(if $(and $(CONFIG_MODULES),$(MODCXXFLAGS)), \
$(call ELFCOMPILEXX, $<, $@), $(call COMPILEXX, $<, $@))
$(MAINCOBJ): $(PREFIX)%.c$(SUFFIX)$(OBJEXT): %.c
$(eval \$\<\_CFLAGS += \${DEFINE_PREFIX}main=\$(addsuffix \_main,\$(PROGNAME\_\$@)))
$(eval \$\<\_CELFFLAGS += \${DEFINE_PREFIX}main=\$(addsuffix \_main,\$(PROGNAME\_\$@)))
$(if $(and $(CONFIG_MODULES),$(MODCFLAGS)), \
$(call ELFCOMPILE, $<, $@), $(call COMPILE, $<, $@))
$(MAINRUSTOBJ): $(PREFIX)%$(RUSTEXT)$(SUFFIX)$(OBJEXT): %$(RUSTEXT)
$(if $(and $(CONFIG_MODULES),$(CELFFLAGS)), \
$(call ELFCOMPILERUST, $<, $@), $(call COMPILERUST, $<, $@))
$(MAINZIGOBJ): $(PREFIX)%$(ZIGEXT)$(SUFFIX)$(OBJEXT): %$(ZIGEXT)
$(Q) $(call RENAMEMAIN, $<, $(basename $<)_tmp.zig)
$(if $(and $(CONFIG_MODULES),$(CELFFLAGS)), \
$(call ELFCOMPILEZIG, $(basename $<)_tmp.zig, $@), $(call COMPILEZIG, $(basename $<)_tmp.zig, $@))
$(Q) rm -f $(basename $<)_tmp.zig
$(MAINDOBJ): $(PREFIX)%$(DEXT)$(SUFFIX)$(OBJEXT): %$(DEXT)
$(if $(and $(CONFIG_MODULES),$(CELFFLAGS)), \
$(call ELFCOMPILED, $<, $@), $(call COMPILED, $<, $@))
$(MAINSWIFTOBJ): $(PREFIX)%$(SWIFTEXT)$(SUFFIX)$(OBJEXT): %$(SWIFTEXT)
$(if $(and $(CONFIG_MODULES),$(CELFFLAGS)), \
$(call ELFCOMPILESWIFT, $<, $@), $(call COMPILESWIFT, $<, $@))
install::
@:
endif # BUILD_MODULE
postinstall::
@:
context:: $(AIDLOBJS)
@:
ifeq ($(DO_REGISTRATION),y)
$(REGLIST): $(DEPCONFIG) Makefile
echo 100ask register REGLIST = $(REGLIST)
$(eval PROGNAME_$@ := $(basename $(notdir $@)))
ifeq ($(CONFIG_SCHED_USER_IDENTITY),y)
$(call REGISTER,$(PROGNAME_$@),$(PRIORITY_$@),$(STACKSIZE_$@),$(if $(BUILD_MODULE),,$(PROGNAME_$@)_main),$(UID_$@),$(GID_$@),$(MODE_$@))
else
$(call REGISTER,$(PROGNAME_$@),$(PRIORITY_$@),$(STACKSIZE_$@),$(if $(BUILD_MODULE),,$(PROGNAME_$@)_main))
endif
register:: $(REGLIST)
@:
else
register::
@:
endif
$(PREFIX).depend: Makefile $(wildcard $(foreach SRC, $(SRCS), $(addsuffix /$(SRC), $(subst :, ,$(VPATH))))) $(DEPCONFIG)
$(shell echo "# Gen Make.dep automatically" >$(PREFIX)Make.dep)
$(call SPLITVARIABLE,ALL_DEP_OBJS,$^,100)
$(foreach BATCH, $(ALL_DEP_OBJS_TOTAL), \
$(shell $(MKDEP) $(DEPPATH) --obj-suffix .c$(SUFFIX)$(OBJEXT) "$(CC)" -- $(CFLAGS) -- $(filter %.c,$(ALL_DEP_OBJS_$(BATCH))) >>$(PREFIX)Make.dep) \
$(shell $(MKDEP) $(DEPPATH) --obj-suffix .S$(SUFFIX)$(OBJEXT) "$(CC)" -- $(CFLAGS) -- $(filter %.S,$(ALL_DEP_OBJS_$(BATCH))) >>$(PREFIX)Make.dep) \
$(shell $(MKDEP) $(DEPPATH) --obj-suffix $(CXXEXT)$(SUFFIX)$(OBJEXT) "$(CXX)" -- $(CXXFLAGS) -- $(filter %$(CXXEXT),$(ALL_DEP_OBJS_$(BATCH))) >>$(PREFIX)Make.dep) \
)
$(Q) touch $@
depend:: $(PREFIX).depend
@:
clean::
$(call DELFILE, .built)
$(call CLEANAROBJS)
$(call CLEAN)
distclean:: clean
$(call DELFILE, Make.dep)
$(call DELFILE, .depend)
$(foreach AIDLSRC,$(AIDLSRCS),$(call DELAIDLOUT,$(AIDLSRC)))
-include $(PREFIX)Make.dep
# Include Wasm specific definitions
include $(APPDIR)/tools/Wasm.mk