OpenWrt源码目录

  分析的OpenWrt源码目录有助于分析OpenWrt的源码

一、原始目录

在这里插入图片描述

1.1、scripts

  构建期间用到的各类脚本文件。它存放了一些脚本,使用了bash,python,perl等多种脚本语言.编译过程中,用于第三方软件包管理的feeds文件也是在这个目录当中.在编译过程中,使用到的脚本也统一放在这个目录中.
  例如patch-kernel.sh封装了patch命令,在编译时,首先将 patches 目录下的所有补丁文件打上,并且判断如果打补丁失败将退出编译过程。
  download.pl 为下载源代码的工具脚本,封装下载工具 wget 的选项以及设置从哪里下载。
在这里插入图片描述

1.2、tools

  在构建过程中使用的各种工具。编译时,主机需要使用一些工具软件,tools 里包含了获取和编译这些工具的命令.软件包里面有Makefile文件,有的还包含了patch.每个Makefile当中都有一句$(eval $(call HostBuild)),这表明编译这个工具是为了在主机上使用的.

1.3、config

  菜单设置配置文件。存放着整个系统的配置文件

1.4、 toolchain

  构建工具链所需的生成文件和配置。这个文件中存放的就是编译交叉编译链的软件包.包括:binutils,gcc,libc等等.

1.5、target

   构建imagebuilder,内核,sdk和工具链所需的生成文件和配置。openwrt的源码可以编译出各个平台适用的二进制文件,各平台在这个目录里定义了firmware和kernel的编译过程。
   存放用于编译各类平台使用的二进制文件,定义了各类平台编译固件和内核的具体过程。
是指目标嵌入式设备,针对不同的平台有不同的特性代码。
   例如下面的“target/linux”目录是对Linux系统的划分,目录下包括Linux系统针对于各种平台标准内核的不订及特殊配置(如ar7、arm系统)。

1.6、package

  用于文件生成和菜单配置的软件包。存放了openwrt系统中适用的软件包,包含针对各个软件包的Makefile。openwrt定义了一套Makefile模板.各软件参照这个模板定义了自己的信息,如软件包的版本、下载地址、编译方式、安装地址等。在二次开发过程中,这个文件夹我们会经常打交道.
  事实上,通过./scripts/feed update -a和./scripts/feed install -a的软件包也会存放在这个目录之中.
  我们可以根据自己的需求,在这个目录下新建目录(根据软件类型存放在对应的目录下),然后编写程序和Makefile脚本,这样就可以编译生成自己想要的软件了。

1.7、include

  文件生成配置文件。openwrt的Makefile都存放在这里。文件名为 *.mk 。这里的文件上是在Makefile里被include的,类似于库文件.这些文件定义了编译过程.
.mk脚本在编译时的作用
  在顶层目录下有一个“Makefile”脚本,当我们在编译源码时,输入make命令,“Makefile”脚本被执行,紧接着.mk脚本会被顶级目录下的Makefile调用,然后这些.mk脚本会解析“.config”文件(.config文件下面有介绍),并且根据“.config”文件的内容来编译相关的内容(例如下载、编译安装packages目录下的第三方软件等)。

二、原始目录下的单个文件

2.1、Makefile:

  在顶层目录执行make命令的入口文件。进行编译的总体工作。自己开发时,这个Makefile不需要改动。make文件如下:

# SPDX-License-Identifier: GPL-2.0-only
#
# Copyright (C) 2007 OpenWrt.org

TOPDIR:=${
    
    CURDIR}
LC_ALL:=C
LANG:=C
TZ:=UTC
export TOPDIR LC_ALL LANG TZ

empty:=
space:= $(empty) $(empty)
$(if $(findstring $(space),$(TOPDIR)),$(error ERROR: The path to the OpenWrt directory must not include any spaces))

world:

DISTRO_PKG_CONFIG:=$(shell $(TOPDIR)/scripts/command_all.sh pkg-config | grep '/usr' -m 1)

