Log4cplus源码分析之-Properties属性配置文件
1 编译
1.1 下载
下载1.1.3 版本: http://sourceforge.net/projects/log4cplus/files/log4cplus-stable/1.1.3/,点击 log4cplus-1.1.3-rc2.zip 下载。
1.2 编译
如果是Win7+VS2010,那么编译过程会很顺畅,因为该版本log4cplus在Win7+VS2010编译验证过。
解压后,进入 log4cplus-1.1.3-rc2\msvc10 目录,打开 log4cplus.sln,编译 log4cplus(动态库),log4cplusS(静态库)。
2. 编译配置
以动态库log4cplus的配置为例
1.1 Configuration Properties General

1. Output Directory:目标文件的存储目录(exe,lib,dll等文件)。
(1)$(SolutionDir): 为工程的solution文件所在的目录,本项目中,就是log4cplus.sln所在的目录: "log4cplus-1.1.3-rc2\msvc10"
注意:$(SolutionDir)路径中已经包含了最后面的“\”,因此与$(PlatformName)之间不需要再添加一个“\”。
(2)$(PlatformName):就是该页面中最上面的Platform选项上所选择的值,在图中可以看到是 “Win32”。
(3)$(Configuration):就是该页面中最上面的Configuration选项上所选择的值,在图中可以看到是 “Debug_Unicode”。
注意:$(Configuration)只是一个配置名称,不是路径,所以需要在最后添加一个“\”。
2. Intermediate Directory: 编译过程中生成的临时文件的存储目录(obj等文件)。
(1)$(ProjectName):就是工程文件 log4cplus.vcxproj的名字log4cplus。编译log4cplusS的时候,就对应log4cplusS。
3. Extensions to Delete on Clean: 当clean工程的时候,要删除的文件。
*.cdf;*.cache;*.obj;*.ilk;*.resources;*.tlb;*.tli;*.tlh;*.tmp;*.rsp;*.pgc;*.pgd;*.meta;*.tlog;*.manifest;*.res;*.pch;*.exp;*.idb;*.rep;*.xdc;*.pdb;*_manifest.rc;*.bsc;*.sbr;*.xml
4. Build Log File:生成的log文件
(1)$(IntDir):指的就是“Intermediate Directory”目录,编译过程中生成的临时文件的存储目录。所生成的log文件也存储在该目录下。
(2)$(MSBuildProjectName):指的也是正在编译的工程名字,对应log4cplus工程就是log4cplus,对应log4cplusS工程就是log4cplusS。
5. $(IntDir)等这些宏的值是在哪儿定义的呢?
这些宏的值都可以在工程的属性页中找到:右键点击工程->Properties->C/C++ General->点击Additional Include Directories->Edit->点击 "Macros>>"按钮,就可以从里面看到所有的宏所对应的值。

1.2 C/C++ General
Additional Include Directories: 从上图也可以看到,Additional Include Directories的值为%(AdditionalIncludeDirectories),打开它,发现它里面没有值,只有一个继承来的“..\include”值。那这个继承的值是从哪儿来的呢?
是从属性配置文件来的。
3. 属性配置文件(.props文件)
log4cplus定义了一套属性配置文件:log4cplus.props,log4cplus_debug.props,log4cplus_release.props
3.1 .props文件的作用
当一个solution中的project越来越多以后,管理编译选项,将成为一件很麻烦的事,单独对每个project进行设置不仅繁琐,而且容易出错。但实际上,visual studio已经为我们提过了统一的管理界面:Property Manager。在visual studio的view菜单中选择property manager,可以清楚的看到每个project继承了哪些property sheet,并且有更多的编辑功能(如创建新property sheet、清除project已经设置了的选项等)。
另外,property sheet还支持多级继承,而实践上一般也是每个solution一个根Property Sheet,然后为每个Configruation(Debug版、Release版等)分别派生出一个,各个project的不同Configruation继承对应的Property Sheet。【1】
3.2 .props文件是如何继承的
1. 在VS2008中,Configuration Properties/General属性页中,都有一项"Inherited Project Property Sheets",可以在这里指定一个或多个Property Sheet供项目继承。
而且VS2008中property文件的后缀名为.vsprops。

2. 在VS2010中,已经没有"Inherited Project Property Sheets"这个选项了。那log4cplus.props,log4cplus_debug.props是如何设置继承关系的呢?
是通过在Property Manager中所设置的顺序来决定的。Property Manager解析值的顺序是“bottom-up order”, 在最上层的.props最晚被解析。
后解析的值会覆盖之前的值,比如说log4cplus.props,log4cplus_debug.props都设置了output directory,而且值还不一样。那么最终output directory值为log4cplus_debug.props所设置的值。【2】

