Internal Confidential Document

FlexBuild说明文档

徐艺波 (xuyibo) 2006-05-31

Version 1.9

需求 4

1.1 为什么开发这个环境 4

1.2 开发原则 4

1.3 功能 4

环境说明 7

规范 7

3.1 源码树目录规范 7

3.1.1 源码树结构 7

3.1.2 private目录 9

3.1.3 public目录 10

3.1.4 env目录 10

3.2 .rc文件规范 10

3.3 source文件规范 11

3.4 pack.iss文件规范 13

3.5 readme.txt文件规范 13

3.6 文档规范 15

3.7 FlexBuild环境维护规范 15

3.8 态度问题 15

使用说明 17

4.1 计划阶段 17

4.2 开发阶段 17

4.3 维护阶段 18

内建工具和命令 19

5.1 mksfx  创建sfx自解压包 19

5.2 mksrc – 创建source文件 19

5.3 bak 工程备份 19

5.4 listbak  显示备份的文件 20

5.5 log 20

5.6 build - 编译项目 20

5.7 clean 清除垃圾文件 21

5.8 FlexEditpad 21

5.9 extractor - 文档提取 21

5.9.1 题外话 21

5.9.2 工具说明 22

5.9.3 extractorchmgen参数说明 22

5.9.4 源代码注释结构 23

5.9.5 sample 24

5.9.6 问题? 25

5.10 find, findstr 25

5.11 res 27

5.12 txt2chm 27

5.13  目录跳转 27

5.14 pack 27

参考资料 28

需求

1.1 为什么开发这个环境

使用Visual C++(VC)这样的IDE极大的提高了项目的开发进度,但VC却不适合控制大型项目的编译输出。假如一个公司里有50个工程,现在打算修改某一个编译参数,用VC改怎么办?逐一用VC打开这50个工程,修改参数,编译。Oh! NO! 这太浪费时间,而且还得提心吊胆的他们该不会出错吧!有时,迫于发布,你不得不跳过测试,而直接将这些东西发布给用户。此时:也许上帝保佑或你的伙计们精明能干,没有任何错误、或者发布了一个调试版的、或者发布了一个根本不能运行的。而当你需要频繁的修改编译参数时,你也许会问:难道没有一种更好的解决方案。我的回答是:有,但它不可能是VC

在我开发项目的时候,偶尔有用户需要英文版,我不得不用VC在创建一个工程,然后翻译一份英文资源,编译给用户,最坏的是几乎没一个软件都需要这么做。有时候就连我这个开发者都搞不明白这么多工程哪个是哪个。我此时就想以后一定要简化一下这个步骤。

我在开发Twain USB驱动的空档开始设计这个环境。一开始要什么都是首创的,很难,所以我借鉴了微软的Build开发环境。微软的Build环境非常强大,也非常复杂,可惜这个开发环境更适合开发操作系统,不适合小规模软件公司开发软件。

1.2 开发原则

大的开发原则是:

简单、灵活、严谨

细的原则:

尽量少定义自己的特性

兼容Visual C++ 6.0

最大程度的隐藏复杂度

1.3 功能

支持Windows下所有类型程序的开发
用户态的.exe和.dll、mfc程序等;内核驱动;lib文件等。

汇编语言支持
支持c与汇编的混合工程

自动打包
需要做的是写一个innosetup脚本,格式有规定,这样指向build /p后将执行自动打包,并放到指定的目录下。

版本的自动递增
每次编译一个模块的时候,自动将程序资源文件中的版本信息递增,以便以后出问题时,快速的找到出问题模块的备份代码,并修复之。

代码行数计数
编译是使用/c参数,将统计工程的源码行数。

代码备份
将程序的资源版本和项目名作为.rar备份文件名,并保存在%BAK_PATH%\目录下。在备份前,尽量运行clean.bat来清除垃圾文件。

cvs的支持 
FlexBuild里面包含我自己花了8个小时编译出来的只需要一个文件的cvs,现在你需要的就是从服务器上checkout你的项目源码到private目录,熟悉cvs命令行(这真得很有趣)。

多语言版本程序的开发
通过给资源文件加语言后缀名来支持多语言程序的开发。在开发出中文版后,拷贝出一份英文的,然后翻译资源文件,打开英文的编译环境编译就可以了。在以后修改功能后,使用bcompare工具比较修改资源文件就可以方便安全的开发出新版本的多语言版本。

符号剥离
无论是Release版本还是Debug版本,VC生成的最终文件都包含一些显示内部细节的资料,比如源码的详细路径等等,FlexBuild能够剥离这些信息,让软件更安全

