一直以来,Delphi 都可以用命令行 dcc32 ProjectName.dpr 对项目进行编译链接,非常方便,Delphi对项目文件的参数配置处理的很简单,便于阅读处理起来也很直观,编译的中间文件也很简单(dcu,dcp)。
而C++Builder就没那么幸运了,因为包含了C++的特征,各种编译的中间文件:lib,obj,res,map,tds。后来新版又增加了一些预编译文件:ilc,ild,ilf,...,pch,#00,...等等等等,各种搜索路径(Include Path,Library Path,Browse Path...),要是用bcc32及ilink32手工进行编译链接,命令的参数都足够写上大半天。幸好,在旧版C++Builder中,如果要用命令行编译BCB项目,只要将bpr文件转换为mak文件,再使用make命令进行编译链接也比较方便,不需要过多的处理:
bpr2mak -oProject1.mak Project1.bpr
make -fProject1.mak
自从Delphi/C++Builder开始使用 MSBuild* 编译系统后(好像是RAD Studio 2006开始,具体忘记了),Delphi项目在保存为dpr的同时,也会保存一份dproj的项目文件,dpr依旧沿用旧格式,dproj 则以MSBuild规范以XML格式保存,除了可以用旧方式命令行编译dpr外,也可以用:
msbuild.exe /t:Rebuild /p:Config=Debug ProjectName.dproj
进行编译,但msbuild必须设定一些环境变量,RAD Studio自带了一个命令行工具已经做好了这些,其实就是设定了以下几个环境变量($(BDS)\bin\rsvars.bat):
@SET BDS=C:\Embarcadero\RAD Studio\7.0
@SET BDSCOMMONDIR=C:\Users\Public\Documents\RAD Studio\7.0
@SET FrameworkDir=C:\Windows\Microsoft.NET\Framework\v2.0.50727
@SET FrameworkVersion=v2.0.50727
@SET FrameworkSDKDir=
@SET PATH=%FrameworkDir%;%FrameworkSDKDir%;%PATH%
@SET LANGDIR=EN
C++Builder则又更杯具了一些,bpr2mak.exe工具已经没有了,所以只能采用MSBuild进行命令行编译。更加杯具的是,随着Delphi和BCB被多次转卖收购,新版本的发布似乎总会有各种各样的Bug,比如手头的RAD Studio 2009进行命令行编译,Delphi正常,BCB则报出超过100个错误,类似如下:
C:\Embarcadero\RAD Studio\7.0\Bin\CodeGear.Cpp.Targets(2175,3): error : Error: Unresolved external '__fastcall Strhlpr::UnicodeFree(System::UnicodeString&)' referenced from C:\EMBARCADERO\RAD STUDIO\7.0\LIB\DEBUG\VCLE.LIB|ustring
C:\Embarcadero\RAD Studio\7.0\Bin\CodeGear.Cpp.Targets(2175,3): error : Error: Unresolved external 'Typinfo::BooleanIdents' referenced from C:\EMBARCADERO\RAD STUDIO\7.0\LIB\DEBUG\VCLE.LIB|vclinit
检查了一下发现编译过程(bcc32.exe)没有问题,只是在ilink32.exe链接过程中报错,在IDE中打开此项目进行编译,查看Message->Output窗口,比较两者的ilink32命令行参数,发现两者有两个地方有明显差异,一个是IDE生成的命令中没有类似 C:\Embarcadero\RAD Studio\7.0\lib\EN\debug 的路径(指的是EN这个目录,去除上面rsvars.bat中的@SET LANGDIR=EN 就可以避免产生这样的搜索路径) ,但是虽然这个目录不存在,也应该不至于导致出错。第二个差异是缺少了rtl.bpi和vcl.bpi的附加obj参数,解决办法是在$(BDS)\bin目录中找到 CodeGear.Cpp.Targets 文件,用记事本打开,搜索字符“memmgr.lib“,在前面加上"rtl.bpi;vcl.bpi" (用;分隔,不含引号),一共有两处要修改。或者查找 "c0w32",在后面加上 "rtl.bpi;vcl.bpi",只有一处修改 —— 因为IDE的命令行中 rtl.bpi vcl.bpi是在c0w32和memmgr.lib中间的。—— (注意:在XE2中,加在c0w32后面已经不管用了,编译会报另一个错误VCL.BPIW.OBJ不存在,Targets文件有很大变化,可能参数的位置变动过了,导致与其他参数混在一起,所以还是加到memmgr.lib处更加合理)。
一些组件包比如DevExpress的Package,没有dproj或者cproj 项目文件,只能通过IDE进行转换,但坑爹的是bpk在好几个版本以前(CRS 2007?)已经不支持bpk项目,根本打不开也谈不上转换了,但它其实是一个make文件,可惜用make命令编译还是要出错,不想去研究了。总之,BCB永远活在Delphi的阴影下。
(*注:MSBuild其实是一个批处理工具,并非编译器,类似于Make命令,详情请Google)
WIKI参考:
http://zh.wikipedia.org/wiki/Delphi
http://zh.wikipedia.org/wiki/C++Builder
附RAD Studio XE2 (Update1)测试结果:
编译 | 项目 | 结果 |
Delphi | VCL Application —— Project1.dpr,Project1.dproj | msbuild 编译 dproj 一次成功,dcc32 编译 dpr 第一次不成功,报缺少Project1.res,原因是新工程没有res文件。 而且在新版RAD Studio中采用了新的资源处理方式,IDE会产生一个临时的 Project1.vrc 文件,通过 cgrc.exe -c65001 Project1.vrc -foProject1.res 来得到res文件 |
Delphi | VCL Package —— Package1.dpk,Package1.dproj | 结果同上,dcc32编译需要有 Package1.res 文件,注意,新版Delphi Package允许同时产生BCB所需要的文件,即选项:Generate all C++Builder files (including package libs),但是dpk文件无此选项,所以用dcc32编译后的bpl文件只能供Delphi使用 |
C++Builder | VCL Application —— Project1.bproj | 直接编译失败,修改CodeGear.Cpp.Targets增加rtl.bpi;vcl.bpi在memmgr.lib前再编译,有两处警告:提示 Path 'Windows\vcl' not found,检查IDE的环境变量,发现多出了BDSINCLUDE和BDSLIB两个,加入到 rsvars.bat 中,再编译无警告。看来Embarcadero的开发者们忘记了更新 rsvars.bat 。还有就是如果不用/t:BuildAll 参数,第二次编译出的程序没有图标,界面也没有样式,这应该是XE2的BUG,在IDE里也是一样,希望能在Update2里得到解决。 |
C++Builder | VCL Package —— Package1.bproj | 结果同上 |