3.3 .props文件是如何创建和添加的?
1. log4cplus.props,log4cplus_debug.props,log4cplus_release.props都是通过 右键->Add New Project Property Sheet来添加的。
2. x64,_Unicode版的.props文件都是通过 右键->Add Existing Property Sheet 来添加的。
4. Visual Studio 2010的配置文件的级别
4.1 工程文件log4cplus.vcxproj分析
打开log4cplus.vcxproj文件可以看到,
<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> ... <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release_Unicode|Win32'" Label="PropertySheets"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="log4cplus.props" /> <Import Project="log4cplus_release.props" /> </ImportGroup> <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug_Unicode|Win32'" Label="PropertySheets"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="log4cplus.props" /> <Import Project="log4cplus_debug.props" /> </ImportGroup> <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="log4cplus.props" /> <Import Project="log4cplus_debug.props" /> </ImportGroup> <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="log4cplus.props" /> <Import Project="log4cplus_release.props" /> </ImportGroup> ... </Project>
(1)导入 C++默认属性文件Microsoft.Cpp.Default.props. 路径位于"C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0".
(2)导入C++属性文件Microsoft.Cpp.props. 路径也位于"C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0".
(3)然后是根据平台类型,导入用户级的props文件"$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props", Win32平台时$(Platform)=Win32,x64平台时$(Platform)=x64,他们均位于"C:\Users\xxx\AppData\Local\Microsoft\MSBuild\v4.0"目录下. 这些文件没有配置任何的内容,如果你删除它们,那么在打开 C++ 工程文件时,IDE 会自动的创建它们;请注意关键就在这里,这些文件的目的就是为了用户可以对C++工程的属性进行自定义,并且是“用户”级别的,也就是说在这些文件中增加的属性将对你所有的工程起作用
(4)然后是针对各个编译选项,import了不同的用户自定义的props文件,Debug版导入log4cplus_debug.props, Release版导入log4cplus_release.props.
对 Microsoft.Cpp.Default.props 、Microsoft.Cpp.props 和 Microsoft.Cpp.targets 进行简单分析就会发现,它们都是首先根据编译的目标平台导入对应的平台定义的文件,然后是自己的属性定义,并且这些属性都会在没有定义的情况下才会生效,避免冲掉前面的定义;并且还可以发现一个秘密,那就是在编译系统还为每一个工程提供了一个免费的属性定义文件,*.vcxproj.user ,这个文件如果存在,那么将会被自动导入. 通过以上分析,我们可以发现C++的编译系统其实除了工程文件本身之外(毕竟不可能把所有的编译选项都放到工程文件中)还另外提供来三个级别的属性配置文件:【3】【4】【5】
a、工程级别的,就是 *.vcxproj.user 文件;还有就是可以在工程vcxproj中import自定义的props.
b、用户级别的,就是 Microsoft.Cpp.$(Platform).user.props 文件
c、系统级别的,就是 前面提供到 Microsoft.Cpp.Default.props 、Microsoft.Cpp.props 和 Microsoft.Cpp.targets 文件;
4.2 以宏定义(PreprocessorDefinitions)为例分析
在log4cplus.props中,定义有
<PreprocessorDefinitions>WIN32;_WIN32_WINNT=0x0501;WINVER=0x0501;INSIDE_LOG4CPLUS;_SCL_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
在log4cplus_debug.props中有
<PreprocessorDefinitions>_DEBUG;DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
在log4cplus_release.props中有
<PreprocessorDefinitions>NDEBUG;_SECURE_SCL=0;_HAS_ITERATOR_DEBUGGING=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
而在工程的属性设置中,又会添加上:
LOG4CPLUS_BUILD_DLL;%(PreprocessorDefinitions)
LOG4CPLUS_BUILD_DLL是DLL版本定义的宏,而对静态库版本的log4cplusS,定义的宏是LOG4CPLUS_STATIC. 每个层次都会添加上 %(PreprocessorDefinitions)以包含上一层次的定义.
5. %(AdditionalIncludeDirectories)是什么?
Additional Include Directories中的%(AdditionalIncludeDirectories)是什么呢?
在下面的图中,从父级或项目默认设置继承(Inherit from parent or project defaults),如果你勾选了这个选项,那么在附加包含目录中,就会在结尾含有%(AdditionalIncludeDirectories)。所以%(AdditionalIncludeDirectories)表示当前project的附加包含目录需要继承使用其父亲的配置。【6】

(1)Microsoft.Cpp.Win32.user 是最底层的props,所以它的 Additional Include Directories中没有%(AdditionalIncludeDirectories)。
(2)log4cplus是次一级的props,所以它的%(AdditionalIncludeDirectories)是继承自Microsoft.Cpp.Win32.user.props.另外,它又添加了一个 “..\include”目录。
(3)log4cplus_debug是顶层的props,所以它的%(AdditionalIncludeDirectories)是继承自log4cplus,所以我们看到它的“Inherited Value”中有“..\include”目录。
Reference:
【1】编译选项的统一管理:Property Manager(http://blog.csdn.net/localvar/article/details/3664514)
【2】Visual Studio 2010: Property Sheets and C++ Directories(http://blog.gockelhut.com/2009/11/visual-studio-2010-property-sheets-and.html)
【3】Visual Studio 2010 C++ 工程文件解读 (http://www.cnblogs.com/WonKerr/archive/2010/06/27/VS2010_VCXPROJ_1.html)
【4】Visual Studio 2010 C++ 属性设置基础 (http://www.cnblogs.com/WonKerr/archive/2010/06/27/VS2010_VCXPROJ_2.html )
【5】Visual Studio 2010 C++ 用户属性设置 (http://www.cnblogs.com/WonKerr/archive/2010/06/27/VS2010_VCXPROJ_3.html)
【6】vs2010里附加包含目录里面的%(AdditionalIncludeDirectories)是什么意思?(http://www.zhihu.com/question/20988366)
浙公网安备 33010602011771号