Microsoft Visual Studio 编译生成 libiconv

  最近需要用到 spatialite,打算在 Windows 下自己编译 libspatialite。官网上有 MinGW how-toMinGW64 how-toMSVC how-to 的教程。由于个人喜好,选择用 MSVC。实际操作起来,才发现官方的教程,基于 OSGeo4W,描述过于简略。当然,如果只是实际使用,还是强烈推荐 OSGeo4W,不用自己编译,安装后有现成的静态库和动态库可供使用。但既然打算自己编译,还是想从依赖库开始。折腾了好久,这里做一个记录。

  其实折腾最久的就是刚开始编译的这个 libiconv。libiconv 从貌似从版本 1.11 以后就不支持 namke 编译了。本来都放弃了自己喜欢用最新稳定版这个陋习,打算勉强用 1.11 这个版本,结果在 VS 2015 下还编译失败了。好在找到了 《How to Build libiconv with Microsoft Visual Studio》,并且按照此文的方法也能够编译目前最新的 1.15 版本。

版本

Visual Studio: 2015

libiconv: 1.15

编译生成

第 1 步

  下载 libiconv。原教程版本是 1.14,这里用的 1.15 也能成功生成,其他版本没有实际测试过。

第 2 步

  用 Visual Studio 新建 Win32 工程,这里命名工程为 libiconv。在设置向导中选择 Application typeDLL,并在 Additional options 中勾选 Empty project


第 3 步

  解压下载的 libiconv-1.15.tar.gz。复制以下文件:

  1. 从解压的文件夹 …\libiconv-1.15\lib\ 中,复制 relocatable.h、relocatable.c、iconv.c 到工程文件夹 …\libiconv\libiconv\ 中。
  2. 从解压的文件夹 …\libiconv-1.15\libcharset\lib\ 中,复制 localcharset.c 到工程文件夹 …\libiconv\libiconv\ 中。
  3. 从解压的文件夹 …\libiconv-1.15\libcharset\include\ 中,复制 localcharset.h.build.in 到工程文件夹 …\libiconv\libiconv\ 中,并重命名为 localcharset.h
  4. 从解压的文件夹 …\libiconv-1.15\windows\ 中,复制 libiconv.rc 到工程文件夹 ..\libiconv\libiconv\ 中。
  5. 在工程文件夹 ..\libiconv\ 中创建文件夹 include
  6. 从解压的文件夹 …\libiconv-1.15\include\ 中,复制 iconv.h.build.in 到工程文件夹 ..\libiconv\include\ 中,并重命名为 iconv.h
  7. 从解压的文件夹 …\libiconv-1.15\ 中,复制 config.h.in 到工程文件夹 ..\libiconv\include\ 中,并重命名为 config.h
  8. 从解压的文件夹 …\libiconv-1.15\lib\ 中,复制所有的头文件(*.h)和所有的定义文件(*.def)到工程文件夹 …\libiconv\include\ 中。

第 4 步

  点击菜单 Project > Add Existing item…,将之前复制到工程文件夹 …\libiconv\libiconv 中的文件加入工程。

第 5 步

  设置工程属性。在设置时,可选择 All ConfigurationsAll Platforms,实际编译生成时,可根据需要选择 Debug 或 Release,x86 或 x64。

  选择 Configuration Properties > General,设置 Output Directory$(SolutionDir)$(Configuration)_$(Platform)\,设置 Intermediate Directory$(SolutionDir)obj\$(ProjectName)\$(Configuration)_$(Platform)\

  选择 Configuration Properties > VC++ Directories,为 Include Directories 添加路径 ..\include

  选择 Configuration Properties > C/C++ > Preprocessor,为 Preprocessor Definitions 添加 BUILDING_LIBICONVBUILDING_LIBCHARSET

  选择 Configuration Properties > C/C++ > Code Generation,设置 Runtime LibraryMulti-threaded(/MT)。原文指出这里是编译动态库的推荐设置,只编译静态库可根据实际情况设置。

  选择 Configuration Properties > C/C++ > Precompiled Headers,设置 Precompiled HeaderNot Using Precompiled Headers