调试版和发布版
调试版使用env目录下的chk_chs.lnk,发布版使用fre_chs.lnk。

预编译头文件内建支持
如果当前源代码目录下有precomp.h文件或stdafx.h,那么把它当作预编译头文件来编译,无须写precomp.c或precomp.cpp,nmake会自动在当前目录下创建此文件。有了预编译的功能,编译C++源代码是非常快的,所以强烈建议C++工程使用预编译头文件。

命令来编译整个源码树
build /s。

编译错误输出
编译完成后,使用log命令来查看。编译错误的工程一目了然。

常用的C++库
支持的库有:WTL、STL、ATL、MFC、BOOST。而且可以方便的增加第三方的库。

丰富的第三方工具全集
在env\bin目录下有着非常丰富的第三方小工具,即使你重装系统,不安装任何其他软件,都可以在FlexBuild环境下写一年的代码(至少得安装个MSDN精简版)。

强大的内建编辑器的支持
FlexBuild有一个非常强大的内建编辑器FlexEdit,比如在FlexEdit中包含一个命令窗口,你可以在这个命令窗口中执行build来编译项目;FlexEdit还支持模板,这样你就不用每次为了符合FlexBuild的文件的编码规范,而来回答从文档中拷贝文件模板了。

和微软DDK build的兼容
FlexBuild使用的描述文件只有source,区别于微软的sources文件。

环境说明

FlexBuild维护了四个主要的目录树。

源码树  d:\dev\private目录下

源码树里,包含项目的代码,文档以及inno安装包脚本等。

发布树  d:\bin\xxx\目录下,xxx代表编译类型,比如中文调试CHK_CHS
源码树编译后,将自动将编译的文件放到这个目录下。如果build制定了/p参数,build还将调用sources文件中的PACK宏,这个宏里面的内容为批处理文件,以sources所在路径在当前路径。

备份树  e:\backup\dev\目录下
在源码树中,执行bak命令,将把此项目下的所有代码安装相对于d:\dev放置到e:\backuk\dev目录下。如果指定了/p参数,最终的打包文件也将放到这个目录下。

SDK树  d:\dev\public目录下
SDK树主要放发布给用户或内部共享的动态库头文件和.lib文件。

规范

3.1 源码树目录规范

3.1.1 源码树结构

dev

  +--private               项目源代码目录

       +--hvperf            项目目录

            +--doc          文档目录

                  +--pack 用于程序的打包目录

                  hvpef.chm  extractor提取的代码注释文档

                  hvperf 项目需求文档.doc

                  hvperf 项目设计文档.doc

                  hvperf 项目开发文档.doc

                  hvperf 项目修改文档.doc

            +--ide          IDE工程文件目录,VC工程的创建的位置

            +--res          工程资源文件

                  hvperf_chs.rc     简体中文资源文件

                  hvperf_eng.rc     英文资源文件

            +--tst         测试单元和功能测试代码

            sources 项目编译描述文件

readme.txt   txt2chm工具生成文档

       +--raw2rgb

            +--doc

            +--ide

            sources

  +--public                公司内部公共的头文件、库

       +--inc               共享的.h文件

       +--lib                共享的.lib文件

  +--env                   工具、快捷方式和规范文档

+--sdk               微软的SDK

           +--asm     SDK 汇编头文件

           +--atlmfc     ATL, MFC库头文件

           +--crt     C运行库头文件

           +--winddk     DDK 头文件

           +--winsdk SDK 头文件

           +--wtl WTL 库头文件

+--doc             规范文档目录

+--lnk 用户自定义的程序、工具目录

       +--tmp tmp目录

       +--template         各种文档、代码模板

+--tools             编译器、连接器等工具

buildlog.htm 编译输出文件

       chk_chs.lnk              中文调试版编译环境

       fre_chs.lnk               中文发布版编译环境

       chk_eng.lnk 英文调试版编译环境

       fre_eng.lnk 英文发布版编译环境

+--web 发布网站目录

       +--Local 目前仅支持本地web方式更新发布数据库

    +-- binaries.mdb 程序版本目录等发布的详细信息数据库

 

binaries                  编译输出目录

       +--CHK_CHS 中文调试版本输出目录

              +--hvperf

              +--raw2rgb

  +--symbols WinDbg使用的symbols目录

        +--CHK_ENG 英文调试版本输出目录

+--FRE_CHS 中文发布版本输出目录

+--FRE_CHS 英文发布版本输出目录

3.1.2 private目录

尽量让【private】目录集中了所有的项目源代码,这样设计是为了方便实现源代码与FTP服务器或备份目录之间的Check-InCheck-Out

