VS2005(VC8)编译Xalan-C_1_10_0
概述
本人设计和研发的一个类似Altova MapForce的文档转换产品,该产品支持常用格式文档间的互相转换,包括XML、Excel、CVS、Txt、HTML、XHTML、EDIFACT、SAP IDoc、Database等。项目采用C++语言,VS2005开发环境。
该产品采用适配器(Adapter)的概念在源文档和目标文档中进行适配或者说是转换。其中一个重要的适配器是Xml2Txt,该适配器将XML文档转换(Transform)为其他纯文本文档(Plain Text,在本项目中指XML、Txt、CVS、HTML、XHTML、EDIFACT等)。该适配器采用XSLT(EXtensible Stylesheet Language Transformations),因此需要一个XSLT的解析器。XSLT解析器的开源项目中Apache下的Xalan项目是首选,Xalan有Xalan-C和Xalan-J两种版本,分别支持C++和Java两种语言。Xalan-C的当前版本为1.10.0。Xalan-C需要使用Apache下的Xerces-C项目来解析XML,本项目使用的版本是Xerces-C 2.8.0。
本文意图不是介绍产品的完整方案,而是介绍本人在技术预研时遇到的一个问题的解决方案,即Xalan-C_1_10_0在VS2005下的编译问题。本着发扬互联网的分享精神,心想可能会有朋友遇到同样的问题,因此将解决方案记录下来与朋友们分享,文中错误之处请指正。
相关资源
Xalan-C的官网地址:
http://xml.apache.org/xalan-c/
Xalan-C_1_10_0的下载地址:
http://xml.apache.org/xalan-c/download.html
Xerces-C的官网地址:
http://xerces.apache.org/xerces-c/
Xerces-C_2_8_0的下载地址:
http://xerces.apache.org/xerces-c/download.cgi
文档约定
$XercesSrcHome:指Xerces-C_2_8_0的源码所在文件夹
$XalanSrcHome:指Xalan-C_1_10_0的源码所在文件夹
步骤
(1)使用vs2005编译Xerces-C_2_8_0
Xerces-C_2_8_0的VS2005解决方案在$XercesSrcHome\Projects\Win32\VC8\xerces-all文件夹下,用VS2005打开。
修改XercesLib的工程属性,在属性对话框中的配置属性\C++\语言选项卡中,设置“将wchar_t视为内置类型”为“否”。
(2)设置XERCESCROOT环境变量
新建XERCESCROOT环境变量,其值设置为Xerces-C_2_8_0源码的根路径,即$XercesSrcHome。
右键我的电脑\属性\高级\环境变量
(3)设置VS2005开发环境的Xerces-C_2_8_0路径
工具\选项\项目解决方案\VC++目录,
添加“包含文件”路径:$XercesSrcHome\src
添加“库文件”:$XercesSrcHome\Build\Win32\VC8\Debug
(4)由于Xalan-C_1_10_0不提供VC8(VS2005)解决方案,但其提供了VS7.1(VS2003)的解决方案。因此需要将解决方案从VC7.1装换为VC8。。
Xalan-C_1_10_0的VC7.1的解决方案位于$XalanSrcHome\c\Projects\Win32\VC7.1。将$XalanSrcHome\c\Projects\Win32\VC7.1文件夹复制为$XalanSrcHome\c\Projects\Win32\VC8,然后用VS2005打开$XalanSrcHome\c\Projects\Win32\VC8\Xalan.sln,开发环境自动将工程转换为VC8。
(5)编译Localization工程
编译Xalan库之前,需要先编译Localization工程。编译过程中将会出现若干错误,下文将逐个解决。
a)修改$XalanSrcHome\c\Projects\Win32\VC8\Utils\Localization\BuildMessages.mak文件,在第一行处加入如下语句:
include tools.ini
并修改$XalanSrcHome\c\Projects\Win32\VC8\Utils\Localization\tools.ini,
将
[NMAKE]
CFG=Release
改为
#[NMAKE]
#CFG=Release
即注册掉NMAKE段。
否则,会出现如下编译错误:BuildMessages.mak(26) : fatal error U1050: Invalid configuration BITS="" specified.
b)修改$XalanSrcHome\c\Projects\Win32\VC8\Utils\MsgCreator\MsgCreator.mak文件,修改debug的编译选项,增加/Zc:wchar_t-,即不将wchar_t视为内置类型。
将
CPP_PROJ=/nologo /MLd /W4 /Gm /GX /ZI /Od /I ".\\" /I $(XALANINCLUDE) $(XERCESINCLUDE) /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fr"$(INTDIR)\\" /Fp"$(INTDIR)\MsgCreator.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
修改为:
CPP_PROJ=/Zc:wchar_t- /nologo /MLd /W4 /Gm /GX /ZI /Od /I ".\\" /I $(XALANINCLUDE) $(XERCESINCLUDE) /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fr"$(INTDIR)\\" /Fp"$(INTDIR)\MsgCreator.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
否则,会出现如下编译错误:
1>ICUResHandler.cpp
1>f:\2-研发库\xml\xslt\xml-xalan\c\src\xalanc\utils\msgcreator\icureshandler.cpp(89) : error C2664: 'void XalanFileOutputStream::write(const UTF16Ch *,unsigned int)' : cannot convert parameter 1 from 'XMLCh [512]' to 'const UTF16Ch *'
1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>f:\2-研发库\xml\xslt\xml-xalan\c\src\xalanc\utils\msgcreator\icureshandler.cpp(150) : error C2664: 'void XalanFileOutputStream::write(const UTF16Ch *,unsigned int)' : cannot convert parameter 1 from 'XMLCh *' to 'const UTF16Ch *'
1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
c)修改$XalanSrcHome\c\Projects\Win32\VC8\Utils\MsgCreator\MsgCreator.mak文件,修改debug的编译选项,将/MLd改为/MDd。
将
CPP_PROJ=/nologo /MLd /W4 /Gm /GX /ZI /Od /I ".\\" /I $(XALANINCLUDE) $(XERCESINCLUDE) /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fr"$(INTDIR)\\" /Fp"$(INTDIR)\MsgCreator.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
修改为:
CPP_PROJ=/Zc:wchar_t- /nologo /MDd /W4 /Gm /GX /ZI /Od /I ".\\" /I $(XALANINCLUDE) $(XERCESINCLUDE) /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fr"$(INTDIR)\\" /Fp"$(INTDIR)\MsgCreator.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
否则会出现如下连接错误:
MsgCreator.obj : error LNK2019: 无法解析的外部符号 __CrtSetReportFile,该符号在函数 _main 中被引用
1>MsgCreator.obj : error LNK2019: 无法解析的外部符号 __CrtSetReportMode,该符号在函数 _main 中被引用
1>MsgCreator.obj : error LNK2019: 无法解析的外部符号 __CrtSetDbgFlag,该符号在函数 _main 中被引用
1>libcpmtd.lib(xmbtowc.obj) : error LNK2001: 无法解析的外部符号 __CrtDbgReportW
1>SAX2Handler.obj : error LNK2019: 无法解析的外部符号 __CrtDbgReportW,该符号在函数 "public: char & __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::operator[](unsigned int)" (??A?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEAADI@Z) 中被引用
1>libcpmtd.lib(cerr.obj) : error LNK2001: 无法解析的外部符号 __CrtDbgReportW
1>libcpmtd.lib(cout.obj) : error LNK2001: 无法解析的外部符号 __CrtDbgReportW
1>libcpmtd.lib(stdthrow.obj) : error LNK2001: 无法解析的外部符号 __CrtDbgReportW
1>libcpmtd.lib(xdebug.obj) : error LNK2019: 无法解析的外部符号 __malloc_dbg,该符号在函数 "void * __cdecl operator new(unsigned int,struct std::_DebugHeapTag_t const &,char *,int)" (??2@YAPAXIABU_DebugHeapTag_t@std@@PADH@Z) 中被引用
1>libcpmtd.lib(xmbtowc.obj) : error LNK2001: 无法解析的外部符号 __malloc_dbg
1>NMAKE : fatal error U1077:
1>libcpmtd.lib(xdebug.obj) : error LNK2019: 无法解析的外部符号 __free_dbg,该符号在函数 "void __cdecl operator delete(void *,struct std::_DebugHeapTag_t const &,char *,int)" (??3@YAXPAXABU_DebugHeapTag_t@std@@PADH@Z) 中被引用
1>libcpmtd.lib(xmbtowc.obj) : error LNK2001: 无法解析的外部符号 __free_dbg
1>Stop.
1>libcpmtd.lib(_tolower.obj) : error LNK2019: 无法解析的外部符号 __calloc_dbg,该符号在函数 __Getctype 中被引用
1>..\..\..\..\..\Build\Win32\VC7.1\Debug\MsgCreator.exe : fatal error LNK1120: 7 个无法解析的外部命令
d)修改$XalanSrcHome\c\Projects\Win32\VC8\Utils\Localization\BuildMessages.mak文件,
将
XERCESPATH=$(XERCESCROOT)/bin;$(XERCESCROOT)\Build\Win32\VC7.1\Release;$(XERCESCROOT)\Build\Win32\VC7.1\Debug;$(XERCESCROOT)\Build\Win64\VC7.1\Release;$(XERCESCROOT)\Build\Win64\VC7.1\Debug
修改为:
XERCESPATH=$(XERCESCROOT)/bin;$(XERCESCROOT)\Build\Win32\VC8\Release;$(XERCESCROOT)\Build\Win32\VC8\Debug;$(XERCESCROOT)\Build\Win64\VC8\Release;$(XERCESCROOT)\Build\Win64\VC8\Debug
否则会出现如下连接错误:
1>NMAKE : fatal error U1077:
1>Stop.
1>Project : error PRJ0019: 工具从"正在执行生成文件项目操作"
1>生成日志保存在“file://f:\2-研发库\xml\xslt\xml-xalan\c\Projects\Win32\VC8\Utils\Localization\BuildLog.htm”
1>Localization - 2 个错误,62 个警告
(6)编译AllInOne
a)修改AllInOne的工程属性,在属性对话框中的配置属性\C++\语言选项卡中,设置“将wchar_t视为内置类型”为“否”。
b)增加宏定义_HAS_ITERATOR_DEBUGGING=0
否则会出现如下编译错误:
2>C:\Program Files\Microsoft Visual Studio 8\VC\include\xutility(1360) : error C2678: binary '<' : no operator found which takes a left-hand operand of type 'xalanc_1_10::XalanDequeIterator<XalanDequeTraits,XalanDeque>' (or there is no acceptable conversion)
2> with
2> [
2> XalanDequeTraits=xalanc_1_10::XalanDequeConstIteratorTraits<xalanc_1_10::NameSpace>,
2> XalanDeque=xalanc_1_10::XalanDeque<xalanc_1_10::NameSpace,xalanc_1_10::ConstructWithMemoryManagerTraits<xalanc_1_10::NameSpace>>
2> ]
(7)编译XalanExe(可选)
a)删除输入库largeint.lib
b)去掉XALAN_USE_WINDOWS_TIMING宏定义
将
#if defined(_MSC_VER) && !defined(_WIN64)
#define XALAN_USE_WINDOWS_TIMING
#endif
改为
#if defined(_MSC_VER) && !defined(_WIN64)
//#define XALAN_USE_WINDOWS_TIMING
#endif
否则会出现如下错误:
3>LINK : fatal error LNK1104: 无法打开文件“largeint.lib”
参考文献
a)http://marc.info/?l=xalan-c-users&m=113116861129527
b)http://lists.gnu.org/archive/html/make-w32/2004-03/msg00027.html
c)http://mail-archives.apache.org/mod_mbox/xml-xalan-c-users/201001.mbox/%
[email protected]%3E
d)http://mail-archives.apache.org/mod_mbox/xml-xalan-c-users/200709.mbox/%3c001301c7fc82$047987d0$4001a8c0@estec5syvrnjfw%3e
e)http://marc.info/?l=xalan-c-users&m=113215252420764
总结
本文成功的解决了Xalan-C_1_10_0在VS2005(VC8)下的编译问题。Xalan-C_1_10_0仅实现了XPath1.0,且不支持数据库扩展(SQLExt),因此在数据转换功能上大受限制。本人拟在产品中实现XalanXPath2.0ExtLib(XPath2.0扩展库)和XalanSQLExtLib(SQL扩展库),以便支持强大的数据转换功能。并在此过程中遇到的技术难点和有价值的方案与朋友们分享。