export ORIG_PATH:=$(if $(ORIG_PATH),$(ORIG_PATH),$(PATH))
export PATH:=$(if $(STAGING_DIR),$(abspath $(STAGING_DIR)/../host/bin),$(TOPDIR)/staging_dir/host/bin):$(PATH)

ifneq ($(OPENWRT_BUILD),1)
  _SINGLE=export MAKEFLAGS=$(space);

  override OPENWRT_BUILD=1
  export OPENWRT_BUILD
  GREP_OPTIONS=
  export GREP_OPTIONS
  CDPATH=
  export CDPATH
  include $(TOPDIR)/include/debug.mk
  include $(TOPDIR)/include/depends.mk
  include $(TOPDIR)/include/toplevel.mk
else
  include rules.mk
  include $(INCLUDE_DIR)/depends.mk
  include $(INCLUDE_DIR)/subdir.mk
  include target/Makefile
  include package/Makefile
  include tools/Makefile
  include toolchain/Makefile

$(toolchain/stamp-compile): $(tools/stamp-compile) $(if $(CONFIG_BUILDBOT),toolchain_rebuild_check)
$(target/stamp-compile): $(toolchain/stamp-compile) $(tools/stamp-compile) $(BUILD_DIR)/.prepared
$(package/stamp-compile): $(target/stamp-compile) $(package/stamp-cleanup)
$(package/stamp-install): $(package/stamp-compile)
$(target/stamp-install): $(package/stamp-compile) $(package/stamp-install)
check: $(tools/stamp-check) $(toolchain/stamp-check) $(package/stamp-check)

printdb:
	@true

prepare: $(target/stamp-compile)

_clean: FORCE
	rm -rf $(BUILD_DIR) $(STAGING_DIR) $(BIN_DIR) $(OUTPUT_DIR)/packages/$(ARCH_PACKAGES) $(TOPDIR)/staging_dir/packages

clean: _clean
	rm -rf $(BUILD_LOG_DIR)

targetclean: _clean
	rm -rf $(TOOLCHAIN_DIR) $(BUILD_DIR_BASE)/hostpkg $(BUILD_DIR_TOOLCHAIN)

dirclean: targetclean clean
	rm -rf $(STAGING_DIR_HOST) $(STAGING_DIR_HOSTPKG) $(BUILD_DIR_BASE)/host
	rm -rf $(TMP_DIR)
	$(MAKE) -C $(TOPDIR)/scripts/config clean

toolchain_rebuild_check:
	$(SCRIPT_DIR)/check-toolchain-clean.sh

cacheclean:
ifneq ($(CONFIG_CCACHE),)
	$(STAGING_DIR_HOST)/bin/ccache -C
endif

ifndef DUMP_TARGET_DB
$(BUILD_DIR)/.prepared: Makefile
	@mkdir -p $$(dirname $@)
	@touch $@

tmp/.prereq_packages: .config
	unset ERROR; \
	for package in $(sort $(prereq-y) $(prereq-m)); do \
		$(_SINGLE)$(NO_TRACE_MAKE) -s -r -C package/$$package prereq || ERROR=1; \
	done; \
	if [ -n "$$ERROR" ]; then \
		echo "Package prerequisite check failed."; \
		false; \
	fi
	touch $@
endif

# check prerequisites before starting to build
prereq: $(target/stamp-prereq) tmp/.prereq_packages
	@if [ ! -f "$(INCLUDE_DIR)/site/$(ARCH)" ]; then \
		echo 'ERROR: Missing site config for architecture "$(ARCH)" !'; \
		echo '       The missing file will cause configure scripts to fail during compilation.'; \
		echo '       Please provide a "$(INCLUDE_DIR)/site/$(ARCH)" file and restart the build.'; \
		exit 1; \
	fi