每个项目都必须有一个sources文件,一个目录下最多只能有一个项目。如果一个目录下需要生成多个项目(比如参数不一样,生成多个版本的程序),那么必须创建子目录,在每个子目录中创建sources文件,然后在父目录下也创建一个sources文件,里面指定DIRS=宏,指定需要编译的目录名。详细信息,请参考sources编码规范。

当创建一个项目后,要保证所有的需要的东西多在这个项目目录及其子目录下。一个命令build /s /p,就能打包出最终的项目输出,而不需要到处寻找拷贝文件。

一份代码只维护一份,不要到处拷贝。

3.1.3 public目录

public】目录放置本公司共享的头文件和库。如果以后需要发布SDK的话,也是从这个目录提取。lib目录中的内容是伴随private动态库的升级而变化的,一般在sources文件中指定/implib:$(LIBPATH)\XXX.libinc目录中的文件需要手动修改。

3.1.4 env目录

开发环境成功安装后,【env】目录中的内容很少变化,所以最好将这个文件夹设置为只读隐藏,以避免许多勿操作或用错误命令时勿删除。(我就用错过两次,用了的是delnode命令行,这个工具不支持中文,当我删除一个中文文件夹时,结果它把我的这个盘的所有资料给删了,不幸啊!)。建议将chk_chs.lnkfre_chs.lnk拷贝到桌面上。

3.2 .rc文件规范

估计版本的完美解决方案,是这个开发环境中的一大优点。你需要做的就是在sources文件中指定:

TARGET_VERSION=1.0.6

TARGET_DESCRIPTION=DaHeng Image Vision XXXXXX

由于资源文件已经高度抽象,你不需要在sources文件中指定任何资源信息,也对VC生成的资源做任何修改。你需要做的就是将正确的资源文件创建在正确的位置

正确的资源文件意思是:

资源文件的名称为:(项目名)_(语言缩写).chs

目前,只支持两种语言的编译环境:中文和英文,如果以后需要可以在扩展。中文的语言缩写为CHS,英文的为ENG。

正确的位置有二:

项目.\res目录

项目根目录下

例子:

假如现在要创建HVPERF工程的中文资源文件:你可以创建HVPERF_CHS.RC在.\res\目录下,或创建在.\目录下。一般在项目包含许多资源,比如位图、图标等等时,为了便于保持源代码目录的简洁干净,我们一般会将所有资源文件都存放在项目.\res\目录下。

版本信息模板:

主版本 次版本 编译次数 编译类型

主版本:主版本为1-9之间的数字。

次版本:次版本同主版本一样,请手动修改次版本。

编译次数:编译次数有编译工具来控制,每次编译代码时编译次数自动递增1,除非编译是指定/F(fixedness)参数。

语言:编译类型用来确定编译的类型,2052为中文,1033为英文。

在sources文件中,TARGET_VERSION用来指定版本信息,结构为:主版本.此版本.编译次数。其中编译类型不需要指定,它会由Build工具根据开发环境变量%BUILDTYPE%自动设置。

3.3 source文件规范

运行mksrc命令,将自动为当前目录创建一合适的sources文件。

sources模板如下:

#

# TARGET_NAME 指定含有扩展名的编译输出文件。后缀名可以为.exe, .dll, .sys,其它后缀名的,都将

按照编译dll的参数来编译。

#

TARGET_NAME=XXXXXX.exe

#

# 用来指定文件属性中版本中的文件描述信息,注意不要换行。

#

TARGET_DESCRIPTION=nsfocus information technology XXXXXX

#

# 用来指定项目用到的字符集。Target character sets,默认用的是MBCS(多字节字符集)。它允许的值

# 有:

#  MBCS      -多字节字符集,默认

#  UNICODE  - UNICODE程序

#  SBCS      -  单字节字符集,很少使用。

#

TARGET_CHARACTER=MBCS

#

# 指定连接的运行库。

#  MSVCRT为动态连接msvcrt.dll

#  LIBC静态连接单线程的C运行库;

#  LIBCMT静态连接多线程的C运行库;

#  MFCDLL为使用MFC42.DLL动态库;

#  MFCSTATIC为使用MFC静态库。

#

TARGET_RUNTIME=LIBC # MSVCRT, LIBC, LIBCMT, MFCDLL, MFCSTATIC, NONE

#

# 指定编译器参数。

#

TARGET_COMPILE=

#

# 指定连接器参数。注意许多参数都已经有开发环境自动设置好了。对于dlllib模块,编译输出会自动

