http://chenyq2008.spaces.live.com/blog/cns!F73164AC8D0D8D50!252.entry
PB是如何工作的?
【使用pbxmlutils打开工程文件】
随便打开一个控制台窗口。先找到pbxmlutils工具所在的路径。比如我的:
D:/Program Files/Microsoft Platform Builder/6.00/cepb/IdeVS/pbxmlutils.exe
然后就执行下面的命令, 这样就可以打开一个工程文件, 不需要vs2005就可以构建nk。
pbxmlutils /getbuildenv /workspace "工程文件所在路径/OSDesign1.pbxml" /config "SMDK2440A ARMV4I Release" > Env.bat
call Env.bat
@echo off
call %_TARGETPLATROOT%/%_TGTPLAT%.bat
这和在vs2005里面打开工程文件一样,接下来就可以执行blddemo命令来构建平台了。
Pbxmlutils.exe打开工程文件时候调用wince.bat初始化cpu类型, 路径等等环境变量, 其中最主要的是建立了变量_DEPTREES, 逻辑比较简单, 就是遍历public下各个自目录下的cesysgen目录下是否存在makefile文件, 如果存在就增加到_DEPTREES
_DEPTREES=winceos dcom gdiex ie script servers shellsdk shell rdp wceshellfe wceappsfe directx voip datasync netcfv2 SQLCE cellcore ostest mediaapps speech FP_VOIP OSDesign3
_DEPTREES就长得这个样子的。 里面就是各个小模块,结构称之为树。组件是以树的形式安排, 每一个树就是public或者private下面的子目录。
使用了上面方法, 在普通的控制台就可以打开工程编译了, 不用启动pb或者vs2005. 我是在wince6下测试的。
【用户主要接口blddemo命令】
BldDemo [[no]clean][[no]cleanplat][nuke][nurel][Parms for CEBUILD]
用途:构建命令。伪代码如下:
Blddemo(clean, norel, Parms)
{
cebuild(Parms); //build操作系统, project和平台模块。
if (!norel) buildrel(); // release copy
if (!nomakeimage) makeimg(); // makeimg
cesysgen(); //
}
blddemo是直接提供给用户的接口, 调用一系列处理完成整个过程。最常用的是BldDemo -q和BldDemo clean -q。 简单介绍下,如果clean参数带上, 则清理之前编译构建遗留的文件。 Cleanplat把bsp目录下target和lib目录清理。Nuke则相当clean+cleanplat。如果指定norel,那么sysgen和build完后不会release copy和makeimage, 如果指定nomakeimg, 则不会makeimage。buildrel是release copy步骤,把需要的文件拷贝到指定目录准备打包。 makeimg打包image。
【重头戏:cebuild.bat】
cebuild [-h] [-r] [-q] [-d deptree_entry] [build_flags]
用途:build操作系统, project和平台模块。伪代码如下:
cebuild(Parms)
{
if (Parms == “-qbsp”) // -qbsp的意思是只处理bsp。
goto skipdeptree;
// build all the trees. _DEPTREES在前面打开项目时候在wince.bat赋了值。
if (_QBLDNEWDEPTREES == "")
_QBLDNEWDEPTREES = _DEPTREES;
for (遍历_QBLDNEWDEPTREES)
cebldtree(TreeName, preproc); // cebldtree , ce_build_tree.
for (遍历_DEPTREES)
cebldtree(TreeName, postproc);
skipdeptree:
if (!SIGN_WITH_RELEASE_KEY)
ManagedCodeSign(); // 和托管代码相关处理,先忽略。
SysgenPlatform(preproc);
cebuild1(platform, common);
cebuild1(platform, bsp);
Sysgenplatform(postproc);
// build 开发者指定目录。 指定路径:
// %_WINCEROOT%/deelopr/%USERNAME%/Source
Build(user_path); // build是ms提供的编译链接工具。
}
cebldtree(TreeName, proc)
{
if (Parms == “-q”) // 这里就是参数-q作用的地方了。之所以Quick的原因了。
goto skip_compile;
cebuild1(private, TreeName); // 编译链接private代码。
cebuild1(public, TreeName); // 编译链接public代码。
skip_compile:
sysgen( ); // 除了winceos,在树里要求子目录cesysgen下存在makefile.
}
【万佛朝宗】
项目不管多么恢弘, 离不开编译和链接。 编译工具就是cl.exe, 链接工具就是link.exe, 在sdk目录下。 今时今日, 都在用make工具, MS使用nmake, 自动根据时间戳来判断编译哪些。 更进一步的, 在nmake之上, MS用build.exe来处理代码。 据说MS大部分产品都是这样的, winddk也是, 所以总感觉搞ddk和wince那么相似。Build使用了dirs + source 文件来建筑整个代码结构的大厦。 废话到此。
所以上面的过程, 仍然没有看到build或者nmake。继续往下挖掘就看到答案了:
cebuild1()
{
build();
}
Sysgen(Parms)
{
cesysgen(); // 执行目录树/oak/misc/cesysgen.bat
nmake();
}
PB如何工作的?(二)
【sysgen变量】
创建一个工程项目的时候就要选择各种功能组件, 每选择一个就设置其对应的sysgen变量等于1, 比如选择ABC后, IDE就会自动设定了环境变量SYSGEN_ABC=1,并且最后会写入工程文件pbxml保存。 所以打开一个工程项目, 就自动获得并设置好了所有选定的sysgen变量。
【树 -- TREES】
编译活动就是把树逐个编译。
之前说过, 树是public下面子目录,一个子目录有可能是就是一个树, 如果是树, 那么树下就会有目录cesysgen, 它下还有makefile文件。除了这些树外,还包括了一颗最大的树:winceos。和一棵项目树, 如下的OSDesign1。
dep trees: winceos dcom gdiex ie script servers shellsdk shell rdp wceshellfe wceappsfe directx voip datasync netcfv2 SQLCE cellcore ostest mediaapps speech FP_VOIP OSDesign1
这片树林是由wince.bat建立的。
编译一棵树是分2个步骤:第一次是preproc, 第二次是postproc。在编译这些树的时候, 如果没有使用“-q”选项, 那么在编译每棵树的时候都会到private和public目录里面去兜一圈, 找到与自己的树名相同的目录, 编译一遍代码。 winceos树对应的是common目录和winceos目录, 里面海量代码大概要编译几个小时。除非自己修改或者补丁 造成的代码更新, 否则还是别那么干吧。 Private目录是可选的, 如果安装pb时候选了share code, 那么就会有private目录,里面全是代码。
winceos是最特别的树, 也是占用我们编译时间最多的。
【细说sysgen过程】
接下来, 就对每一颗树进行sysgen。如下:
Sysgen -p 树名 -b clean preproc/postproc
如果是winceos树, 省略参数 -p 树名。换言之,不带-p参数的话,它的默认树名为common,即winceos。
sysgen过程就2个步骤:1.cesysgen,2.nmake。
1. cesysgen有3个功能, 检查, 报告和设置。检查功能就是检查sysgen变量是不是等于1. 报告功能就是报告当前所有的sysgen变量等。 cesysgen最主要的功能是设置环境变量给nmake使用, 指定需要哪些模块MODULES和组件COMPONENTS。流程是这样的, sysgen首先调用的是项目目录下的cesysgen.bat, 然后它调用位于public/cebase/oak/misc目录下的cesysgen.bat, 然后这个cesysgen按preproc,pass1,pass2步骤来逐个调用位于同一目录下的树名.bat 以及cebasecesysgen.bat, 如果,他们存在的话。
2. nmake失败会导致常见的“error SYSGEN0000: error(s) in sysgen phase”错误提示。不少人拿这个错误来询问原因, 其实这只是个提示,还需要结合日志build.log来检查具体的错误原因,个别情况下,可以考虑修改下makefile辅助调试准确定位错误。
【模块和组件 -- MODULES and COMPONENTS】
http://msdn.microsoft.com/en-us/library/ms924511.aspx
前面说到cesysgen设置变量给nmake处理。 设置些什么变量? 怎么解决模块和组件之间的依赖关系?
一棵树由许多模块组成,