第 6 步

  需要对源代码进行一些修改。

libiconv.rc

  在第 4 行插入代码:

1
2
3
4
#define PACKAGE_VERSION_MAJOR 1
#define PACKAGE_VERSION_MINOR 15
#define PACKAGE_VERSION_SUBMINOR 0
#define PACKAGE_VERSION_STRING "1.15"

localcharset.c

  注释 81 - 83 行:

1
2
3
4
/* Get LIBDIR. */
//#ifndef LIBDIR
//# include "configmake.h"
//#endif

iconv.c

  修改 250 - 252 行:

1
2
3
4
5
6
//size_t iconv (iconv_t icd,
// ICONV_CONST char* * inbuf, size_t *inbytesleft,
// char* * outbuf, size_t *outbytesleft)
size_t iconv(iconv_t icd,
const char* * inbuf, size_t *inbytesleft,
char* * outbuf, size_t *outbytesleft)

localcharset.h

  修改 21 - 25 行:

1
2
3
4
5
6
7
8
9
10
11
12
//#if @HAVE_VISIBILITY@ && BUILDING_LIBCHARSET
//#define LIBCHARSET_DLL_EXPORTED __attribute__((__visibility__("default")))
//#else
//#define LIBCHARSET_DLL_EXPORTED
//#endif
#ifdef BUILDING_LIBCHARSET
#define LIBCHARSET_DLL_EXPORTED __declspec(dllexport)
#elif USING_STATIC_LIBICONV
#define LIBCHARSET_DLL_EXPORTED
#else
#define LIBCHARSET_DLL_EXPORTED __declspec(dllimport)
#endif

config.h

  在 …\libiconv\include\ 中打开,注释 30 行:

1
2
/* Define as good substitute value for EILSEQ. */
//#undef EILSEQ

iconv.h

  在 …\libiconv\include\ 中打开,修改 174 行:

1
2
//#if @HAVE_WCHAR_T@
#if HAVE_WCHAR_T

  修改 127 行:

1
2
//#if @USE_MBSTATE_T@
#if USE_MBSTATE_T

  修改 106 - 107 行:

1
2
3
4
//#if @USE_MBSTATE_T@
//#if @BROKEN_WCHAR_H@
#if USE_MBSTATE_T
#if BROKEN_WCHAR_H

  修改 88 行:

1
2
//extern LIBICONV_DLL_EXPORTED size_t iconv (iconv_t cd, @ICONV_CONST@ char* * inbuf, size_t *inbytesleft, char* * outbuf, size_t *outbytesleft);
extern LIBICONV_DLL_EXPORTED size_t iconv (iconv_t cd, const char* * inbuf, size_t *inbytesleft, char* * outbuf, size_t *outbytesleft);

  修改 25 - 30 行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//#if @HAVE_VISIBILITY@ && BUILDING_LIBICONV
//#define LIBICONV_DLL_EXPORTED __attribute__((__visibility__("default")))
//#else
//#define LIBICONV_DLL_EXPORTED
//#endif
//extern LIBICONV_DLL_EXPORTED @DLL_VARIABLE@ int _libiconv_version; /* Likewise */
#if BUILDING_LIBICONV
#define LIBICONV_DLL_EXPORTED __declspec(dllexport)
#elif USING_STATIC_LIBICONV
#define LIBICONV_DLL_EXPORTED
#else
#define LIBICONV_DLL_EXPORTED __declspec(dllimport)
#endif
extern LIBICONV_DLL_EXPORTED int _libiconv_version;

使用

  使用时,需要 …\libiconv\include\ 中的 iconv.h。根据使用需要,可在编译生成的输出文件夹中找到 libiconv.liblibiconv.dll

许可

  鉴于本文是照搬的,为尊重原文,与原文一样,本文及其相关的代码遵循 The GNU Lesser General Public License (LGPLv3)

原文

How to Build libiconv with Microsoft Visual Studio