放置到public\lib目录下,对于动态dll输出文件名称为xxx.lib;对于lib,输出文件名debug版为xxx_sd.lib

# release版为xxx_s.lib,如果你的某个工程需要引用某个静态版本可以在TARGET_LINK参数中指定:

# xxx$D.lib(这里的$D意思是指debugrelease对一种后缀)。

#

TARGET_LINK=

#

# 指定源代码,注意这里只包含.c.cpp.cxx源代码文件,其它任何文件都不应该放在这里。如果

源代码不在根目录下,必须使用/来替代目录标识\,应为标识\已经被nmake用作标准Token了。

#

TARGET_SOURCE=foo.c \

           ../cam/fooo.c \

           mm.c cc.c

#

指定在编译项目前执行的命令。比如,如果项目用到.mc资源,那么就可以在这里调用mc来先编译

之,这个宏总是执行的。如果没有指定这个宏,那么build将生成一个默认的不含任何命令的宏。

#

TARGET_PRE:

COMMAND

#

指定在项目编译完成,binplace也执行完成后,执行的命令。比如,binplace将编译的文件放置到输出

目录后,可能需要将doc\pack目录的帮助文件也打包到输出目录,那么就可以使用命令:

# copy /y doc\pack\help.chm $(TARGET_PATH)

其中,$(TARGET_PATH)就是程序的输出目录,可以通过设置env\bianries.mdb Access数据库来修改

程序的输出目录。

#

其中,最有用处的命令要算:pack $(TARGET_PATH) 它的作用非常强大,实现自动打包,打包好的程

序在env.batPACKDIR定义的路径下。

#

TARGET_POST:

    COMMAND

3.4 pack.iss文件规范

FlexBuild内建了安装脚本功能,你需要做的就是,拷贝pack.iss到项目doc\pack目录下,修改里面的:

[CustomMessages]

TARGET_NAME=MyProg

TARGET_FILE=MyProg.exe

然后,在source文件中的PACK:下添加:

Pack $(TARGET_PATH)

默认情况下,安装程序包含中文和英文两种安装界面。

为了总体的设计目标,我必须在简单和灵活之间做一下抉择。所以在经历了无数次的思考后,我还是决定,不再实现自动的安装脚本。

3.5 readme.txt文件规范

readme是给备份工具bak、txt2chm、安装脚步使用的。以便在代开备份文件后就能看到这个版本包含什么样的功能特性等。注意这个文件是给内部看的,主要目的就是为了以后某一个版本出问题时,提供一份替代版本参考资料。readme还有一个好处就是,便于追寻bug是在哪个版本中引入的。在使用bak来备份软件时,它会提取sources里面的版本信息,并将它连同项目名构成形如:

XXX_2.0.10.rar

的备份文件。如果没有提取到版本信息,那么bak将使用当天的日期来替代版本,备份名如:

XXX_2006-6-12.rar

readme.txt只在发布某一版本软件的时候才添加记录,里面包含此版本不同于上一次readme.txt记录版本的新特性。编译发布产品后,必须使用bak命令在备份整个项目。

备份的目的是为了以后万一出了问题的时候,还原工程。虽然这样浪费了点硬盘空间,但我们备份的只有代码,所以备份后的文件还是挺小的。备份的目的文件夹也是按照工程名分开的,位于%BAK_PATH%\工程名下。我是一个很挑剔的人,我很不希望浪费任何的硬盘空间,但我还是设计了备份功能,毕竟什么事情都可能发生,我们无法预测未来,但我们可以尽量让灾难造成的损失降到最低点,备份就是一个不错的法子,而且这些备份记录也是公司的宝贵财富,它也是公司技术积累的一部分。还记得911事件吗,时候有些媒体就说,如果世贸大厦里的许多公司没有做备份,那么他们的损失将会更加严重。

//

// 项目名称:XXXXXX

// 项目成员:全名 (Email) --

//

1. 项目简介

XXX--------------------------最多76个字符------------------------------------XXX

2. 版本记录

