LINUX 编译系统

经常需要移植代码,我觉得LINUX的编译系统是一个很好的组织源代码和实施软件编译的模板,BUSYBOX就采用了这个模板。因此我将通读LINUX makefile。对其进行改造,方便以后编写代码。

  1. Makefile 的使用
  2. HOST工具和软件配置设置
  3. 软件依赖/构造描述
  4. 增强的编译工具
  5. 基本编译工具和编译选项
  6. 改造后的Makefile

每个段落都采用接口/实现来描述。

 

1. Makefile 的使用

1.1 MAKE执行过程显示控制

1.1.1 使用

make V=0/1/2

0: 简单显示,不显示具体命令,只显示过程

1: 详细显示,显示具体执行命令

2: 显示原因

1.1.1 实现

KBUILD_VERBOSE = $(V)

ifeq ($(KBUILD_VERBOSE),1)

  quiet =

  Q =

else

  quiet=quiet_
  Q = @
endif

 

ifeq ($(KBUILD_VERBOSE),2)
why =  。。。

echo-why = $(call escsq, $(strip $(why)))
endif

每个命令有相应的简化显示版本,如

quiet_cmd_sysmap = SYSMAP
      cmd_sysmap = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap
在执行命令前使用:

echo-cmd = $(if $($(quiet)cmd_$(1)), /
 echo '  $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';)

若KBUILD_VERBOSE = 1, 所显示的为命令所对应字符串而非简化版本。

1.2 代码检查开关

1.2.1 接口 

make C=1

1.2.2 实现

KBUILD_CHECKSRC = $(C)

ifneq ($(KBUILD_CHECKSRC),0)
  ifeq ($(KBUILD_CHECKSRC),2)
    quiet_cmd_force_checksrc = CHECK   $<
          cmd_force_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ;
  else
      quiet_cmd_checksrc     = CHECK   $<
            cmd_checksrc     = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ;
  endif
endif

1.3 用户提供软件模块支持

1.3.1 接口

make M=dir

1.3.2 实现

module-dirs := $(addprefix _module_,$(KBUILD_EXTMOD))
PHONY += $(module-dirs) modules
$(module-dirs): crmodverdir $(objtree)/Module.symvers
 $(Q)$(MAKE) $(build)=$(patsubst _module_%,%,$@)

modules: $(module-dirs)
 @echo '  Building modules, stage 2.';
 $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
。。。。

1.4 指定存放编译结果的目录(目标目录)

1.4.1 接口

make O=dir/to/store/output/files/

1.4.2 实现

KBUILD_OUTPUT := $(O)

$(filter-out _all,$(MAKECMDGOALS)) _all:
 $(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) /
 KBUILD_SRC=$(CURDIR) /
 KBUILD_EXTMOD="$(KBUILD_EXTMOD)" -f $(CURDIR)/Makefile $@

 

2. HOST工具和软件配置设置

为了对LINUX系统进行配置,系统使用KCONFIG系统,具体参见Documentation目录下kconfig-language.txt。 由于无法提供KCONFIG的执行文件,KCONFIG解释软件提供源代码。在使用KCONFIG系统前须编译出KCONFIG解释软件。

所有LINUX的配置以MACRO 存储在include/linux/autoconf.h 中,所有的文件都依赖此文件并包含此文件。如此,autoconf.h某一个改变都导致整个系统重新编译,这显然依赖的粒度太大。

LINUX采用的方法是每个文件虽然都包含autoconf.h但并不依赖它。但是make系统只能认识文件日期之间的依赖关系,这样就需要为每个MACRO创建对应的文件。这样依赖某些宏的文件可以变为依赖相应的宏对应的文件。

script/kconfig/conf 根据autoconf.h生成伪header。所有的伪header位于include/config目录下。

但是GCC -M不能生成对此伪文件的依赖。fixdep改变GCC -M的结果使得其增加对伪文件的依赖。

scripts_basic:
 $(Q)$(MAKE) $(build)=scripts/basic

# To avoid any implicit rule to kick in, define an empty command.
scripts/basic/%: scripts_basic ;

PHONY += outputmakefile
# outputmakefile generates a Makefile in the output directory, if using a
# separate output directory. This allows convenient use of make in the
# output directory.
outputmakefile:
ifneq ($(KBUILD_SRC),)
 $(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile /
     $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)
endif

 

config %config: scripts_basic outputmakefile FORCE
 $(Q)mkdir -p include/linux include/config
 $(Q)$(MAKE) $(build)=scripts/kconfig $@

注:LINUX采用以下方法包含autoconf.h

 

LINUXINCLUDE    := -Iinclude /
                   $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) /
     -include include/linux/autoconf.h

 

注: fixdep中的相关注释

 * If the user re-runs make *config, linux/autoconf.h will be
 * regenerated.  make notices that and will rebuild every file which
 * includes autoconf.h, i.e. basically all files. This is extremely
 * annoying if the user just changed CONFIG_HIS_DRIVER from n to m.
 *
 * So we play the same trick that "mkdep" played before. We replace
 * the dependency on linux/autoconf.h by a dependency on every config
 * option which is mentioned in any of the listed prequisites.
 *
 * To be exact, split-include populates a tree in include/config/,
 * e.g. include/config/his/driver.h, which contains the #define/#undef
 * for the CONFIG_HIS_DRIVER option.
 *
 * So if the user changes his CONFIG_HIS_DRIVER option, only the objects
 * which depend on "include/linux/config/his/driver.h" will be rebuilt,
 * so most likely only his driver ;-)

 

你可能感兴趣的:(Linux,linux,makefile,output,cmd,documentation,basic)