转载自
这几天刚好要做一个决策支持系统软件的框架搭建,看到网上一些较好的资料整理了下,给大家分享。
一、Visual Studio 项目的文件组织方式
VC6.0之后的VC (VS)系列使用解决方案(Solution)来替代原来的工作空间,用于组织和管理多个相关的项目(Project)。VS中的每个管理器(解决方案或项目)都会对应一个总的文件夹,这个管理器文件夹下存放本管理器的配置文件以及子管理器。以C#项目为例,解决方案管理器总文件夹下包含解决方案配置文件*.sln和项目子管理器文件夹,而项目子管理器文件夹下包含C#源文件*.cs、项目配置文件*.csproj、Properties属性文件夹、obj文件夹和bin文件夹。其中obj和bin文件夹下各包含debug和release两个文件夹。obj文件夹下存放中间编译结果,bin文件夹下存放最终生成的exe或dll文件。
二、常用项目属性和系统默认配置变量
通常程序开发步骤包括编辑程序、编译程序、装配链接程序、程序调试测试、安装部署。表1给出了程序开发过程中常用的系统变量名和意义:
表1 项目配置常用的系统变量名和意义
图1是某一个工程设置的例子,下面的案例中是以新建一个MyProject的项目为例:
图1
注意:从上图可以看出,TargetDir指目标目录,是一个目录。而TargetPath是目标路径,包括具体的文件名。
2.1 常规—> 输出目录
项目属性的“常规”栏目中“输出目录(OutDir)”的作用是给 ( O u t D i r ) 系 统 变 量 赋 值 , 其 默 认 属 性 值 为 ( S o l u t i o n D i r ) ( C o n f i g u r a t i o n N a m e ) , (OutDir)系统变量赋值,其默认属性值为(SolutionDir)(ConfigurationName), (OutDir)系统变量赋值,其默认属性值为(SolutionDir)(ConfigurationName),(SolutionDir)表示解决方案目录,$(ConfigurationName)的值为debug或release。启动编译后会在解决方案文件夹下建立debug文件夹。
也就是说默认情况下的输出目录是在解决方案目录下的debug或release文件夹下,当然这是针对C++型项目而言,C#型项目不一样。
2.2 常规—> 中间目录
项目属性的“常规”栏目中,“中间目录(IntDir)”的作用是存储链接器所需的输入文件,默认属性为(ProjectDir)(ConfigurationName),编译后会在MyProject项目文件夹下建立一个debug文件夹,并在该文件夹下生成MyProject.obj二进制文件。
2.3 链接器—> 常规—> 输出文件
项目属性的“链接器”栏目下,“常规”选项下,“输出文件”默认属性为$(OutDir)$(ProjectName).exe,其中 ( O u t D i r ) 指 的 是 输 出 目 录 , 启 动 链 接 后 , 在 输 出 目 录 下 生 成 M y P r o j e c t . e x e 文 件 。 (OutDir)指的是输出目录,启动链接后,在输出目录下生成MyProject.exe文件。 (OutDir)指的是输出目录,启动链接后,在输出目录下生成MyProject.exe文件。(TargetDir)的值是由“输出文件”指定的目录决定的。也就是链接器最后生成的*.exe文件所在位置。
图2
“输出目录”和“输出文件”两个属性对应的目录默认情况下是一样的,这样用着方便。如果两个不一样,则链接器所需的*.ilk和*.pdb等中间文件在“输出目录”,而最终生成的exe文件在“输出文件”属性设置的目录中。
2.4 调试—> 命令
项目的“输出目录”属性值决定着系统变量 ( O u t D i r ) 的 值 , 而 项 目 的 “ 输 出 文 件 ” 的 属 性 值 决 定 着 (OutDir)的值,而项目的“输出文件”的属性值决定着 (OutDir)的值,而项目的“输出文件”的属性值决定着(TargetDir)和 ( T a r g e t P a t h ) 的 值 。 程 序 调 试 时 , 系 统 变 量 (TargetPath)的值。程序调试时,系统变量 (TargetPath)的值。程序调试时,系统变量(OutDir)的值是最先确定的,而 ( T a r g e t D i r ) 和 (TargetDir)和 (TargetDir)和(TargetPath)的值是在链接器生成exe文件后才确定的。
“调试”栏目中的“命令(Command)”属性项,这个属性表示启动调试器时执行的exe文件“全路径名+文件名”,默认为链接器生成的$(TargetPath)目录,当然你也可以手动更改“命令”属性的值。
图3
单击调试按钮(VS中的那个小三角形按钮),VS会起动图中所示目录下的exe文件。一般来说“链接器”—>“输出文件”与“调试”—>“命令”中的文件位置、名称是相同,以表示链接器生成的文件和调试时使用的文件一样。一言以蔽之,①<“调试”—>“命令”>、②TargetPath、③输出文件,④输出目录(OutDir) 默认情况下是处于同一个目录,并呈现出前一个紧密依赖于后一个的关系。
2.5 调试—> 工作目录
工作目录(WorkingDirection )与执行目录(Command)可以不同,它是程序工作运行过程中默认读取的目录,调试时是将工作目录下的文件作为附加参数添加到执行目录的exe文件中去调试执行。“调试”栏目中的“工作目录”项,默认属性值为$(ProjectDir),即工程配置文件MyProject.vcproj所在目录,调试过程中它会随着OpenFileDialog、SaveFileDialog等对象所确定的目录而改变。对于静态链接的lib和dll库文件可以放入exe所在的执行目录,而动态加载的dll一般放在工作目录,比如插件就放在工作目录。此外,程序运行过程中生成一个txt文本文件或读取一些配置文件,如果在创建或读取过程中未指定绝对路径,只指定其文件名,那么默认的路径就是工作目录。
VS中工作目录是用于调试过程,只有在调试时,VS才会把项目配置属性中的工作目录设置为执行进程的工作目录,然后再启动对应的exe程序。如果用户选择直接双击一个exe程度启动新进程,VS会自动把exe文件所在的目录设置为新进程的工作目录。因此,在软件部署发布的时候,需把工作目录内的文件拷贝到exe所在的执行目录内,否则就会运行出错。
2.6 链接器—> 输入—> 附加依赖项
“链接器”栏目下,“输入”选项下,“附加依赖项”属性。此项是设置程序链接时使用的静态库的名称。相当于链接已经编译好了的“代码”。由此我们可以简单的认为这些库就相当于我们自己写的源文件,只不过这些库是编译好了的源文件而已。
图4
三、案例操作演示
3.1 前期准备工作
为了增强读者对前面内容的理解,此部分将通过一个实际的案例对其进行演示,假设我们期望的目录结构如下图所示。解决方案的名称为GMA,包含一个动态链接库项目ChocolateMilk(生成dll)和一个应用程序项目PureMilk(生成exe),需要使用一个第三方库log4cxx(Apachelog4j的C++移植版本,用于日志输出)。log4cxx是以动态库的方式编译的,所以我们需要它的①导入库(log4cxxd.lib),②头文件和③动态链接库(log4cxx.dll),分别位于Lib、Include和Bin中。
图5
GMA是解决方案目录
PureMilk和ChocolateMilk是项目目录
Lib目录用于存放导入库或者静态库(包括第三方库和用户项目生成库)
Include用于存放第三方库的头文件
Bin目录存放所有动态链接库和执行档,包括自己的产出和第三方库,分Release和Debug两个版本。另外,程序运行过程中需要外部的数据文件和启动时需要的配置文件等等都可放于该目录
Temp用于存放临时生成文件,其中Compile存放编译器编译时生成的obj文件,Link存放链接器的输出文件。
PureMilk和ChocoliteMilk两个项目的头文件和源文件位置不要动,仍然在各自的项目文件夹内。
上面目录结构清晰,一目了然,当我们的程序需要制作安装包时我们只需将“Bin/Release”目录下的所有文件打包。而在发布和转移源码时我们可以打包除了Temp目录以外“GMA”目录下的所有文件和目录。如果不需要执行档,还可不包括Bin文件。
然而,VC 2008( VS 2008) 并不会自动为用户准备好上面的所有的配置,其中一些工作的需要用户修改项目的缺省设置来完成。
使用“/GMA/Temp/Compile/”作为项目编译时使用的中间目录
使用“/GMA/Temp/Link/”作为项目链接的输出目录
当项目是应用程序时,在构建结束后拷贝执行文件到“/GMA/Bin/Release/”或“/GMA/Bin/Debug/”,当项目是动态链接库时,除了拷贝dll到Bin,还拷贝导入库到“/GMA/Lib/”
当项目是应用程序时,调试时运行“/GMA/Bin/Debug/”或“/GMA/Bin/Release/”下面的执行文件,并以“/GMA/Bin/Debug/”或“/GMA/Bin/Release/”为工作目录
3.2 开始两个项目配置属性设置
3.2.1 动态链接库项目ChocolateMilk配置属性
使用“/GMA/Temp/Compile/”作为项目编译时使用的中间目录
使用“/GMA/Temp/Link/”作为项目链接的输出目录
注意高亮的部分,首先将配置改成All Configuration(全部配置),这样可以让我们同时修改Debug和Release的部分;
Output Directory(输出目录,链接器)栏位填入:
$(SolutionDir)\Temp\Link$(ProjectName)$(ConfigurationName)
Intermediate Directory(中间目录,编译器)栏位填入:
$(SolutionDir)\Temp\Compile$(ProjectName)$(ConfigurationName)
默认设置的dll和lib生成文件为输出目录中,因此构建结束后拷贝动态链接库到“/GMA/Bin/Release/” 或“/GMA/Bin/Debug/”,拷贝导入库到“/GMA/Lib/”。
我们通常都会在Debug版本的输出库后面加上字母“d”以表示这是Debug版本,在Debug配置下,修改Import Library属性为(TargetDir)(TargetName)d.lib:
图7
为了实现构建结束后动态链接库和导入库的拷贝,VC可以让我们设置构建前后执行的脚本程序,需要我们写构建后执行的脚本:
图8
由于VC中缺少表示导入库的系统变量值,所以在Command Line设置时需要分别设置
Debug配置下:
copy “(TargetPath)”“(SolutionDir)\Bin$(ConfigurationName)\”;
copy “(TargetDir)(TargetName)d.lib” “$(SolutionDir)\Lib\”;
Release配置下:
copy “(TargetPath)”“(SolutionDir)\Bin$(ConfigurationName)\”;
copy “(TargetDir)(TargetName).lib” “$(SolutionDir)\Lib\”;
3.2.2 应用程序项目PureMilk配置属性
使用“/GMA/Temp/Compile/”作为项目编译时使用的中间目录
使用“/GMA/Temp/Link/”作为项目链接的输出目录
将配置改成All Configuration,这样可以让我们同时修改Debug和Release的部分;
OutputDirectory(输出目录,链接器)栏位填入:
$(SolutionDir)\Temp\Link$(ProjectName)$(ConfigurationName)
IntermediateDirectory(中间目录,编译器)栏位填入:
$(SolutionDir)\Temp\Compile$(ProjectName)$(ConfigurationName)
构建结束后拷贝执行文件到“/GMA/Bin/Release/”或“/GMA/Bin/Debug/”
在Command Line中填入,All配置下:
copy (TargetPath)(SolutionDir)\Bin$(ConfigurationName);
调试时运行“/GMA/Bin/Debug/”或“/GMA/Bin/Release/”下面的执行文件,并以“/GMA/Bin/Debug/”或“/GMA/Bin/Release/”为工作目录
Command栏填入:
$(SolutionDir)\Bin$(ConfigurationName)$(TargetFileName)
WorkingDirectory栏填入:
$(SolutionDir)\Bin$(ConfigurationName)