[版本(最新的记录放在最前面)

XXX--------------------------最多76个字符-------------------------XXX [作者 日期]

例子:

//

// 项目名称:Bayer变换优化

// 项目成员:徐艺波 (xyb) 2006-06-02

//

1. 项目简介

   优化Bayer变换,以提高Bayer变换在速度慢的机器上的速度。

2. 新增功能

[1.0]

用汇编重写了fast算法 [xuyibo 2006-06-03]

[1.0]

inline方式优化了部分代码。 [xuyibo 2006-06-03]

3.6 文档规范

文档包含:

需求文档、设计文档

开发文档

维护文档

详细信息见公司的文档规范。

3.7 FlexBuild环境维护规范

所有的代码以一台机器上的为主,尽量不要今天在这台机器上,明天再另一台机器上编辑代码,主与辅的关系不要打乱。

每次产品提交都要在FlexBuild环境中自动实现,而且每次提交都要备份该版本的源码。

每次修复bug提交到cvs前,先使用cvs diff来进一步确认一下是否改动的正确,避免引入其他的一些低级bug

3.8 态度问题

不论你是否相信,态度几乎决定了一切。我很钦佩德国人那种严谨的作风,当你看到德国城市那种整齐干净的氛围,你不得不说,生活在这里的人是多么的伟大。激情或梦想的确能够促使产品的诞生,但态度却是人内心的东西,那是一种习惯。

认真、稳重、谨慎

制定规则不难,难的是严格的执行

对事不对人

休息时好好休息,工作时认真工作

在没有了解程序结构之前,不要修改任何代码。

做好与会做是两个不同的世界

从底层把握功能实现,而不总是去尝试着失败

使用说明

4.1 计划阶段

编写需求文档

编写设计文档 (设计用户界面和接口)

在开始写代码前,请认真的研究需求,然后作出设计,一般设计时间将占整个项目开发时间的四分之一左右。在这一阶段:我们要完成软件的需求文档、软件难点的测试程序、软件接口的定义等等。并将这些文档存放在项目目录【doc】文件夹里。公共软件接口发到public\inc目录下。

这一阶段主要是有项目经理完成的,项目经理在了解了客户的需求,开会讨论,最终写出需求文档。需求文档一般有最有经验的程序员编写,目的就是保证需求文档的稳定性。需求文档一旦编写完,要经最终用户确认,一致同意后,便封存需求文档。除非上级批准允许修改,否则决不能擅自改动需求文档。

需求文档出来后,再按照需求文档编写设计文档,里面设计到软件接口以及用户界面设计,及其流程图。这也是有最有经验的程序员来担当。如同建筑师的设计一样,按照用户提出的需求,设计出建筑的蓝图。一旦完成,讨论通过后,封存。除非项目经理批准允许修改,否则决不能擅自改动需求文档。

4.2 开发阶段

按照设计文档编写代码

记录开发文档

测试并写测试程序

进入编码阶段,所有的接口都必须严格按照需求文档中定义的来编写。任何改动都必须经过项目经理确认后才可以修改,同时在需求文档中【设计修改】里添加改动的内容、日期等等。

开发时,肯定会遇到一些难题,解决这些难题,能极大的提高我们的开发设计水平,而伴随开发写一份开发文档是一个不错的主意。里面记录着解决这个问题的方法,以及自己的观点等等。

dev, private, public, env, inc, lib, bin, ide, doc, tst都是标准目录名
为了便于小组内各个成员的协作,请不要修改这些标准目录的名称和位置。如果需要扩展标准目录,请跟项目经理讨论后在做决定。

对于动态库,导出保证运行extractor用来后能提取出所有导出给用户的chm文档。尽量将需求文档中定义的接口用动态库来实现。

如果你使用IDE工具来开发,比如Visual C++,那么请将项目创建在项目ide目录下。FlexBuild默认的编译输出文件也在ide目录下。这样做的目的是便于clean工具清理垃圾文件。

小的项目,一般还是有项目经理负责主要的编码工作;对于大的项目,项目经理负责控制这个项目的进度、人员的分工、难点的解决等,主要的编码工作主要有项目成员完成的。测试单元的编写要伴随着开发过程,边开发边测试。一般黑盒测试可以有文档编写人员来完成,白盒有内部项目成员的专门测试人员(如果有的话),或资深工程师来担当,但无论如何,要保证开发人员和测试人员不是同一个人。说到这里,我们也许会有一个疑问:如果把最资深的工程师用来测试的话,是不是降低了生产率,的确,但这样也是在培养小组中其它人的技能,最终提高整个项目小组的开发水平。

4.3 维护阶段

维护doc目录下的维护文档

解决软件bugs和更新软件

维护好历史版本的更新记录

发布的时候,修改发布软件的主模块(.exe工程)的sources文件的PACK宏为:

PACK:

    pack $B

然后执行命令:build /f /p,来发布。发布后,打包的程序将在目录: e:\release下,测试通过后,发布。

稳定阶段,主要参与者是用户,用户通过反馈来决定自己开发的产品是否符合用户需求、是否有bugs等等。这一阶段,我们要保存每一次发布产品源码和发布包的备份,以便以后出现问题后追溯。

内建工具和命令

开发环境内建了许多辅助工具和命令,熟悉她们会助你一臂之力。

6.1 mksfx  创建sfx自解压包

相关文件:微软的cabsdk

Compress\selfext下的工程

用法:mksfx [stub application] [outputfile]

6.2 mksrc – 创建source文件

根据当前目录的情况创建合适的sources文件。首先如果当前目录下存在(项目).def文件,那么mksrc将认为这是一个动态库工程;否则是一个可执行文件工程。一般创建的sources文件都可以正确运行的。

如果当前目录下,已经有mksrc文件了,那么mksrc会提示你是否覆盖当前文件。创建完文件后,使用“type sources”命令来显示创建的sources文件内容。

CUI, 必须采用main为入口函数,尤其是汇编

GUI, 必须采用WinMain,下面是一个列表:

CUI

main

GUI

WinMain

Dll

DllMain

Sys

DriverEntry

其他

LIB, MFCSTATIC

其他

MFCSTATIC

6.3 bak 工程备份

备份当前目录下的文件到%BAKDIR%目录下,默认为e:\bak,你可以在%BASEDIR%\env\env.bat文件中设置此变量的值。一般建议将备份工程目录设在不同于开发盘的盘上,这样可以避免备份资料免受开发盘误操作而丢失。

如果当前目录下有文件sources并且包含一个有效的TARGET_VERSION宏,那么bak工具使用项目名和版本信息来备份文件。否则将使用项目名和当前日前来备份文件。

下面是一些备份出来的文件名称:

dev_2006-06-09.rar

matrix_1.0.168.rar

private_2006-06-09.rar

6.4 listbak  显示备份的文件

listbak显示相关的%BAKDIR%路径下的备份文件,其命令行如下:

/A 显示所有的备份文件(*.rar)

/D 显示备份文件大小的详细信息

/H 详细listbak命令行帮助

/S 搜索备份子目录下的相关文件

6.5 log

打开编译记录,网页形式的,其中编译错误的用红色标识;正确的用绿色。

6.6 build - 编译项目

在当前目录下枚举所有编译项目,并逐一编译。

不同于微软有单独的DIRS文件,我在设计时,为了追求简单,在1.03版本中,我将DIRS宏写在sources文件中,Build在编译前先枚举sources目录下的DIRS宏,并生成一份编译目录,保存在%BASEDIR%\env\build.dat文件中,然后依次编译每一个目录,编译完成后生成一份编译结果日志%BASEDIR%\env\build.log,里面包含每个工程是否编译成功、编译花费的时间以及总的花费的时间。

在编译每一个工程后,Build也会用红色来显示编译错误的工程,我借鉴了红绿灯的颜色,呵呵!

Build的命令参数如下:

/C
重新编译这个项目,而不检查文件是否过期。

/0
只枚举目录树而不编译链接。

/F
编译源码树的时候,不递增每个项目的版本。

/P
编译后,自动执行TARGET_POST里的批处理,并更新pack.iss安装脚本如果存在的话。

/S
编译子目录。

/R      Reserved
保留Build生成的中间文件。

每次编译后,可以使用log命令来显示编译的结果。

6.7 clean 清除垃圾文件

clean.exe自动清除当前目录以及子目录下的所有debugrelease目录。Clean命令参数如下,参数可以用-/\

-F[ext;ext;ext] 
指定要删除的文件后缀名,如果不指定-F参数,那么clean工具在删除完目录后,不做任何删除文件的操作。

如果为了方便,你可以使用clean.bat命令,它将清除清除所有VC和开发环境生成的垃圾文件。改批处理文件的内容如下:“clean.exe /F.plg;.opt.ncb.ilk” 

6.8 FlexEditpad

  FlexEdit是基于Programmers Notepad修改而成的FlexBuild内建的代码编辑工具,功能非常强大,当然目前还有许多需要更新的地方。我引进打算不再做大的修改,如果你有什么需求,可以同我联系。

  pad是基于Notepad2编译的FlexBuild内建的notepad的替代代码编辑工具,简洁、快速。

6.9 extractor - 文档提取

6.9.1 题外话

在工具说明之前,我先唠叨几句为什么开发这个工具,有耐心的请继续:我看过NT内核代码,也看过Linux的内核代码,其间的差别我就不说了,大家可以看看SAMPLE目录下的WAIT.C,一份从NT内核源码中提取出来的模块。

6.9.2 工具说明

WinExtractor 是一个代码注释提取器。它能够提取源代码中符合规格的注释以及函数说明,生成htm网页文件。

   生成的文档格式非常类似MSDN中的文档,当然比MSDN要简洁的多,也漂亮的多(我自个这么认为∵)。最后WinExtractor自动讲生成的网页文件制作成一个.chm的帮助文件。目前生成的文档模板还不能定制,如果未来有必要,我再添加这部分的功能。

整个代码提取工具由三个部分组成:WinExtracotor.exe, extractor.exe, chmgen.exe。还有几个动态库,其中只有matrix.dll是我写的,其中里面包含一些目录枚举迭代的导出函数。

WinExtractor.exe

带界面的代码提取工具。

Extractor.exe

基于命令行的代码提取工具。

Chmgen.exe

.chm文档生成工具。

用户使用WinExtractor设置合适的参数后,WinExtractor调用ExtractorChmGen来完成代码文档的提取工作。WinExtractor暂时还没有完全包含ExtractorChmGen的所有功能,ExtractorChmGen的命令行参数也没有最终稳定下来,我也在不断努力让这几个工具更协调的工作。

6.9.3 extractorchmgen参数说明

Extractor:

/nologo no logo 不显示版权信息

/D:[输出目录] document 文档输出目录

/S subdirectory 搜索子目录。

/P:[ext;ext] Process 处理文件的后缀名,默认为.c.cpp

/G Group 将一个文件中提取的所有函数说明放到一个.htm文件中。

/? help 显示帮助

/R Reserved 保留所有生成的.htm文件。

Tag:[ ; ; ] tag 设定搜索标识,默认为\f;/*++;--*/

Chmgen

/I Index 生成索引

/L:[listfile] List 指定生成.chm的所有.htm文件相对路径

6.9.4 源代码注释结构

/**/

int

func (

    IN  int nV1,

    IN  int nV2,

    OUT intpV 

    )

/*++

Description:

    /*++--*/之间的文档内容,WinExtractor 简单的测试有以“:”结尾的字符串。如果有,那么粗体显示它。WinExtractor 不会做其他任何的修改。

Arguments:

    IN int nV1,输入的整型参数,有效值范围0~255

    IN int nV2,输入的整型参数,有效值范围0~255

    OUT int× pV,输出的整型参数,有效值范围0~255

Return Value:

    0,计算正确,结果存放在pV

    -1,参数超出范围,*pV的内容没有改变。

--*/

{

// ……

// 函数实现,winextractor不关心里面的内容,除非它含有上面红色的Token

// ……

}

红色的为WinExtractor的搜索标识。WinExtractor将把/*++--*/中的内容作为函数的说明输出到网页中,同时在/**//*++之间的函数头也将被格式化后输出。

/**/, /*++, --*/是可以改变,默认情况下WinExtractor所有的设置都是按照微软的NT内核编码规范来设置的,所以,要符合大恒图像的编码规范应该将WinExtractor中的【生成】-【设置】中的搜索标识中改为:/**/;/*++;--*/

目前搜索标识之间的内容还不能自定义,也就是说/**/之后必须是函数定义,这可能不太符合我们的过去的编码风格(通常我们会把注释写在函数定义之前)。我也一直在思考为什么微软采用函数定义之后写注释的原因?现在我想:将注释写在函数定义之后更规范,跟标准化。这种写法会让你会更关注函数的接口,而不是实现,毕竟从用户或使用的角度看接口比实现更重要。

如果以后需要,我将添加功能以让用户指定文档注释的位置(在函数头前面还是后面)。

6.9.5 sample

运行WinExtractor,设置代码目录和输出文档目录:

然后点击生成即可。

或者在命令行下:

cd /d d:\extractor  // if you extract archive to d:\extractor

extractor sample

这样extractor自动会将提取的文档放入当前目录(d:\extractor\doc)文件夹下,而且自动删除生成的.htm文件。如果需要保留网页文件,请加入/R参数。

6.9.6 问题?

1. 有必要每一个函数都符合这个规范吗?

的确没有必要。WinExtractor是面向底层代码模块而开发的。 所以如果是类似“Hello World”的程序的确没有必要符合这个规范,毕竟此时我们关注的不是接口,而是测试。

6.10 find, findstr

微软xp下的两个命令行工具,用于查找字符串。

[find]

FIND [/V] [/C] [/N] [/I] [/OFF[LINE]] "string" [[drive:][path]filename[ ...]]

  /V         Displays all lines NOT containing the specified string.

  /C         Displays only the count of lines containing the string.

  /N         Displays line numbers with the displayed lines.

  /I         Ignores the case of characters when searching for the string.

  /OFF[LINE] Do not skip files with offline attribute set.

  "string"   Specifies the text string to find.

  [drive:][path]filename

             Specifies a file or files to search.

If a path is not specified, FIND searches the text typed at the prompt

or piped from another command.

[findstr]

FINDSTR [/B] [/E] [/L] [/R] [/S] [/I] [/X] [/V] [/N] [/M] [/O] [/P] [/F:file]

        [/C:string] [/G:file] [/D:dir list] [/A:color attributes] [/OFF[LINE]]

        strings [[drive:][path]filename[ ...]]

  /B         Matches pattern if at the beginning of a line.

  /E         Matches pattern if at the end of a line.

  /L         Uses search strings literally.

  /R         Uses search strings as regular expressions.

  /S         Searches for matching files in the current directory and all

             subdirectories.

  /I         Specifies that the search is not to be case-sensitive.

  /X         Prints lines that match exactly.

  /V         Prints only lines that do not contain a match.

  /N         Prints the line number before each line that matches.

  /M         Prints only the filename if a file contains a match.

  /O         Prints character offset before each matching line.

  /P         Skip files with non-printable characters.

  /OFF[LINE] Do not skip files with offline attribute set.

  /A:attr    Specifies color attribute with two hex digits. See "color /?"

  /F:file    Reads file list from the specified file(/ stands for console).

  /C:string  Uses specified string as a literal search string.

  /G:file    Gets search strings from the specified file(/ stands for console).

  /D:dir     Search a semicolon delimited list of directories

  strings    Text to be searched for.

  [drive:][path]filename

             Specifies a file or files to search.

Use spaces to separate multiple search strings unless the argument is prefixed

with /C.  For example, 'FINDSTR "hello there" x.y' searches for "hello" or

"there" in file x.y.  'FINDSTR /C:"hello there" x.y' searches for

"hello there" in file x.y.

Regular expression quick reference:

  .        Wildcard: any character

  *        Repeat: zero or more occurances of previous character or class

  ^        Line position: beginning of line

  $        Line position: end of line

  [class]  Character class: any one character in set

  [^class] Inverse class: any one character not in set

  [x-y]    Range: any characters within the specified range

  \x       Escape: literal use of metacharacter x

  \<xyz    Word position: beginning of word

  xyz\>    Word position: end of word

For full information on FINDSTR regular expressions refer to the online Command Reference.

6.11 res

这个工具原自:http://www.resedit.net/网站上的resedit.exe,一个用来编辑资源文件的轻量级的工具,可以代替VC带的资源编辑器。由于这个软件还存在bug,慎重的使用。

6.12 txt2chm

  如果当前项目包含readme.txt,那么就可以使用txt2chm工具生成chm格式帮助。这个命令已经被doc命令包装起来,最好直接调用doc命令来生成文档。

6.13  目录跳转

跳到经常使用的文件夹去。比如输入:g bin,将跳转到d:\binaries目录下

参数

目录

展开后

private

%BASEDIR%\private

d:\dev\private

public

%BASEDIR%\public

d:\dev\public

env

%BASEDIR%\env

d:\dev\env

tools

%BASEDIR%\env\tools

d:\dev\tools

bin

%BINPLACEDIR%

d:\bin

inc

%BASEDIR%\public\inc

d:\dev\public\inc

lib

%BASEDIR%\public\lib

d:\dev\public\lib

sdk

%BASEDIR%\env\sdk

d:\dev\env\sdk

bak

%BAKDIR%

e:\backup\dev

6.14 pack

  pack是是个脚本,它在检测当前目录doc\pack目录下是否包含pack_%LANG%.isspack.iss后来决定是否需要打包。这也是我集成innosetup的地方,你需要做的就是,拷贝env\template pack.iss文件到当前目录,修改里面的安装脚步,然后在sources文件中修改TARGET_POST宏:

TARGET_POST:

    pack $B

参考资料

微软Build开发环境
非常棒的开发环境,微软资深元老Steve Wood编写。

Watcom C编译器开发环境
现在已经开源的编译,里面有自己的编译环境,我没有仔细看,我主要从这里找到了非常完整的各大CPU厂商的文档。

Visual C++ 6.0 Export makefile
在自己不熟悉makefile,和VC如何编译的时候,这里给了许多参考。

Debugging the Development Process
微软的资深项目经理史蒂夫.马魁尔的经典书,关于项目管理方面看过的最好的书。

编辑器:UltraEdit、editplus、textpad、wscite、visual studio、programmers notepad、notepad++、notepad2
ed是FlexBuild的内建的首选的编辑器,FlexEdit 的开发过程中借鉴这些编辑器。