跟大多数UNIX库一样,libxml2的编译遵循以下“标准”:
gunzip -c xxx.tar.gz | tar xvf - (或者tar xzvf libxml2-xxxx.tar.gz) cd libxml2-xxxx ./configure --help查看各选项,然后编译并安装。
./configure [possible options] make make install安装后有可能还要重新运行ldconfig或类似工具以更新被安装的共享库列表。
Microsoft (R) COFF/PE Dumper Version 10.00.30319.01 Copyright (C) Microsoft Corporation. All rights reserved. Dump of file libiconv-2.dll File Type: DLL Section contains the following exports for libiconv-2.dll 00000000 characteristics 50C075A5 time date stamp Thu Dec 06 18:38:29 2012 0.00 version 1 ordinal base 13 number of functions 13 number of names ordinal hint RVA name 1 0 00013000 _libiconv_version 2 1 00011478 aliases2_lookup 3 2 00011350 aliases_lookup = _locale_charset 4 3 000120F0 iconv_canonicalize 5 4 00011908 libiconv 6 5 00011958 libiconv_close 7 6 000114C0 libiconv_open = _libiconv_set_relocation_prefix 8 7 00011970 libiconv_open_into 9 8 00012580 libiconv_relocate 10 9 000124C0 libiconv_set_relocation_prefix 11 A 00011EB8 libiconvctl 12 B 00011FC8 libiconvlist 13 C 00012350 locale_charset Summary 1000 .CRT 1000 .bss 1000 .data 1000 .debug_abbrev 1000 .debug_aranges 1000 .debug_frame 1F000 .debug_info 6000 .debug_line 18000 .debug_loc 1000 .debug_pubnames 1000 .debug_pubtypes 4000 .debug_ranges 1000 .debug_str 1000 .edata 4000 .eh_frame 1000 .idata CD000 .rdata 1000 .reloc 1000 .rsrc 12000 .text 1000 .tlsionv.def需要修改成符合模块定义文件的语法。我们只要关心DEF文件定义里的两个段:LIBRARY段和EXPORTS段。LIBRARY段指出DLL的内部名,这里为libiconv-2;EXPORTS段指出导出的函数或数据。上面数据的中间部分列出了所有导出函数和数据,真正需要是orinal列(表示编号)和name列。把iconv.def修改成如下内容:
LIBRARY "libiconv-2" EXPORTS _libiconv_version @1 aliases2_lookup @2 aliases_lookup = _locale_charset @3 iconv_canonicalize @4 libiconv @5 libiconv_close @6 libiconv_open = _libiconv_set_relocation_prefix @7 libiconv_open_into @8 libiconv_relocate @9 libiconv_set_relocation_prefix @10 libiconvctl @11 libiconvlist @12 locale_charset @13最后生成导入库:lib /machine:ix86 /def:iconv.def,生成iconv.lib和iconv.exp文件。发布时包含libiconv-2.dll, iconv.lib和iconv.h即可,并且注意它是使用LGPL许可的。
附:用MSVC编译最新的libiconv
最新的libiconv已经不提供用Visual C/C++和nmake来编译了。如果一定要用Visual C++来编译libiconv,我们需要对源码的编译过程做一些分析,然后对源代码做一些调整。
libiconv-1.14中,lib\和libcharset\下是libiconv和libcharset库的源码,需要导出的头文件iconv.h在include\下,为iconv.h.in或iconv.h.build.in。它们使用LGPL许可,而其他目录下的源码是GPL许可,我们也无需使用。iconv.h.build.in中包含一些@开头的符号变量,这是为了提高可移植性而定义的,它们用来收集一些特定于系统的编译构建信息。在用./configure配置源码时,这些变量会被configure扫描到的相关值替换掉,从而生成iconv.h。在Visual C++下编译时没有配置的过程,因此我们需要了解这些变量的含义。
1)@HAVE_VISIBILITY@: 表示是否有__visibility__属性。这是GCC/G++的__attribute__属性扩展,表示导出符号的可见性,这在创建.so动态库时有用。__attribute__((__visibility__("default")))表示导出的符号可见,而__attribute__ ((visibility("hidden")))可以防止从动态库中导出符号。若用Microsoft Visual C++编译器来编译,显然值为0。
2)@DLL_VARIABLE@: 表示后面声明的变量是否是从外部DLL中导入过来的。如果是,本变量值设成__declspec (dllimport);如果不是,则设成空。显然这里可以设成空的。参考configure.ac中对本变量的处理。
在Windows系统中,__declspec(dllimport)用于声明一个导入函数,是说这个函数是从别的DLL(或EXE)导入,我要用。不使用__declspec(dllimport)导入外部函数也能正确编译代码,但使用__declspec(dllimport)使编译器可以生成更好的代码。编译器之所以能够生成更好的代码,是因为它可以确定函数是否存在于DLL中,这使得编译器可以生成跳过间接寻址级别的代码,而这些代码通常会出现在跨DLL边界的函数调用中。但是,必须使用__declspec(dllimport)才能导入DLL中使用的变量。
__declspec(dllexport)用于声明一个导出函数,是说这个函数要从本DLL导出,要给别人用,一般用在开发DLL时。使用这个声明可以省掉在DEF文件中手工定义导出哪些函数的工作。当然,如果你的DLL里全是C++的类的话,你无法在DEF里指定导出的函数,只能用__declspec(dllexport)导出类。
3)@EILSEQ@: EILSEQ是errno.h中定义的一个错误码,表示非法字节序列(例如在MBCS字符串)。 一些系统像SunOS 4没有EILSEQ,一些系统像BSD/OS在其他头文件中有EILSEQ,在这些系统上就需要定义我们自己的EILSEQ。Linux, Windows上有这个错误码,因此无需自己再定义,本变量值为空。
4)@ICONV_CONST@: 表示在"char"前面是否加上"const",例如在Linux系统上./configure后可以看到这个变量替换为空,即使用"char**",而不是"const char**"。Windows上值为"const"。
5)@USE_MBSTATE_T@: 是否使用宽字符处理函数wchar.h。若要支持多种字符集,本变量值为1。mbstate_t类型用于C的字符编码转换函数和C++的字符编码转换类,C/C++标准没有规定具体的数据类型。mbstate_t类型的对象表示转换函数mbrlen, mbrtowc, mbsrtowcs, wcrtomb或wcsrtombs的一个转换状态(这些函数在wchar.h中)。可用mbsinit()函数测试是否处于读入新字符状态。举个例子,有些字符集包含了一类带有状态编码的字符,如很多Latin语言系带有的重音符号(accent),通常用一个编码表示一种accent,其后面的一个字符表示需要添加accent的字符(因此如果需要输出accent本身,后面还得加另外一个字符,比如空格)。这种字符就是表示进入到某种状态,用mbstate_t类型来描述这种状态。
6)@BROKEN_WCHAR_H@: wchar.h是否有bug。在带桌面C工具包的HP Tru64 UNIX系统上有一个bug,包含<wchar.h>之前必须先包含<stdio.h>。在BSD/OS 4.0.1上有一个bug,必须在包含<wchar.h>之前必须先包含stddef.h>,<stdio.h>和<time.h>。本变量标记这样的特殊情况。Linux, Windows上本变量值为0。
7)@HAVE_WCHAR_T@: 是否使用宽字符处理。若上面使用了宽字符处理,本变量值为1。
详细的构建过程可参考一篇文章:http://www.codeproject.com/Articles/302012/How-to-Build-libiconv-with-Microsoft-Visual-Studio
在Libxm2Learning解决方案下添加一个Win32 DLL空项目libiconv,设置编译成Release版本。
第一步:拷贝源文件
把libiconv-1.14\lib\下的"relocatable.h", "relocatable.c"和"iconv.c"拷贝到libiconv项目目录中。
把libiconv-1.14\libcharset\lib\localcharset.c拷贝到libiconv项目目录中。
把libiconv-1.14\libcharset\include\localcharset.h.build.in拷贝到项目中,并重命名为localcharset.h。
把libiconv-1.14\windows\libiconv.rc拷贝到项目目录。
在libiconv项目下创建子目录include,用来放各个头文件。
把libiconv-1.14\include\iconv.h.build.in拷贝到项目include子目录下,并重命名为iconv.h。
把libiconv-1.14\config.h.in拷贝到项目include子目录下,并重命名为config.h。
把libiconv-1.14\lib\下的所有头文件(*.h)和模块定义文件(*.def)拷贝到项目include子目录下。
第二步:设置项目属性
把项目根目录下的两个源文件、两个文件和一个资源文件导入到libiconv项目视图中。设置项目属性。
"VC++ Directories"设置:在"Include Directories"中添加include子目录。
"Preprocessor Definitions"设置:添加宏"BUILDING_LIBICONV"和"BUILDING_LIBCHARSET"。
"Code Generation"设置:"Runtime Library"最好设置为/MT,以静态链接多线程版的C运行时函数库。
第四步:调整源代码
1)iconv.h: 按照上面介绍把各个@...@变量替换成相应值。更改函数导入导出声明,即把以下针对gcc/g++的导出定义
#if @HAVE_VISIBILITY@ && BUILDING_LIBICONV #define LIBICONV_DLL_EXPORTED __attribute__((__visibility__("default"))) #else #define LIBICONV_DLL_EXPORTED #endif修改为针对MSVC的定义:
#if BUILDING_LIBICONV #define LIBICONV_DLL_EXPORTED __declspec(dllexport) #elif USING_STATIC_LIBICONV #define LIBICONV_DLL_EXPORTED #else #define LIBICONV_DLL_EXPORTED __declspec(dllimport) #endif2)libiconv.rc: 在前面添加以下定义。
#define PACKAGE_VERSION_MAJOR 1 #define PACKAGE_VERSION_MINOR 14 #define PACKAGE_VERSION_SUBMINOR 0 #define PACKAGE_VERSION_STRING "1.14"3)localcharset.c: 删掉或注释掉以下几行(76-79行)。
/* Get LIBDIR. */ /* #ifndef LIBDIR # include "configmake.h" #endif */4)iconv.c: 把其中的ICONV_CONST宏(247行)改成const。
#if @HAVE_VISIBILITY@ && BUILDING_LIBCHARSET #define LIBCHARSET_DLL_EXPORTED __attribute__((__visibility__("default"))) #else #define LIBCHARSET_DLL_EXPORTED #endif修改为针对MSVC的定义:
#ifdef BUILDING_LIBCHARSET #define LIBCHARSET_DLL_EXPORTED __declspec(dllexport) #elif USING_STATIC_LIBICONV #define LIBCHARSET_DLL_EXPORTED #else #define LIBCHARSET_DLL_EXPORTED __declspec(dllimport) #endif6)config.h: 删掉或注释掉以下内容(29-30行),否则会导致Windows上没有EILSEQ定义,从而代码编译通不过。
/* Define as good substitute value for EILSEQ. */ /*#undef EILSEQ*/好了,一切准备就绪,编译完之后就可以在解决方案的Release目录中看到libiconv.dll了,以及导入库libiconv.lib(若让libxml2链接时使用,则需要改名为iconv.lib)。发布时还包含头文件iconv.h。
Microsoft (R) COFF/PE Dumper Version 10.00.30319.01 Copyright (C) Microsoft Corporation. All rights reserved. Dump of file libiconv.dll File Type: DLL Section contains the following exports for libiconv.dll 00000000 characteristics 50B5EAAA time date stamp Wed Nov 28 18:42:50 2012 0.00 version 1 ordinal base 9 number of functions 9 number of names ordinal hint RVA name 1 0 000E8DC0 _libiconv_version = __libiconv_version 2 1 00012810 iconv_canonicalize = _iconv_canonicalize 3 2 000120C0 libiconv = _libiconv 4 3 00012100 libiconv_close = _libiconv_close 5 4 00011D90 libiconv_open = _libiconv_open 6 5 00012120 libiconv_open_into = _libiconv_open_into 7 6 00012420 libiconvctl = _libiconvctl 8 7 00012600 libiconvlist = _libiconvlist 9 8 00012970 locale_charset = _locale_charset Summary 3000 .data CE000 .rdata 2000 .reloc 1000 .rsrc 19000 .text原始的libiconv使用LGPL许可,因此这个调整的libiconv也是LGPL许可,在使用时必须仔细注意授权的问题。如果动态链接libiconv.dll,则你的应用程序无需发布源码。如果编译成静态库并使用静态链接,则你的应用程序或者发布源码,或者发布目标文件(*.obj),以便其他人通过静态链接LGPL的libiconv来重新生成应用程序。