$(BIN_DIR)/profiles.json: FORCE
	$(if $(CONFIG_JSON_OVERVIEW_IMAGE_INFO), \
		WORK_DIR=$(BUILD_DIR)/json_info_files \
			$(SCRIPT_DIR)/json_overview_image_info.py $@ \
	)

json_overview_image_info: $(BIN_DIR)/profiles.json

checksum: FORCE
	$(call sha256sums,$(BIN_DIR),$(CONFIG_BUILDBOT))

buildversion: FORCE
	$(SCRIPT_DIR)/getver.sh > $(BIN_DIR)/version.buildinfo

feedsversion: FORCE
	$(SCRIPT_DIR)/feeds list -fs > $(BIN_DIR)/feeds.buildinfo

diffconfig: FORCE
	mkdir -p $(BIN_DIR)
	$(SCRIPT_DIR)/diffconfig.sh > $(BIN_DIR)/config.buildinfo

buildinfo: FORCE
	$(_SINGLE)$(SUBMAKE) -r diffconfig buildversion feedsversion

prepare: .config $(tools/stamp-compile) $(toolchain/stamp-compile)
	$(_SINGLE)$(SUBMAKE) -r buildinfo

world: prepare $(target/stamp-compile) $(package/stamp-compile) $(package/stamp-install) $(target/stamp-install) FORCE
	$(_SINGLE)$(SUBMAKE) -r package/index
	$(_SINGLE)$(SUBMAKE) -r json_overview_image_info
	$(_SINGLE)$(SUBMAKE) -r checksum
ifneq ($(CONFIG_CCACHE),)
	$(STAGING_DIR_HOST)/bin/ccache -s
endif

.PHONY: clean dirclean prereq prepare world package/symlinks package/symlinks-install package/symlinks-clean

endif

  (1)、执行make时,如果不指定任何目标,因为world目标处于第一位,所以默认执行world。
  (2)、在make时不指定OPENWRT_BUILD参数时,进入ifneq语句,如果编译时make OPENWRT_BUILD=1则进入else。ifneq语句主要工作为:
    重写OPENWRT_BUILD变量并export导出OPENWRT_BUILD变量。
    包含仅顶级目录下include目录下的debug.mk、depends.mk、toplevel.mk。
    debug.mk:在编译过程中各类信息的输出 (V=s参数用到)。
    depends.m:检查当前系统在编译内核阶段所有需要依赖的包是否安装。
    toplevel.mk:解析编译world目标的规则。
  (3)、“make clean”:删除编译目录。
  (4)、“make dirclean”:除了删除编译目录之外还删除编译工具目录。
  (5)、“make printdb”:输出所有的编译变量定义。

2.2 、rules.mk

  定义了Makefile中使用的一些通用变量和函数

2.3、 Config.in

  在include/toplevel.mk中我们可以看到,这是和make menuconfig相关联的文件.

2.4、 feeds.conf.default

  是下载第三方一些软件包时所使用的地址

2.5、 LICENSE & README

  即软件许可证和软件基本说明.其中README描述了编译软件的基本过程和依赖文件.

三、生成目录

  在我们编译完成后除了下载的源码文件,多出来的部分很明显就是编译过程中新生成的。编译工具链、目标平台的软件包等需要下载的文件都放在dl目录下。目标平台和软件包两部分都需要“build_dir/”作为编译的临时目录,并且会将目录 staging_dir作为编译的临时安装目录,最终的生成文件保存在目录bin下。
在这里插入图片描述

