Make.bat实际上只起引导作用,其只有一行批处理语句perl make2.pl%*,于是运行该批处理文件后控制权转给了perl脚本make2.pl。在这个perl脚本中解析了用户输入的命令行参数,设置变量,准备make时需要的临时配置文件,随后根据生成的可运行映像是PC模拟版还是ARM版而分别调用不同的构建过程。
Pc模拟版的构建通过调用如下命令实现。
system("$msdev MoDIS.dsw /MAKE \"$argu - Win32 $modisDir\"
/OUT ${MoDISLogDir}\\${argu}.log")
在这里$msdev就是VC的msdev,通过VC的工程文件MoDIS.dsw和后面的参数进行具体的构建过程。熟悉VC工程的朋友应该比较清楚,因此就不再具体解释了。之后将只以ARM版为主来讲解整个工程的构建过程。
ARM版的构建通过调用如下命令实现。
system("${makeCmd} -f${makeFolder}${myMF} -r -R
CUSTOMER=$custom PROJECT=$project $action")
在这里${makeCmd}是tools\make.exe,即GNU的make,${makeFolder}${myMF}是make\Gsm2.mak,$action是new、update、remake等。变量CUSTOMER和PROJECT分别是客户名和项目名,在构建过程中将根据此两个变量的值选定项目相关的配置文件,从而实现客户化的定制。通过给make指定ARM版的核心Makefile文件Gsm2.mak,开始了ARM版的构建过程。
Gsm2.mak文件中包含了Option.mak这个配置用的Makefile文件,另外还包含了一些以.tmp和.bld为后缀的由perl脚本make2.pl生成的临时配置文件。这些临时配置文件主要是一些action如clean、remake等所需的变量设置,及客户化和版本号等的一些信息。Gsm2.mak控制了new、update、remake等动作的过程。具体分别如下所示。
new : cleanall cmmgen mmi_feature_check asngen codegen asnregen\
operator_check_lite update
update : cleanlog cleanbin mcddll_update codegen resgen cksysdrvremake
remake : cleanlog cleanbin genverno libs $(BIN_FILE)done
上面的构建过程的几个步骤中,最重要的两个步骤是libs、$(BIN_FILE)。libs调用ARM版的编译器和连接器将各个模块目录下的C文件编译链接为独立的库。$(BIN_FILE)这个步骤将各个模块编译链接得到的库和mtk_lib目录下的库一起链接起来得到一个映像文件,然后使用ADS的工具fromelf将映像文件生成以变量BIN_FILE命名的二进制文件,该文件可以下载到硬件板上运行。
libs这个步骤如下所示。
libs: cleanlib startbuildlibs $(COMPLIBLIST)
libs中真正进行编译链接的步骤是$(COMPLIBLIST),要生成的库由变量COMPLIBLIST列出,在ARM版中,变量COMPLIBLIST从变量COMPLIST得到。变量COMPLIST是在Option.mak及其包含的Makefile文件中赋值的。因有很多库需要编译链接,变量COMPLIBLIST展开后包含多个步骤,而这些步骤都是重复不变的,因此在定义步骤$(COMPLIBLIST)的构建过程时使用%.lib代替。%.lib这个步骤先清除了之前的一些依赖关系文件,将一些变量的设置写入~compbld.tmp这个临时文件中,然后给make指定Makefile文件comp.mak,完成库的编译和链接,如下所示。
%.lib:
…
@if /I %OS% EQU WINDOWS_NT \
(if /I $(BM_NEW) EQU TRUE \
(tools\make.exe -fmake\comp.mak -k -r -R $(strip $(CMD_ARGU))COMPONENT=$* >$(strip $(COMPLOGDIR))\$*.log2>&1)
\
else \
(tools\make.exe -fmake\comp.mak -r -R $(strip $(CMD_ARGU))COMPONENT=$* >$(strip $(COMPLOGDIR))\$*.log2>&1) \
) \
else \
(if /I $(BM_NEW) EQU TRUE \
(tools\make.exe -fmake\comp.mak -k -r -R $(strip $(CMD_ARGU))COMPONENT=$* >$(strip $(COMPLOGDIR))\$*.log) \
else \
(tools\make.exe -fmake\comp.mak -r -R $(strip $(CMD_ARGU))COMPONENT=$* >$(strip $(COMPLOGDIR))\$*.log) \
)
上面的命令语句中,参数-k是指有错误也要继续编译,-r和-R是指没有GNUmake的默认规则和变量。COMPONENT=$*把当前要生成的库赋给变量COMPONENT。要注意%.lib匹配了所有要生成的库,但这个步骤一次只生成一个模块的库,这个步骤对所有匹配到的库都会执行一次。
comp.mak这个Makefile文件控制了模块的编译链接过程。在这个文件中,首先将当前模块要生成的库(由变量COMPONENT传入)设置给了变量TARGLIB。之后从.lis文件中得到SRC_LIST和CPPSRC_LIST两个源文件列表,设定要编译的C文件、C++文件、汇编文件等的列表,和要链接的中间目标文件的列表。将.inc、.def、.pth文件中的头文件路径、C文件路径、编译链接参数等赋值给相应的变量。将平台相关(如6223、6225)的编译参数加上,确定使用ARM编译器还是thumb编译器,是否支持ARM指令和thumb指令的interwork模式。最后进入库的编译链接过程。
库的编译链接由update_lib步骤完成,这个步骤直接依赖了$(TARGLIB)。目标$(TARGLIB)是由所有按照.c.obj、.s.obj、%.obj:%.cpp等规则编译得到的中间目标文件链接得到的。其主要过程如下所示。
$(TARGLIB):
...
@if exist $(FIXPATH)\$(CUS_MTK_LIB)\$(COMPONENT).lib \
(copy /z $(FIXPATH)\$(CUS_MTK_LIB)\$(COMPONENT).lib $(subst/,\,$(TARGLIB))) &\
($(LIB) -r $(TARGLIB) $(COMPOBJS_DIR)/*.obj) \
else \
($(LIB) -create $(TARGLIB)$(COMPOBJS_DIR)/*.obj)
...
Option.mak是整个工程构建过程中的总控配置文件,在这个文件中还包含了_.mak和REL_CR_MMI_.mak这两个项目相关的配置文件,用户自定义的配置文件USER_SPECIFIC.mak,另外还包含了一些临时生成的配置文件。这些配置文件在一起设置了工程构建过程中用到的编译器、链接器,库和二进制的工具,设置了编译链接时的参数,公共的头文件路径,设置了需要包含mtk_lib目录中的哪些既有的库,设置了需要生成的库等一系列相关的设置。
如果看不懂,请阅读相关的arm的编译工程
=====================================================================
在build目录下的Makefile文件中添加宏定义的时候,在用make r221 gprs new命令后,添加的宏不在
了,原因是应该把添加的宏放在make目录下的Makefile文件中,因为在New的时候会拷贝make目录下的
akefile覆盖build目录下的Makefile.
11 IncrediBuild联合编译的使用默认分类
联合编译的意义在于充分利用网格中的闲置电脑资源提高我们的编译效率。它主要由Agents和CoordinatorServer组成。Agents主要作为工作机,分配出来的计算工作在这些电脑上完成。CoordinatorServer负责分配工作,协调网络中的各个电脑的性能均衡。
联合编译的功能引入分为下面几个要素:
1. 使能或禁止联合编译功能;
2. 检查XGC是否存在;
3. 定义可用的进程数;
4. 中间编译文件;
5. 编译命令;
1.1. 使能或禁止联合编译的参数设定
对于MTK平台,可以通过命令行方式参数“-disable_ib”,“-no_ib”或“-bm”。我们可以通过查看脚本make2.pl确认。
} elsif ($ARGV[0] =~ /-disable_ib/i) {
$disable_ib = 1;
} elsif ($ARGV[0] =~ /-no_ib/i) {
$disable_ib =1;
} elsif ($ARGV[0] =~ /-bm/i) {
$disable_ib =1;
}
1.2. 确认联合编译环境
接着系统开始检查联合编译器以及系统是否支持联合编译,请看下面脚本的检查。首先,脚本执行命令“$exec_xgc_result = `XGConsole /NOLOGO /SILENT /NOWAITtools\\XGC_Test.xml 2>&1`;”,确认是否存在联合编译器。
my $no_of_proc=1;
my $exec_xgc_result=999;
# $exec_xgc_result = system("XGConsole /NOLOGO/SILENT tools\\XGC_Test.xml \n");
$exec_xgc_result = `XGConsole /NOLOGO /SILENT/NOWAIT tools\\XGC_Test.xml 2>&1`;
if ("$exec_xgc_result" ne "")
{
$exec_xgc_result=99;
# print "XGConsole not found";
} else
{
if (("$ENV{\"TERM\"}" eq "")&& ("$ENV{\"USERDOMAIN\"}" eq"DOMAIN_MTK"))
{
$disable_ib =1;
print "WARNING: XGConsole is supported but it's NOT in telnetmode. TERM is not defined! \n";
}
if ($disable_ib==0)
{
$exec_xgc_result=0;
# print "XGConsolefound";
} else
{
$exec_xgc_result=99;
}
}
其中,XGC_Test.xml是比较简单的。然后,通过环境变量确认OS是否支持联合编译。
下面的脚本是用来确认对VC++的联合编译特性的支持的。
my $exec_buildconsole=999;
#$exec_buildconsole = system("BuildConsole\n");
$exec_buildconsole =`BuildConsole 2>&1`;
if ($exec_buildconsole =~ /IncrediBuild/)
{
if ( "$ENV{\"TERM\"}" eq "" )
{
$disable_ib =1;
print "WARNING: BuildConsole is supported but it's NOT in telnetmode. TERM is not defined! \n";
}
if ($disable_ib==0)
{
$exec_buildconsole=0;
#print "\nBuildConsolefound";
} else
{
$exec_buildconsole=99;
}
} else
{
$exec_buildconsole=99;
#print "\nBuildConsole not found";
}
if ( $exec_buildconsole==0 ) # support BuildConsole
{
system "perl tools\\RunMsdev.pl";
$msdev = 'BuildConsole msdev';
} else # not support BuildConsole
{
$msdev ='msdev';
}
1.3. 定义进程数
根据CPU个数设定编译可创建的进程数,一般双核CPU的进程数设为4各基本均衡了。
if (($action eq "update") || ($action eq "remake") || ($actioneq "new") || ($action eq "bm_new") ||
($actioneq "c,r") || ($action eq "c,u") || ($action eq "scan")) {
if ($ENV{"NUMBER_OF_PROCESSORS"}> 1) {
if ($exec_xgc_result==0 )
{
$no_of_proc = $ENV{"NUMBER_OF_PROCESSORS"}*2;
if ($fullOpts eq ""){
$fullOpts = "CMD_ARGU=-j$no_of_proc";
} else {
$fullOpts .= ",-j$no_of_proc";
}
} else{
if ($fullOpts eq ""){
$fullOpts = "CMD_ARGU=-j$ENV{\"NUMBER_OF_PROCESSORS\"}";
} else {
$fullOpts .= ",-j$ENV{\"NUMBER_OF_PROCESSORS\"}";
}
}
}
}
MTK还提供了通过“-o|-op|opt”来设定进程数。
if ($fullOpts ne "") {
# Fix build errors when "parallel jobs processing" fuctionenabled by argument "-o|-op|-opt" in command line
my @temp = @mOpts;
@mOpts = ();
foreach (@temp)
{
if ($_ =~ /^\s*(-j|--jobs)/)
{
$fullOpts .= ",$_";
}
else
{
push(@mOpts,$_);
}
}
# End
$fullOpts =~ s/"/\\"/g;
$fullOpts = "\"$fullOpts\"";
$fullOpts =~ s/,/ /g;
$makeCmd .= " " . join(" ", @mOpts) . "$fullOpts ";
}
1.4. 中间编译文件
中间编译文件intermed.mak包括了需要编译各个模块的依赖关系和编译方法。
1.5. 编译命令
(if /I $(BM_NEW) EQU TRUE \
(XGConsole /command="tools\make.exe -fmake\intermed.mak -k -r -R $(strip $(CMD_ARGU)) " /NOLOGO /profile="tools\XGConsole.xml" ) \
else \
(XGConsole /command="tools\make.exe -fmake\intermed.mak -r -R $(strip$(CMD_ARGU)) " /NOLOGO/profile="tools\XGConsole.xml" ) \
) \
其中,XGConsole.xml规定了各种编译工具的是否支持远程工作和是否允许分段处理的特性。
按照Xoreax IncrediBuild的说明我们可以在用GNUMAKE等语言的编译器使用联合编译。