客户端DDK编译环境配置说明
文档主要说明DDK编译环境的部署,如何使用该环境进行客户端代码的编译,环境中一些主要命令、如何扩展一些命令。以及在从VC环境下移植过来后,代码需要改进的一些描述。文章将着重对相关模块下的sources makefile进行描述。
主要分以下五个部分,各个部分的详细叙述请参见各章节。
1. DDK build server的部署
2. DDK环境目录的介绍
3. DDK编译工具和操作介绍
4. 编译过程描述以及tang工程编译分析
5. VC源代码移植一些常见编译错误
6. 一些遗留移植和完善工作
DDK build server是指存在ddk build环境的服务器,可供每个开发人员下载到自己的开发机器,经过简单的配置就能成为本地ddk编译换进的一套机制。DDKbuild server可供公司各个项目组使用,方便的下载,配置并执行编译功能。
目前没有ddk buildserver部署,大家可以从机器192.168.12.103的共享目录中进行下载。
从上图中可以看到红圈标识的几个文件和文件夹,下面一一进行介绍:
Bin目录:包含了对应系统平台下的整个环境的工具和编译命令,已经进行环境设置的bat等。例如:cl.exe,mc.exe,midl.exe,rc.exe包括编译命令build.exe等。
Inc目录:包含了整个环境中的头文件,其中包含的子目录crt,atl,wtl,ddk,api,mfc等包含了各种不同编程框架,crt以及系统sdk的头文件。各个子目录都,对应与相应的环境变量一一对应:
Crt $( CRT_INC_PATH) = ddk下载目录\inc\crt
Sdk $( SDK_INC_PATH)= ddk下载目录\inc\api
Wtl $( WTL_INC_PATH)= = ddk下载目录\inc\wtl80
…
Lib目录:包含了整个编译环境下的所有lib文件(除用户lib),其中包含的子目录atl,crt,mfc,以及不同操作系统对应的库目录。各个子目录与相应的环境变量一一对应:
Crt $(CRT_LIB_PATH)= ddk下载目录\lib\crt\*
Sdk $( SDK_LIB_PATH)= ddk下载目录\lib\wxp\*
…
Src目录:源代码路径,开发人员将需要编译的代码都放在src目录下。
Dir文件:是整个环境非常重要的一个文件,dir中记录了当前文件夹需要编译的子文件夹,并以一定格式组织,作为ddk编译时目录路由的凭证。
所有在dir目录中的文件夹都会被编译,可以通过删除在dir文件中的目录记录来排除编译某个文件夹。
下表列出了DDK环境中的一些工具盒对应处理的文件类型。
Description |
Component |
Consumes |
Build utilities |
build.exe nmake.exe |
sources files, dirs files makefile, makefile.def, makefile.inc |
File that controls the build environment |
SetEnv.bat |
|
Files that identify what is to be built |
dirs, sources, and makefile files |
|
Compiler |
cl.exe |
.cpp files, .c files, .h files |
Linker |
link.exe |
.obj files, .lib files |
Supporting tools |
midl.exe rc.exe binplace.exe stampinf.exe mofcomp.exe |
.idl files .rc files
.inx files .mof files |
Windows Auto Code Review (OACR) tool |
oacrcl.exe, oacrlink.exe |
oacr.ini, oacruser.ini |
其中OACR工具是用来做代码的静态分析,可以帮助我们规范代码,排查一些代码中的问题。
环境的设置:命令行窗口的启动,实际上是使用了以下的一段命令语句:
C:\Windows\System32\cmd.exe /k D:\ddk_build\bin\setenv.batD:\ddk_build\ chk x86 WinXP
这段语句实际打开一个命令行窗口,并且执行Setenv.bat文件从而设置了一系列的环境变量。在目录介绍章节当中提到的环境变量都在这个时候设置好的。
编译过程:build.exe实际执行编译的整个过程,大致过程可表示为:
Scan:扫描工程文件。编译过程的第一步,扫描整个工程中的文件树(dir文件起作用)并且决定是不是进行目标编译。在扫描结束后,Build工具会根据扫描结果,得到目标的类型,以及决定整个编译过程的细节,包括有哪些步骤需要执行比如pass0,pass1,pass2,并且各个过程的参数有哪些等等。总之就是编译任务执行前的所有准备工作。
Pass0:处理源代码。在这个过程中NMAKE会调用一个或多个的工具去处理源代码,比如:
· Microsoft Interface DescriptionLanguage (MIDL) compiler (Midl.exe).
· Other WDK support tools such asthe Stamp INF tool (Stampinf.exe) and Managed Object Format (MOF) compiler(Mofcomp.exe).
· The BinPlace utility(Binplace.exe) to place files.
Pass1:编译obj,lib文件。编译源文件生成object文件和库文件。以下的工具会被调用或可能被调用:
· The C/C++ compiler (Cl.exe).
· The Resource compiler (Rc.exe).
· Other WDK support tools such asthe Stampinf.exe and Mofcomp.exe.
· The BinPlace utility(BinPlace.exe) to place files.
· The linker might be calledthrough the OACR wrapper (Oacrlink.exe).
下表表示了一些在pass1过程中可能产生的一些目标文件:
TARGETTYPE value in sources file |
Description |
Files input to |
Files created by pass 1 |
Is target complete after pass 1? |
LIBRARY |
Static library |
.h, .c, .cpp |
.lib |
Yes |
DYNLINK |
Dynamic link library or user-mode driver |
.h, .c, .cpp |
.lib (import library) |
No |
DRIVER |
Kernel-mode driver |
.h, .c |
.obj |
No |
Pass2:生成最终的目标文件。在这个过程中linker会将pass1中生成的中间文件链接成最终的目标,比如可执行程序,dll,驱动程序等。以下工具会被使用或可能被使用到:
· Linker (Link.exe).
· Resource compiler (Rc.exe).
· BinPlace utility(BinPlace.exe), to place files.
· The linker might be calledthrough the OACR wrapper (Oacrlink.exe).
Binplace文件:在pass0,1,2三个过程的每个结束时,如果我们在sources文件中定义了对应的PASS0_BINPLACE, PASS1_BINPLACE,PASS2_BINPLACE,那么BinPlace.exe都会被调用,并按照sources中定义的规则进行文件的binplace。具体请参见sources文件分析部分。
Tang工程解析
在ddk环境下的编译过程都严格的按照上面的步骤进行编译,下面将列举tang项目中的三个不同类型的工程lib,dll,exe 进行分析,主要是分析工程中的Sources文件。
SOURCES文件用于描述其所在目录下,有哪些文件参与编译,编译的结果应该是什么(是一个lib还是一个sys还是一个可执行程序),输出目录在哪里,要传递给编译器的各种定义和选项分别是什么,等等。由一个SOURCES文件描述的其实就是一个单独的工程,Build最后会参照SOURCES文件的设置,产生一个指定的目标文件(dll ? lib ? exe ?sys ?)完全依赖于SOURCES文件的写法。
CommonLib工程:
TARGETNAME=Commonlib //Lib名称
TARGETTYPE=LIBRARY //指定工程的类型为Lib工程
C_DEFINES= $(C_DEFINES) -DUNICODE -D_UNICODE //指定为unicode编码
MSC_WARNING_LEVEL=/W1 /WX //指定警告错误级别
USE_MSVCRT=1 //使用crt
USE_STL=1 //使用STL
USE_ATL=1 //使用ATL
STL_VER=70 //指定STL版本为7.0
MINWIN_SDK_LIB_PATH=$(SDK_LIB_PATH)
INCLUDES= $(COMMON_DIR)\Inc;\
$(COMMON_DIR)\Support\Inc;\
$(CRT_INC_PATH);\
$(SDK_INC_PATH);\
$(SDK_INC_PATH)\crt\stl70;\ //工程中引用头文件目录
TARGETLIBS= \ //工程中引用的lib库
$(SDK_LIB_PATH)\user32.lib \
$(SDK_LIB_PATH)\Kernel32.lib \
$(SDK_LIB_PATH)\Advapi32.lib \
$(SDK_LIB_PATH)\comctl32.lib \
$(SDK_LIB_PATH)\gdi32.lib \
$(SDK_LIB_PATH)\winspool.lib \
$(DDK_LIB_PATH)\nt.lib\
$(SDK_LIB_PATH)\shell32.lib\
$(SDK_LIB_PATH)\ole32.lib\
$(SDK_LIB_PATH)\oleaut32.lib\
$(SDK_LIB_PATH)\psapi.lib\
$(SDK_LIB_PATH)\msxml2.lib\
$(SDK_LIB_PATH)\shlwapi.lib\
SOURCES=Commonlib.idl \
RegistryFun.cpp\
unzip.cpp\
Util.cpp\
WinObject.cpp\
XmlWrapper.cpp\
zip.cpp\
ElementHelper.cpp\ //需要编译的源文件列表
TARGET_DESTINATION=Target\chk //binplace的目的地址
PASS0_BINPLACE=-:DEST Common\Inc$(OBJ_PATH)\$(O)\$(TARGETNAME).h //PASS0 binplace
PASS2_BINPLACE=$(OBJ_PATH)\$(O)\$(TARGETNAME).lib //PASS2binplace
其中pass0 的binplace使用了:DEST改变binplace的目的地址,如果定义了TARGET_DESTINATION,默认使用该定义的地址为binplace的目的地址。但是可使用:DEST改写该值。但必须严格按照语法进行定义。Pass2使用默认的目标地址。
所以工程编译过程中,在sources的当前目录中生成一些中间文件,有几个是产生的log文件,可以帮助分析编译过程中的一些参数传递和一些错误等。具体生成的中间文件及文件夹如下图,其中在文件夹类似objchk_wxp中生成的是obj,lib,res,manifest等中间文件:
当然最终的目标文件也会生成在那个目录中,但是如果进行了binplace的设置,binplace.exe会将设定的文件移动到目标目录下。
LogDLL工程:
TARGETNAME=LogDll //Lib名称
TARGETTYPE=DYNLINK //指定工程的类型为动态链接库工程
C_DEFINES= $(C_DEFINES) -DUNICODE -D_UNICODE -DWIN32
MSC_WARNING_LEVEL=/W1 /WX
USE_MSVCRT=1
USE_STL=1
USE_ATL=1
STL_VER=60
MINWIN_SDK_LIB_PATH=$(SDK_LIB_PATH)
INCLUDES= $(COMMON_DIR)\Inc;\
$(CRT_INC_PATH);\
$(SDK_INC_PATH);\
$(SDK_INC_PATH)\crt\stl60;\
TARGETLIBS= \
$(SDK_LIB_PATH)\user32.lib \
$(SDK_LIB_PATH)\Kernel32.lib \
$(SDK_LIB_PATH)\Advapi32.lib \
$(SDK_LIB_PATH)\comctl32.lib \
$(SDK_LIB_PATH)\gdi32.lib \
$(SDK_LIB_PATH)\winspool.lib \
$(DDK_LIB_PATH)\nt.lib\
$(SDK_LIB_PATH)\shell32.lib\
$(SDK_LIB_PATH)\ole32.lib\
$(SDK_LIB_PATH)\oleaut32.lib\
$(SDK_LIB_PATH)\psapi.lib\
$(SDK_LIB_PATH)\msxml2.lib\
SOURCES=Log.cpp \
LogDll.rc\
TARGET_DESTINATION=Target\chk
PASS1_BINPLACE=$(OBJ_PATH)\$(O)\$(TARGETNAME).lib
PASS2_BINPLACE=$(OBJ_PATH)\$(O)\$(TARGETNAME).dll
和CommonLib类似,只是target类型不一样。
1. 除AVModule的各业务模块都没有进行移植编译,需要各个模块的负责人进行移植
2. 在移植过程中的一些错误改正,以及OACR检测出的一些警告的修复等。
3. Build client环境的一些自动化设置脚本,已经一些通用的脚本编写,命令扩展工作等。
4. 待补充…