Chinaunix首页 | 论坛 | 博客
  • 博客访问: 869072
  • 博文数量: 189
  • 博客积分: 4310
  • 博客等级: 上校
  • 技术积分: 1925
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-27 08:56
文章分类

全部博文(189)

文章存档

2015年(1)

2013年(2)

2012年(1)

2011年(39)

2010年(98)

2009年(48)

分类: Android平台

2015-02-03 16:38:59

应该是12年写的文档,由于各种原因没有发出来,不过mtk的编译架构应该整体没变,望对需要的人有帮助


 

    先从最先的mk这个文件说起。这个mk文件其实是perl脚本,不要被这个陌生的名字吓着,比起makefile还是好理解了很多。我刚看脚本时也不懂,也是一步步googlegoogle是最好的老师嘛。

my $DEBUG = 1; # enable/disable script debugging message 这边其实打印的debug信息也不多,往下仔细看一下,就清楚了。

@chkDirs = qw(mediatek mediatek/config mediatek/build/tools);其实这个perl的数组。后面还会出现很多这样的数组。

后面的代码大部分是检验文件存不存在和赋值这类的,所以先忽略吧,这进入比较关键的make过程吧

$cmdArg = "CMD_ARGU=\"@mOpts\"";

$makeCmd = "make -f mediatek/build/makemtk.mk $cmdArg @mOpts";

 

以下的执行分为两种情况,

1):new 这边将进行用户代码的复制,复制的文件是根据projectconfig.mk来复制。这个后面再稍微详细说吧

2):remake 不复制用户工程配置的代码。如果编译内核会从新生成mediatek-config文件,其实如果重复编译的话。如果没有改到项目的配置。不用新生成这个文件也可以的。这个也后面再说吧。

