NuttX 构建系统
(嵌入式 实时操作系统 rtos nuttx 7.1 makefile)
NuttX 构建系统
转载请注明出处: http://blog.csdn.net/zhumaill/article/details/24400441
1 简单介绍
NuttX 是通过 Makefile 文件组织编译的。Makefile 文件描写叙述了整个 NuttX project的编译、链接等规则,告诉 make 要编译哪些文件、如何编译以及在什么条件下编译。
NuttX 没有使用 Autoconf、 Automake、 CMake、 SCons 等自己主动化编译工具。它的 Makefile 文件全然由手工编写。比那些自己主动化编译工具所使用的编译文件更easy阅读。更easy理解软件的编译过程。
正应了那句话:试图用一种方法使事情变得简单,结果却使事情变得更复杂。
2 Makefile 文件组织结构
- nuttx/Makefile: 顶层 Makefile 文件。内容非常easy,依据主机环境。条件包括 Makefile.unix 或 Makefile.win。
- nuttx/Makefile.unix:Linux 环境下的 Makefile 文件。
- nuttx/Makefile.win:Windows 环境下的 Makefile 文件。
- nuttx/Make.defs:从 nuttx/config/<板卡>/<目标配置>/Make.defs 复制而来。
- 各级子文件夹下的 Makefile、 Make.defs 和 Make.dep。
3 Makefile 文件包括树
(顶层文件夹是 nuttx)
` |<--.config
|
| |<--.config
| |<--tools/Config.mk
|<--Makefile.unix-|
Makefile-| | |<--.config
| |<--Make.defs-|<--tools/Config.mk
| |<--arch/arm/src/armv7-m/Toolchain.defs
|
|<--Makefile.win-(略)
能够看出,《nuttx 配置系统》中所生成的 .config 文件被包括在 Makefile 文件里。
各级子文件夹下的 Makefile、 Make.defs 和 Make.dep 并非通过 include 包括的。而是在运行 Makefile 文件里的 make 命令时调用的。
4 构建目标和选项
4.1 构建目标:
下面是在顶层 Makefile 文件里可用的构建目标的概述:
all
默认目标,按已选择的输出格式构建 NuttX 可运行文件。
clean
移除派生对象文件、静态库文件、可运行文件和暂时文件,但保留配置和上下文的文件和文件夹。还保留 Make.dep 文件。
distclean
除了完毕 “clean” 的工作之外,还包含移除全部配置和上下文的文件。本质是将文件夹结构还原为其原始的、未配置的状态。
4.2 应用程序内务处理目标
APPDIR 变量引用用户应用程序文件夹。如 NuttX 包括的 app/ 文件夹,然而,这不被看作是 NuttX 的一部分,能够被一个不同的应用程序文件夹替代。在大多数情况下,应用程序文件夹在 Makefile 脚本中被看作像不论什么其他构建文件夹。可是,为方便起见,包括了下面目标,以支持从 NuttX 构建文件夹处理用户应用程序文件夹中的内务处理功能。
apps_clean
仅对用户应用程序文件夹运行 clean 操作。
apps_distclean
仅对用户应用程序文件夹运行 distclean 操作。 apps/.config 文件被保留,所以这不是一个全然的 distclean。但多于配置复位。
export
export 目标将打包 NuttX 库和头文件到可输出包。
注意事项:(1) 须要对 KERNEL 构建做一些扩展。
(2) tools/mkexport.sh 中的逻辑仅仅支持 GCC,比如,显式地假定静态库生成器为“ar”。
download
这是一个助手目标,它将重建 NuttX 并将其下载到目标系统,仅仅需一步。
此目标的操作全然依赖于用户 Make.defs 文件里的 DOWNLOAD 命令的实现。假设没有定义 DOWNLOAD 命令。它将产生一个错误。
4.3 内部目标
下面目标是由 make 逻辑内部使用的,但假设有必要。能够在某些条件下从命令行调用。
depend
创建构建依赖关系,生成 Make.dep 文件和 .depend 文件。(注意:当前在使用 Windows 本地工具链的 Cygwin 下不支持构建依赖关系)
context
在每次目标构建时调用 context 目标以确保正确配置了 NuttX。
基本配置步骤包含在 include/nuttx 文件夹中创建 config.h 和 version.h 头文件,建立链接到配置文件夹的符号链接。
clean_context
这是 distclean 目标的一部分。它移除由 context 目标创建的全部头文件和符号链接。
4.4 构建选项
当然。不论什么 make 变量的值都能够从命令行覆盖。然而,有一个特殊的变量赋值选项可能对你很实用:
V=1
这是生成具体级别标志。假设你在命令行上指定 V=1,你将在构建时看到所使用的确切命令。当加入新的板卡或追踪编译时错误和警告时可能很实用。
5 all 目标依赖树
` |<--pass1dep-|<----------------------------------------╮
|<--pass1deps-| |<--tools/mkdeps$(HOSTEXEEXT) |
| | | |
| ╭--╯ |<--$(USERLIBS)(平面构建时为空) |
| | |
| | |<--pass2dep-|<---------------------------------------|
|<---pass2deps-| |<--tools/mkdeps$(HOSTEXEEXT) |
| | | | |
| | | |<--$(NUTTXLIBS)(与配置有关)<--╮ |
| | | | |
| | | ╭-----------------------------------╯ |
| | | | |
| | | |<--lib/libsched$(LIBEXT)<--sched/libsched$(LIBEXT)<--------|
| | | |<--lib/libc$(LIBEXT)<--libc/libc$(LIBEXT)<-----------------|
| | | |<--lib/libmm$(LIBEXT)<--mm/libmm$(LIBEXT)<-----------------|
all<--$(BIN)-| | | |<--lib/libarch$(LIBEXT)<--$(ARCH_SRC)/libarch$(LIBEXT)<----|
| | | |<--lib/libcxx$(LIBEXT)<--libxx/libcxx$(LIBEXT)<------------|
| | | |<--lib/libapps$(LIBEXT)<--$(APPDIR)/libapps$(LIBEXT)<------|
| | | |<--lib/libnet$(LIBEXT)<--net/libnet$(LIBEXT)<--------------|
| | | |<--lib/libfs$(LIBEXT)<--fs/libfs$(LIBEXT)<-----------------|
| | | |<--lib/libdrivers$(LIBEXT)<--drivers/libdrivers$(LIBEXT)<--|
| | | |<--lib/libbinfmt$(LIBEXT)<--binfmt/libbinfmt$(LIBEXT)<-----|
| | | |
| | ╰---------╮ |
| | | |
| ╰--------╮ | |
| | | |
|<--pass1<--╯ | |
| | |
|<--pass2<------╯ |
|
╭---------------------------------------------------------------------------╯
|
| |<--check_context
| |
| |<--include/nuttx/config.h-|<--$(TOPDIR)/.config
| | |<--tools/mkconfig$(HOSTEXEEXT)
| |
| |<--include/nuttx/version.h-|<--$(TOPDIR)/.version
| | |<--tools/mkversion$(HOSTEXEEXT)
| |
|<--context-|<--include/math.h<--include/nuttx/math.h
|<--include/float.h<--include/nuttx/float.h
|<--include/stdarg.h<--include/nuttx/stdarg.h
|
| |<--include/arch<-Make.defs
| |
| |<--include/arch/board-|<--include/arch<--Make.defs
| | |<--Make.defs
| |
|<--dirlinks-|<--include/arch/chip-|<--include/arch<--Make.defs
| |<--Make.defs
|
|<--$(ARCH_SRC)/board<--Make.defs
|<--$(ARCH_SRC)/chip<--Make.defs
|<--include/apps<--Make.defs
6 all 目标编译过程
6.1 context 目标
由于 all 目标是默认目标。所以运行无參数的 make 命令即为编译 all 目标。首先会尝试编译 context 目标,当中,依据 .config 文件生成 config.h,有很多 C 文件包括了 config.h,以获得用户配置。注意当中的2个文件夹软链接,下文会用到:
$(ARCH_SRC)/board:
将 nuttx/configs/shenzhou/src 文件夹链接到 nuttx/arch/arm/src/board 文件夹。
$(ARCH_SRC)/chip:
将 nuttx/arch/arm/src/stm32 文件夹链接到 nuttx/arch/arm/src/chip 文件夹。
可是由于在安装 buildroot 时已经运行过一次 make context,并且运行 make clean 也不会删除 context 目标所生成的文件,所以这一步没做不论什么事。
6.2 pass1dep 目标
pass1dep: context tools/mkdeps$(HOSTEXEEXT)
$(Q) for dir in $(USERDEPDIRS) ; do \
$(MAKE) -C $$dir TOPDIR="$(TOPDIR)" depend ; \
done
平面构建是指将 NuttX 编译成单个二进制文件,构建的全部组件位于同样的地址空间,全部组件都能够訪问全部其他组件。
平面构建时 $(USERDEPDIRS) 为空,它也没做不论什么事。
6.3 $(USERLIBS) 目标
平面构建时 $(USERLIBS) 为空,它也没做不论什么事。
这样整个 pass1deps 目标就完毕了。
6.4 pass2dep 目标
pass2dep: context tools/mkdeps$(HOSTEXEEXT)
$(Q) for dir in $(KERNDEPDIRS) ; do \
$(MAKE) -C $$dir TOPDIR="$(TOPDIR)" EXTRADEFINES=$(KDEFINE) depend; \
done
依据 $(KERNDEPDIRS) 变量的值,在各级子文件夹下生成 Make.dep 和 .depend文件。
nuttx 文件夹下生成 Make.dep 和 .depend 文件的子文件夹有:
- nuttx/arch/arm/src
- nuttx/binfmt
- nuttx/configs/shenzhou/src
- nuttx/drivers
- nuttx/fs
- nuttx/libc
- nuttx/libxx
- nuttx/mm
- nuttx/net
- nuttx/sched
6.5 $(NUTTXLIBS) 目标
接下来就编译 pass2deps 目标中的 $(NUTTXLIBS),这是一个多目标。依据配置的不同,详细的目标也不同。它的工作是生成多个静态库文件。这里生成了10个静态库文件:
- nuttx/lib/libapps.a
- nuttx/lib/libarch.a
- nuttx/lib/libbinfmt.a
- nuttx/lib/libc.a
- nuttx/lib/libcxx.a
- nuttx/lib/libdrivers.a
- nuttx/lib/libfs.a
- nuttx/lib/libmm.a
- nuttx/lib/libnet.a
- nuttx/lib/libsched.a
以下以 libarch.a 为例。考查静态库的编译过程。
$(ARCH_SRC)/libarch$(LIBEXT): context
$(Q) $(MAKE) -C $(ARCH_SRC) TOPDIR="$(TOPDIR)" libarch$(LIBEXT)
当中: $(ARCH_SRC) = nuttx/arch/arm/src。$(LIBEXT) = .a。传递的不是变量名,而是变量中的值。第2行的意思是先切换到文件夹 nuttx/arch/arm/src。再运行 make 命令,传递參数 TOPDIR。编译目标 libarch.a。这里的 make 调用的是文件夹 nuttx/arch/arm/src 中的 Makefile,编译的是该 Makefile 中的目标。在 nuttx/arch/arm/src/Makefile 中先定义
BIN = libarch$(LIBEXT),然后:
$(BIN) $(KBIN): $(OBJS)
$(call ARCHIVE, $@, $(OBJS))
当中:OBJS = $(AOBJS) $(COBJS),而
AOBJS = $(ASRCS:.S=$(OBJEXT))
ASRCS = $(CHIP_ASRCS) $(CMN_ASRCS)
COBJS = $(CSRCS:.c=$(OBJEXT))
CSRCS = $(CHIP_CSRCS) $(CMN_CSRCS)
nuttx/arch/arm/src/Makefile 包括了 nuttx/arch/arm/src/chip/Make.defs,4个变量 CHIP_ASRCS、 CMN_ASRCS、 CHIP_CSRCS、 CMN_CSRCS 都是在 nuttx/arch/arm/src/chip/Make.defs 中定义的。多次赋值后的变量值例如以下:
CHIP_ASRCS = (空)
CMN_ASRCS = up_saveusercontext.S up_fullcontextrestore.S up_switchcontext.S vfork.S
CHIP_CSRCS = stm32_allocateheap.c stm32_start.c stm32_rcc.c stm32_lse.c stm32_lsi.c stm32_gpio.c stm32_exti_gpio.c stm32_flash.c stm32_irq.c stm32_timerisr.c stm32_dma.c stm32_lowputc.c stm32_serial.c stm32_spi.c stm32_sdio.c stm32_tim.c stm32_waste.c stm32_ccm.c
stm32_i2c.c stm32_idle.c stm32_pmstop.c stm32_pmstandby.c stm32_pmsleep.c stm32_pminitialize.c stm32_eth.c stm32_pwr.c stm32_rtc.c
CMN_CSRCS = up_assert.c up_blocktask.c up_copyfullstate.c up_createstack.c up_mdelay.c up_udelay.c up_exit.c up_initialize.c up_initialstate.c up_interruptcontext.c up_memfault.c up_modifyreg8.c up_modifyreg16.c up_modifyreg32.c up_releasepending.c up_releasestack.c
up_reprioritizertr.c up_schedulesigaction.c up_sigdeliver.c up_systemreset.c up_unblocktask.c up_usestack.c up_doirq.c up_hardfault.c up_svcall.c up_vfork.c
从这里能够查到哪些源文件被编译,哪些源文件没有被编译。
命令 $(call ARCHIVE, $@, $(OBJS)) 打包静态库 libarch.a。
如今回到nuttx/Makefile.unix:
lib/libarch$(LIBEXT): $(ARCH_SRC)/libarch$(LIBEXT)
$(Q) install $(ARCH_SRC)/libarch$(LIBEXT) lib/libarch$(LIBEXT)
当中: install 是 Linux 命令。这里等同于复制。将 libarch.a 拷贝到 nuttx/lib 文件夹。
6.6 pass1 目标
pass1: pass1deps
ifeq ($(CONFIG_BUILD_2PASS),y)
$(Q) if [ -z "$(CONFIG_PASS1_BUILDIR)" ]; then \
echo "ERROR: CONFIG_PASS1_BUILDIR not defined"; \
exit 1; \
fi
$(Q) if [ ! -d "$(CONFIG_PASS1_BUILDIR)" ]; then \
echo "ERROR: CONFIG_PASS1_BUILDIR does not exist"; \
exit 1; \
fi
$(Q) if [ ! -f "$(CONFIG_PASS1_BUILDIR)/Makefile" ]; then \
echo "ERROR: No Makefile in CONFIG_PASS1_BUILDIR"; \
exit 1; \
fi
$(Q) $(MAKE) -C $(CONFIG_PASS1_BUILDIR) TOPDIR="$(TOPDIR)" LINKLIBS="$(LINKLIBS)" USERLIBS="$(USERLIBS)" "$(CONFIG_PASS1_TARGET)"
endif
平面构建时不做不论什么事。
6.7 pass2 目标
最后编译pass2
pass2: pass2deps
$(Q) $(MAKE) -C $(ARCH_SRC) TOPDIR="$(TOPDIR)" EXTRA_OBJS="$(EXTRA_OBJS)" LINKLIBS="$(LINKLIBS)" EXTRADEFINES=$(KDEFINE) $(BIN)
$(Q) if [ -w /tftpboot ] ; then \
cp -f $(BIN) /tftpboot/$(BIN).${CONFIG_ARCH}; \
fi
ifeq ($(CONFIG_RRLOAD_BINARY),y)
@echo "MK: $(BIN).rr"
$(Q) $(TOPDIR)/tools/mkimage.sh --Prefix $(CROSSDEV) $(BIN) $(BIN).rr
$(Q) if [ -w /tftpboot ] ; then \
cp -f $(BIN).rr /tftpboot/$(BIN).rr.$(CONFIG_ARCH); \
fi
endif
ifeq ($(CONFIG_INTELHEX_BINARY),y)
@echo "CP: $(BIN).hex"
$(Q) $(OBJCOPY) $(OBJCOPYARGS) -O ihex $(BIN) $(BIN).hex
endif
ifeq ($(CONFIG_MOTOROLA_SREC),y)
@echo "CP: $(BIN).srec"
$(Q) $(OBJCOPY) $(OBJCOPYARGS) -O srec $(BIN) $(BIN).srec
endif
ifeq ($(CONFIG_RAW_BINARY),y)
@echo "CP: $(BIN).bin"
$(Q) $(OBJCOPY) $(OBJCOPYARGS) -O binary $(BIN) $(BIN).bin
endif
@echo "DUMP: $(BIN).out"
$(Q) $(OBJDUMP) -x $(BIN) > $(HOME)/$(BIN).out
@echo "DUMP: $(BIN).S"
$(Q) $(OBJDUMP) -d -j .text -j .init_section -j .ARM.exidx -j .data -j .bss $(BIN) > $(HOME)/$(BIN).S
cp -f $(BIN) $(BIN).hex $(BIN).bin $(HOME)
把静态库链接成 elf 格式的可运行文件。并转换成 .hex、 .bin 等其他格式的文件。
最后5行是我加上去的。生成符号文件、反汇编文件,并把一些终于文件拷贝到 Linux 用户主文件夹。由《NuttX 安装脚本》中的下面几行实现:
if !(grep -q ' @echo "DUMP: $(BIN).out"' Makefile.unix); then
sed -i '/pass2:/,/^$/{
/^$/i\ @echo "DUMP: $(BIN).out"
/^$/i\ $(Q) $(OBJDUMP) -x $(BIN) > $(HOME)/$(BIN).out
/^$/i\ @echo "DUMP: $(BIN).S"
/^$/i\ $(Q) $(OBJDUMP) -d -j .text -j .init_section -j .ARM.exidx -j .data -j .bss $(BIN) > $(HOME)/$(BIN).S
/^$/i\ cp -f $(BIN) $(BIN).hex $(BIN).bin $(HOME)
}' Makefile.unix
fi
7 nuttx/Make.defs 文件
nuttx/Make.defs 文件是 Makefile 片断。从 nuttx/config/<板卡>/<目标配置>/Make.defs 复制而来。
由《NuttX 安装脚本》中的下面几行实现:
echo "nuttx配置"
cd $BASEDIR/$TOPDIR/nuttx/tools
./configure.sh $TARGETCONFIG
该 Makefile 片断提供架构和工具特定的构建选项。
它将在构建时被全部其他 Makefile 文件包括(一旦它被安装)。该 makefile 片断应定义:
- 工具: CC、 LD、 AR、 NM、 OBJCOPY、 OBJDUMP
- 工具选项: CFLAGS、 LDFLAGS
当该 Makefile 片断执行时,它将被传递构建根文件夹的路径 TOPDIR。该 Makefile 片断应包括:
$(TOPDIR)/.config: Nuttx 配置
$(TOPDIR)/tools/Config.mk: 一般定义
nuttx/Make.defs 文件里的定义可能依赖于 .config 文件里的一些设置。比如。假设 CONFIG_DEBUG=y。 CFLAGS将最有可能不同。
tools/Config.mk 文件包括额外的定义。这些定义可能在必要时被架构特定的 Make.defs 文件覆盖:
COMPILE、 ASSEMBLE、 ARCHIVE、 CLEAN 和 MKDEP 宏
版权声明:本文博主原创文章,博客,未经同意不得转载。
NuttX 构建系统的更多相关文章
- Google分布式构建软件之二:构建系统如何工作
分布式软件构建第二部分:构建系统如何工作 注:本文英文原文在google开发者工具组的博客上[需要FQ],以下是我的翻译,欢迎转载,但请尊重作者版权,注名原文地址. 上篇文章中提到了在Google,所 ...
- C/C++构建系统 GNU autotool
我们在网上经常可以看到c/c++开源的项目,其中很多都是使用GNU的构建系统进行配置和编译的,如果按照规范构造这些的步骤,有一定的门槛和复杂度,下文把关于auotools系列的工具和概要的流程简要汇总 ...
- C/C++构建系统 -工具汇总
关于构建系统可以先参考百科 http://en.wikipedia.org/wiki/List_of_build_automation_software http://www.drdobbs.com/ ...
- [系统集成] Android 自动构建系统
一.简介 android app 自动构建服务器用于自动下载app代码.自动打包.发布,要建立这样的服务器,关键要解决以下几个问题: 1. android app 自动化打包android 的打包一般 ...
- 团队项目·冰球模拟器——cmake 自动化构建系统的配置文件的编写
1 前言 考虑到命令行界面下编译程序并不如在 IDE 那么直观,再考虑到各位队友对 Linux 并不熟悉,如何大幅度地减轻整个项目的开发复杂度就是一个很重要的问题. 在 Linux 下有个很古老但很有 ...
- GYP构建系统总结
GYP,Generate Your Project,一个Google开源的构建系统,最开始用于Chromium项目,现在一些其他的开源项目也开始使用GYP,如v8和node-gyp.不管怎样,这仅仅是 ...
- Mozilla 构建系统(转)
英文来源:Mozilla’s Build System 中文出处:开放博客,由灰狐翻译小组制作 Mozilla 构建系统是一个非常酷的分布式系统,运行在BuildBot上.系统能在每次修改后自动重新构 ...
- [Gradle] 在 Eclipse 下利用 gradle 构建系统
转载自:http://www.ibm.com/developerworks/cn/opensource/os-cn-gradle/ 构建系统时候常常要用到 Ant, Maven 等工具,对于初学者 ...
- spring+springmvc+mybatis构建系统
今天和大家分享的是spring+springmvc+mybatis搭建框架的例子,说到这里不得不说现在市面上一流大公司还有很多用这种架子,创业型公司大部分都用springboot集成的mvc+myba ...
随机推荐
- usart和uart 的区别
摘自:https://blog.csdn.net/meic51/article/details/7714847 什么是同步和异步 转自https://blog.csdn.net/seashine_ya ...
- hdu 4406 费用流
这题问题就是当前时刻究竟选择哪门课程,易知选择是和分数有关的,而且是一个变化的权值,所以能够用拆点的方式,把从基础分到100分都拆成点.但若这样拆点的话,跑费用流时就必须保证顺序.这样就麻烦了..观察 ...
- centos 查询DNS
cat /etc/resolv.conf
- 在vue中使用babel-polyfill
在 Vue.js项目中使用Vuex,Vuex 依赖 Promise,所以如果你的浏览器没有实现 Promise (比如 IE),那么就需要使用一个 polyfill 的库 我们可以通过babel-pr ...
- 【31.72%】【codeforces 604B】More Cowbell
time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...
- jquery-9 京东和酒仙网左侧导航如何实现
jquery-9 京东和酒仙网左侧导航如何实现 一.总结 一句话总结:布局的话多用定位,由底往上一层层的来布. 1.如何实现导航向div的平滑滑动? 右侧div和左侧的li一定要放在一起 127 &l ...
- Android百日程序:GridView实现相冊效果
本章使用GridView控件来做一个相冊效果. 图片效果例如以下: 响应点击事件,点击的时候提示是当前第几章图片.从左到右,从上到下. 点击了第一张图片,显示了1. 步骤: 一 新建项目,然后把图片资 ...
- Android图表和图形创建库:EazeGraph
EazeGraph是一个 Android 库用于创建漂亮和花哨的图表.它具有易于使用和高度可定制的特点.当前支持四种不同的图表如下: Chart types Bar Chart Stacked Bar ...
- Android XMPP服务器, BOSH(Http-Binding)和WEB客户端搭建
目标: 搭建一个XMPP服务器, 实现在web page上用javascript与自己XMPP服务器通信, 匿名登录并与任何一个XMPP(Jabber)帐户通信. (Gtalk目前尚有问题) XMPP ...
- 简单sql部分强化练习题
简单查询部分sql练习题 -- 选择部门30中的全部职工 select * from emp where deptno = 30; -- 列出全部业务员(CLERK)的姓名,编号,和部门编号 sele ...