3.1、feeds

  openwrt的附加软件包管理器的扩展包索引目录.有点绕,简单来说就是下载管理软件包的.默认的feeds下载有packages、management、luci、routing、telephony。如要下载其他的软件包,需打开源码根目录下面的feeds.conf.default文件,去掉相应软件包前面的#号,然后更新源。
  在OpenWrt固件中,几乎所有东西都是软件包(package),可以编译为以“.ipk”结尾的安装包,这样就可以很方便地安装、升级和卸载了。注意,扩展软件包不是在主分支中维护的,但是可以使用软件包编译扩展机制(feeds)来进行扩展安装。这些包能够扩展基本系统的功能,只需要将它们链接进入主干。之后,这些软件包将会显示在编译配置菜单中。
  目录feeds用于保存扩展软件包,可以使用软件包编译扩展机制来进行扩展安装。这些包能够扩展基本系统的功能,只需要将它们链接进入编译主目录的package目录下。 之后,这些软件包将会显示在配置菜单中。
  ./sripts/feeds install -a时,feeds目录就产生了,安装的软件就存放在这个目录下了。

./scripts/feeds update -a

  安装下载好的包:

./scripts/feeds install -a

3.2、build_dir

  在前面的原始目录中,我们提到了host工具,toolchain工具还有目标文件.openwrt将在这个目录中展开各个软件包,进行编译.所以这个文件夹中包含3个子文件夹:
“build_dir/host”是一个临时目录,用来储存不依赖于目标平台的工具。tools目录中各类工具编译的结果存放在host中,因此可以看到这些目录的名称与tools下的工具名称相同。
“build_dir/toolchain-*”目录,用来储存依赖于指定平台的编译工具链。tools-chain目录交叉编译工具最终编译的结果文件。
“build_dir/”目录:目标平台和软件包两部分都需要“build_dir/”作为编译的临时目录。

3.2.1、 host

  在该文件夹中编译主机使用的工具软件

3.2.2 、toolchain-XXX

  在该文件夹中编译交叉工具链

3.2.3、 target-XXX

  在此编译目标平台的目标文件,包括各个软件包和内核文件.

3.3、bin

  保存编译完成后的二进制文件,包括:完整的bin文件,所有的ipk文件.

3.4、.dl

  在编译过程中使用的很多软件,刚开始下载源码并没有包含,而是在编译过程中从其他服务器下载的,这里是统一的保存目录。
  编译工具链、目标平台的软件包等需要下载的文件都放在dl目录下。
  在编译过程中,各类需要下载的包都保存在这个目录下 (编译过程中用的工具)。
  当编译的过程中,如果出错,出错的原因是某个软件包下载错误或丢失,可以手动下载对应的软件包(压缩文件形式),并放在这个目录下,之后重新编译。
  dl目录与feeds目录的区别:dl中存放的是编译过程中需要用到的工具,而feeds中存放的是系统编译好之后在系统中需要用的软件。

3.5、 staging_dir

  用于保存在build_dir目录中编译完成的软件.所以这里也和build_dir有同样的子目录结构.
  比如,在target-XXX文件夹中保存了目标平台编译好的头文件,库文件.在我们开发自己的ipk文件时,编译过程中,预处理头文件,链接动态库,静态库都是到这个子文件夹中.
  staging_dir作为编译的临时安装目录,其中staging_dir/toolchain-*”目录:是编译工具链的最终安装位置。通常我们不需要改动编译链目录下的任何东西,除非要更新编译工具版本等。
  tools、toolchain、build_dir、staging_dir四者的关系
  tools、toolchain目录中的编译中间文件存放在buidl_dir目录下。例如生成的.o 文件等。
  buidl_dir目录存放的软件编译文件,最终安装在staging_dir目录下,因此staging_dir目录为编译安装目录,文件安装到staging_dir目录,并由staging_dir目录的文件生成最终的编译成果。
  所以:流程是:tools、toolchain==>编译到build_dir中==>安装到staging_dir中。

3.6、tmp

  从名字来看,是临时文件夹.在编译过程中,有大量中间临时文件需要保存,都是在这里.

3.7、.logs

  这个文件夹,有时可以看到,有时没有.这是因为这个文件夹保存的是,编译过程中出错的信息,只有当编译出错了才会出现.我们可以从这里获取信息,从而分析我们的软件编译为什么没有完成.

猜你喜欢

转载自blog.csdn.net/xxxx123041/article/details/132481759