if ($#arguments < 0)

    {

      print "you yan here6666666666666\n";

      if (${uAct} =~ /(new|remake|clean)/)

      {

        if ($uAct =~ /(new|remake)/)

        {

          &chkMustEnv;

          &chkDep;

        }

        $result += &p_system("$makeCmd ${uAct}all");

      }

      else

      {

        $result += &p_system("$makeCmd $uAct CUR_MODULE=android");

      }

    }

    else

    {

      print "you yan here77777777777\n";

      foreach $uMod (@arguments)

      {

        &chkDep("$uMod");

        if ( ($KMOD_PATH ne "") && ($uMod eq "kernel") )

        {

           print "you yan here888888888\n";

           print "$uAct $uMod $KMOD_PATH\n";

          $result += &p_system("$makeCmd $uAct CUR_MODULE=$uMod KMOD_PATH=$KMOD_PATH");

          last;

        }

        elsif ( ($DR_MODULE ne "") && ($uMod eq "android") )

        {

          $result += &p_system("$makeCmd $uAct CUR_MODULE=$uMod DR_MODULE=$DR_MODULE");

          last;

        }

        else

        {

          $result += &p_system("$makeCmd $uAct CUR_MODULE=$uMod");

        }

      }

}

 

关于p_system这个函数就是调用perl的运行函数。

sub p_system

{

  my ($cmd) = @_;

  my ($debugp) = 0;

  my $result;

  ($debugp != 0) && print("$cmd\n");

  ($performanceChk == 1) && print &CurrTimeStr . " system $cmd\n";

  $result = system("$cmd");

  ($performanceChk == 1) && print &CurrTimeStr . " exit $cmd\n";

  return $result;

}

 

真正的执行在system("$cmd");如果大家有空可以google一下,看看怎么回事。毕竟自己亲手弄弄比较好理解。

 

我们现在来看make -f mediatek/build/makemtk.mk

现在就进入了这个熟悉而又陌生,厌恶的世界了。其实比较不好看懂的也是在这边。如果大家想了解了叫makefile make的,给大家推荐两个文档——《跟我一起写makefile》和《gnu make》,其中《跟我一起写makefile》很适合入门,《gnu make》是跟很好的资料书,大部分makefile的知识点都用,很方便查找。在makefile中,比较经常需要查找的就是几个自动变量。如果你的脑袋觉得比较轻松的时候,可以记记,毕竟每次查一下还是要花时间的。

下面是一些自动变量,我先列出来

 

$@

代表规则中的目标文件名。如果目标是一个文档(Linux中,一般称.a文件为文档),那么它代表这个文档的文件名。在多目标的模式规则中,它代表的是哪个触发规则被执行的目标文件名。

$%

规则的目标文件是一个静态库文件时,代表静态库的一个成员名。例如,规则的目标是“foo.a(bar.o)”,那么,“$%”的值就为“bar.o”,“$@”的值为“foo.a”。如果目标不是函数库文件,其值为空。

$<

规则的第一个依赖文件名。如果是隐含规则,则它代表通过目标指定的第一个依赖文件。

$?

所有比目标文件更新的依赖文件列表,空格分割。如果目标是静态库文件名,代表的是库成员(.o文件)的更新情况

 

$^

规则的所有依赖文件列表,使用空格分隔。如果目标是静态库文件名,它所代表的只能是所有库成员(.o文件)名。一个文件可重复的出现在目标的依赖中,变量“$^”只记录它的一次引用情况。就是说变量“$^”会去掉重复的依赖文件。

$+

类似“$^”,但是它保留了依赖文件中重复出现的文件。主要用在程序链接时,库的交叉引用场合。

$*

在模式规则和静态模式规则中,代表“茎”。“茎”是目标模式中“%”所代表的部分

 

$$@”、“$$(@D)”和“$$(@F)”(注意:要使用“$$”),它们分别代表了“目标完整的文件名”、“目标文件名中的目录部分”和“目标的实际文件名部分”。

makemtk.mk里将声明很多的变量,包括编译的线程,指定分区的文件

 

如果编译的选项是new的话将会复制客户的代码与配置文件,将会执行以下代码

custgen:

    $(hide) echo $(SHOWTIME) $@ing...

    $(hide) echo -e \\t\\t\\t\\b\\b\\b\\bLOG: $(S_LOG)$@.log

    $(hide) make -f mediatek/build/custgen.mk $(DEAL_STDOUT_CUSTGEN) && \

      $(SHOWRSLT) $${PIPESTATUS[0]} $(LOG)$@.log || $(SHOWRSLT) $${PIPESTATUS[0]} $(LOG)$@.log

其中hide :=  @,所以$(hide)即@,由于在makefile中执行每条指令都会打印出来,然而如果makefile中在命令前面在@,表示在执行这条语句是省略打印命令命令接下来我们来看make -f mediatek/build/custgen.mk,custgen.mk文件里面的内容很少,

include mediatek/build/Makefile

$(call codebase-path)

all: mtk-config-files mtk-custom-files

       @echo "done"

mtk-config-files := $(strip $(call mtk.config.generate-rules,mtk-config-files))

mtk-custom-files := $(strip $(call mtk.custom.generate-rules,mtk-custom-files))

其中mtk-config-filesmtk-custom-files就是来搬运客户的配置文件和客户的配置源文件。mtk.config.generate-rules,mtk-config-filesmtk.custom.generate-rules,mtk-custom-files这两个宏的定义比较复杂,它们的实现分别在mediatek/build/libs/config.mkmediatek/build/libs/custom.mk中。

大家在编译new的时候会看到类似的打印信息

[CONFIG] copy mediatek/config/公司产品目录/mtk_omx_core.cfg

           to mediatek/config/out/公司产品目录/mtk_omx_core.cfg

这个是由mtk.config.generate-rules,mtk-config-files实现

[CUSTOM] copy mediatek/custom/公司产品目录/uboot/inc/cust_battery.h

           to mediatek/custom/out/公司产品目录/uboot/inc/cust_battery.h

这个是由mtk.custom.generate-rules,mtk-custom-files实现。

 

将会分别把代码复制到mediatek/config/outmediatek/custom/out这两个目录里,然而这部分代码是根据什么复制过来的呢,这边的代码就是会根据我们经常配的projectconfig.mk这个来执行,复制对应文件夹。后面再会说到编译过程。

 

下面来说我最关心的地方,kernel的配置。刚拿到MTK的代码时,我也是非常的蒙

也许做过MTKfuture phone的同事,也许是不会蒙,可我真是蒙的,那是真实灰常的郁闷,呵呵。后面就有一定要把MTK的代码还原成真实android的想法。也可以再进步进步我的makefile。塞翁失马焉知非福嘛。后面再网上也看到有人说。做MTK的东西学不到什么,做MTKandroid还是在future phone。我想当这个人,如果把MTK的脚本makefile都大概知道了,他也就不会说这句话了。如果要理清MTK的代码,你就必须对linux代码结构,编译,链接的方式有所了解。(我还真实花时间去看了linux的编译,呵呵,给大家推荐个文档《linux 内核构建系统》)。所以如果你理清了MTK的代码,你对linux的认识又会上一个小台阶。还有一些linux的书籍,就大家去google吧。

好吧,不扯了。各有各的想法吧。下面来看看如果编译内核的吧。

编译内核将运行makemtk.mk这个文件里的的

kernel:

ifeq ($(BUILD_KERNEL),yes)

  ifeq ($(ACTION),)

       $(hide) perl $(MEM_PARTITION_GENERATOR) \

                     $(MTK_PLATFORM) \

                     $(MTK_LCA_SUPPORT) \

                     $(MEM_PARTITION_TABLE) \

                     $(PARTITION_HEADER_LOCATION) \

                     $(dir $(SCATTER_FILE)) \

                     $(MTK_NAND_PAGE_SIZE) \

                     $(MTK_EMMC_SUPPORT) \

                     $(EMMC_CHIP) \

                     $(BOARDCONFIG_LOCATION) \

                     $(MTK_LDVT_SUPPORT) \

                     $(TARGET_BUILD_VARIANT) \

                     $(DEAL_STDOUT_PTGEN)

 

       $(hide) perl $(OTA_SCATTER_GENERATOR) $(SCATTER_FILE) $(OTA_SCATTER_FILE)

  endif

 

  ifneq ($(KMOD_PATH),)

       $(hide)    echo building kernel module KMOD_PATH=$(KMOD_PATH)

       $(hide) cd $(KERNEL_WD) && \

       (KMOD_PATH=$(KMOD_PATH) ./build.sh $(ACTION) $(KERNEL_ARG) ) && cd $(MKTOPDIR)

  else

       $(hide) echo $(SHOWTIME) $(SHOWBUILD)ing $@...

       $(hide) echo -e \\t\\t\\t\\b\\b\\b\\bLOG: $(S_MODULE_LOG)

       $(hide) cd $(KERNEL_WD) && \

         (MAKEJOBS=$(MAKEJOBS) ./build.sh $(ACTION) $(PROJECT) $(DEAL_STDOUT) && \

          cd $(MKTOPDIR) && \

          $(call chkImgSize,$(ACTION),$(PROJECT),$(SCATTER_FILE),$(if $(strip $(ACTION)),,$(KERNEL_IMAGES)),$(DEAL_STDOUT),&&) \

         $(SHOWRSLT) $${PIPESTATUS[0]} $(MODULE_LOG) $(ACTION) || \

         $(SHOWRSLT) $${PIPESTATUS[0]} $(MODULE_LOG) $(ACTION))

#     $(hide) $(SHOWTIMECMD)

  endif

else

       $(hide) echo Not support $@.

endif

 

其中最重要的是在

       $(hide)    echo building kernel module KMOD_PATH=$(KMOD_PATH)

       $(hide) cd $(KERNEL_WD) && \

       (KMOD_PATH=$(KMOD_PATH) ./build.sh $(ACTION) $(KERNEL_ARG) ) && cd $(MKTOPDIR)

 

 

 

以上代码的功能是进入内核目录,执行build.sh这个shell脚本。MTK的脚本为什么要从perlmakefile再到shell。具体原因不太清楚,我猜是,跟它分区的文件这些有关。还望有哪个大哥指点指点。下面我们进入build.sh这个文件吧

这个文件比较重要的是

# select correct configuration file

make mediatek-configs

# update configuration

nice make ${makeflags} ${makedefs} silentoldconfig

 

先来说说,linux标准的kconfig文件吧。最重要的kconfig文件是在kernel/arch/arm/这个文件夹下

source "net/Kconfig"

 

source "drivers/Kconfig"

 

source "fs/Kconfig"

 

source "arch/arm/Kconfig.debug"

 

source "security/Kconfig"

 

source "crypto/Kconfig"

 

source "lib/Kconfig"

 

source "../mediatek/source/kernel/Kconfig"

这边也就跟mediatek这个文件夹联系起来了。另

/mediatek/source/kernel/Kconfig的最后

source "../mediatek/platform/mt6575/kernel/Kconfig/Kernel"

source "../mediatek/platform/mt6575/kernel/Kconfig/Board"

source "../mediatek/platform/mt6575/kernel/Kconfig/Drivers"

也就把MTKlinux有关的大部分配置选项包括进来的,呵呵,还有些是没有配置文件的,直接设置obj-y的,等会会看到。

接下来我们看makefile文件,最重要的makefile文件是在kernel/arch/arm/这个文件夹下

其中里面一句很重要的

include ../mediatek/build/kernel/Makefile

mediatek/build/kernel/Makefile这个文件里,有段我们做驱动很关心的:

generated_files := $(call mtk.config.generate-rules)

.config mediatek-configs: $(MTK_ROOT_GEN_CONFIG)/kconfig $(MTK_ROOT_GEN_CONFIG)

       @echo "[COPY] $< --> $@"

       @cp $< $@

       @echo "[COPY] $< --> .config"

       @cp $< .config

大家在编译内核的时候会看到

**** Configuring / ..//mediatek/config/out/公司产品目录/autoconfig/kconfig / ****

[COPY] ../mediatek/config/out/公司产品目录/autoconfig/kconfig --> mediatek-configs

[COPY] ../mediatek/config/out/公司产品目录/autoconfig/kconfig --> .config

 

这边就是生成在kernel目录下的mediatek-cofigs这个文件的。这里面就是用到了,我前面说到的自动变量,如果大家忘记了,麻烦大家倒回去查一下吧。

由上面可以看出,mediatek-configsmediatek/config/out/公司产品目录/autoconfig/kconfig的拷贝,这个kconfig不是linux的标准的kconfig,而是编译选项。而大家也会看到,这边也生成了一个.config,然而等你编译完,用mediatek-configs.config比较一下,两个文件的内容是不一样的。具体原因是在执行make mediatek-config的时候也会生成一个.config文件,此时会把这段代码生成的覆盖。然而大家又会觉得疑惑,那mediatek/config/out/公司产品目录/autoconfig/kconfi是怎么生成的呢,在MTK的代码中是找不到跟这个文件一样的,这个文件是由三个文件合并而成。合并的代码在mediatek/build/libs/config.mk

define .mtk.config.generate-auto-merge-rules

.PHONY: mediatek-configs.$(1)

mediatek-configs: mediatek-configs.$(1)

mediatek-configs.$(1): $(2)

$(2): PRIVATE_FILE_LIST := $(3)

$(2): $(3) $(4)

       @echo "[CONFIG] generate $(2) "

       @cat $(3) | $(5) > $(2)

Endef

 

大家在new的时候会看到

[CONFIG] generate mediatek/config/out/公司产品目录/autoconfig/kconfig

这句其实就是上段代码打印。

这个kconfig是由

mediatek/config/mt6575/autoconfig/kconfig/platform

mediatek/config/common/autoconfig/kconfig/AEE

mediatek/config/公司产品目录/autoconfig/kconfig/project 

这三个文件合成的,使用的工具是

python mediatek/build/tools/config/merge-kconfig.py

如果大家想了解,可以再上段代码中,打印出来。

 

另:我们经常配置的projectconfig.mk这个文件,只是普通makefile声明的变量而已,并没有跟linux标准的kconfigmakefile联系。

 

由于时间限制,我现在只看到这里。Google那部分代码,有空再整理,本文写得比较粗糙和匆忙。由于表达能力不是很强,可能会有很多的语句不顺。望各位见谅。就仅当笔记。各位有什么意见和建议,欢饮指点哦。谢谢!
阅读(6500) | 评论(0) | 转发(0) |
0

上一篇:Activity的启动流程

下一篇:没有了

给主人留下些什么吧!~~