本文操作按照《c&c++开源库编译指南》中内容规范编写,编译环境配置、工具下载、目录规划,及更多其他开源库编译方法请参考该文章。
c&c++开源库编译指南:https://blog.csdn.net/binary0006/article/details/144086155
本文章中的源代码已提交到gitee仓库,地址:https://gitee.com/binary0010/depends/tree/master/c/libiconv-1.11.1
1.libiconv 概述
libiconv 是一个广泛使用的字符编码转换库,由 GNU 项目开发并维护,旨在解决不同字符编码之间的转换问题,确保软件在多语言环境下能正确处理文本数据。
从技术实现上看,libiconv 支持多种常见的字符编码,如 ASCII、UTF - 8、GBK、ISO - 8859 等。它提供了一套简洁的 API 接口,包括 iconv_open 用于打开一个编码转换描述符,iconv 进行实际的编码转换操作,以及 iconv_close 关闭转换描述符。这些接口可以方便地集成到各种 C 或 C++ 程序中,也可通过包装器供其他编程语言调用。编译时,libiconv 具有良好的跨平台性,能在 Linux、Windows、macOS 等多种操作系统上进行编译,并且依赖较少,通常只需标准的 C 库支持。
在应用场景方面,libiconv 具有广泛的用途。在 Web 开发中,当服务器接收来自不同客户端的多语言数据时,可使用 libiconv 将其转换为统一的编码格式进行处理和存储;在文本处理工具中,如编辑器、翻译软件等,libiconv 能帮助用户在不同编码的文本文件之间进行转换。在开源社区,libiconv 基于 GPL 许可发布,代码托管在 GNU 的官方仓库。社区活跃度高,持续对其进行维护和更新,修复潜在的漏洞,添加对新编码格式的支持,拥有大量的用户和开发者群体,被众多知名项目所采用。
2.libiconv编译
2.1.源代码下载
libiconv源代码可以在gun的官方ftp上下载,源代码下载地址:https://ftp.gnu.org/pub/gnu/libiconv/,根据网上查到的资料显示支持vs编译最后一个版本为1.11.1版本,该版本的发布日期是2007-12-10,虽然看着有点老旧,实践测试功能是可以正常使用的,这里我们会使用vs2008来进行编译,选这个低版本也可以避免在vs2008中编译报错。
也可以自己复制这个地址下载:https://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.11.1.tar.gz
2.2.windows编译
先解压源代码到指定目录,libiconv-1.11.1版本中中没有提供CMakeLists.txt编译脚步,提供了makefile文件,在windows上可以使用nmake来构建和编译,但是实际操作已经通过网上查阅的资料,在编译过程中始终会出现问题。这里我们自己编译CMakeLists.txt脚本来构建。
2.2.1.源代码分析
2.2.1.1.makfile文件分析
在编译CMakeLists.txt脚本之前我们先分析一下源代码目录中的Makefile.msvc,他会编译libcharsets、lib、srclib、src、po、man、tests等多个子工程,还会拷贝vs特化的一些头文件iconv.h.msvc-static|iconv.h.msvc-shared、config.h.msvc。
实际上以sdk方式做开发时,只需要libcharsets和lib子工程编译的库就可以了,后面根据Makefile.msvc文件的分析编写我们规范的CMakeLists.txt脚本文件,同时还会对源代码做部分修改。
2.2.1.2.源代码修改
针对libiconv源代码修改,实际上是新增源代码下lib、libcharset工程中需要使用的头文件,共有四个,后面会给出每个文件的源代码:
libiconv-1.11.1/include/iconv.h libiconv-1.11.1/lib/config.h libiconv-1.11.1/libcharset/config.h libiconv-1.11.1/libcharset/include/localcharset.h |
libiconv-1.11.1/include/iconv.h代码:
/* Copyright (C) 1999-2003, 2005-2006 Free Software Foundation, Inc.
This file is part of the GNU LIBICONV Library.
The GNU LIBICONV Library is free software; you can redistribute it
and/or modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
The GNU LIBICONV Library is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU LIBICONV Library; see the file COPYING.LIB.
If not, write to the Free Software Foundation, Inc., 51 Franklin Street,
Fifth Floor, Boston, MA 02110-1301, USA. */
/* When installed, this file is called "iconv.h". */
#ifndef _LIBICONV_H
#define _LIBICONV_H
#define _LIBICONV_VERSION 0x010B /* version number: (major<<8) + minor */
#if defined(__GNUC__) && !defined(__MINGW32__)
# if HAVE_VISIBILITY && BUILDING_LIBICONV
# define LIBICONV_DLL_EXPORTED __attribute__((__visibility__("default")))
# else
# define LIBICONV_DLL_EXPORTED
# endif
#elif defined(__MINGW32__)
#elif defined(_MSC_VER)
# include <Windows.h>
# ifdef ICONV_DLL
# ifdef BUILDING_LIBICONV
# define LIBICONV_DLL_EXPORTED __declspec(dllexport)
# else
# define LIBICONV_DLL_EXPORTED __declspec(dllimport)
# endif // ICONV_DLL
# else
# define LIBICONV_DLL_EXPORTED
# endif
#endif
extern LIBICONV_DLL_EXPORTED int _libiconv_version; /* Likewise */
/* We would like to #include any system header file which could define
iconv_t, 1. in order to eliminate the risk that the user gets compilation
errors because some other system header file includes /usr/include/iconv.h
which defines iconv_t or declares iconv after this file, 2. when compiling
for LIBICONV_PLUG, we need the proper iconv_t type in order to produce
binary compatible code.
But gcc's #include_next is not portable. Thus, once libiconv's iconv.h
has been installed in /usr/local/include, there is no way any more to
include the original /usr/include/iconv.h. We simply have to get away
without it.
Ad 1. The risk that a system header file does
#include "iconv.h" or #include_next "iconv.h"
is small. They all do #include <iconv.h>.
Ad 2. The iconv_t type is a pointer type in all cases I have seen. (It
has to be a scalar type because (iconv_t)(-1) is a possible return value
from iconv_open().) */
/* Define iconv_t ourselves. */
#undef iconv_t
#define iconv_t libiconv_t
typedef void* iconv_t;
/* Get size_t declaration.
Get wchar_t declaration if it exists. */
#include <stddef.h>
/* Get errno declaration and values. */
#include <errno.h>
/* Some systems, like SunOS 4, don't have EILSEQ. Some systems, like BSD/OS,
have EILSEQ in a different header. On these systems, define EILSEQ
ourselves. */
#ifndef EILSEQ
#define EILSEQ @EILSEQ@
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* Allocates descriptor for code conversion from encoding `fromcode' to
encoding `tocode'. */
#ifndef LIBICONV_PLUG
#define iconv_open libiconv_open
#endif
extern LIBICONV_DLL_EXPORTED iconv_t iconv_open (const char* tocode, const char* fromcode);
/* Converts, using conversion descriptor `cd', at most `*inbytesleft' bytes
starting at `*inbuf', writing at most `*outbytesleft' bytes starting at
`*outbuf'.
Decrements `*inbytesleft' and increments `*inbuf' by the same amount.
Decrements `*outbytesleft' and increments `*outbuf' by the same amount. */
#ifndef LIBICONV_PLUG
#define iconv libiconv
#endif
extern LIBICONV_DLL_EXPORTED size_t iconv (iconv_t cd, const char* * inbuf, size_t *inbytesleft, char* * outbuf, size_t *outbytesleft);
/* Frees resources allocated for conversion descriptor `cd'. */
#ifndef LIBICONV_PLUG
#define iconv_close libiconv_close
#endif
extern LIBICONV_DLL_EXPORTED int iconv_close (iconv_t cd);
#ifndef LIBICONV_PLUG
/* Nonstandard extensions. */
/* Control of attributes. */
#define iconvctl libiconvctl
extern LIBICONV_DLL_EXPORTED int iconvctl (iconv_t cd, int request, void* argument);
/* Hook performed after every successful conversion of a Unicode character. */
typedef void (*iconv_unicode_char_hook) (unsigned int uc, void* data);
/* Hook performed after every successful conversion of a wide character. */
typedef void (*iconv_wide_char_hook) (wchar_t wc, void* data);
/* Set of hooks. */
struct iconv_hooks {
iconv_unicode_char_hook uc_hook;
iconv_wide_char_hook wc_hook;
void* data;
};
/* Fallback function. Invoked when a small number of bytes could not be
converted to a Unicode character. This function should process all
bytes from inbuf and may produce replacement Unicode characters by calling
the write_replacement callback repeatedly. */
typedef void (*iconv_unicode_mb_to_uc_fallback)
(const char* inbuf, size_t inbufsize,
void (*write_replacement) (const unsigned int *buf, size_t buflen,
void* callback_arg),
void* callback_arg,
void* data);
/* Fallback function. Invoked when a Unicode character could not be converted
to the target encoding. This function should process the character and
may produce replacement bytes (in the target encoding) by calling the
write_replacement callback repeatedly. */
typedef void (*iconv_unicode_uc_to_mb_fallback)
(unsigned int code,
void (*write_replacement) (const char *buf, size_t buflen,
void* callback_arg),
void* callback_arg,
void* data);
#if 1
/* Fallback function. Invoked when a number of bytes could not be converted to
a wide character. This function should process all bytes from inbuf and may
produce replacement wide characters by calling the write_replacement
callback repeatedly. */
typedef void (*iconv_wchar_mb_to_wc_fallback)
(const char* inbuf, size_t inbufsize,
void (*write_replacement) (const wchar_t *buf, size_t buflen,
void* callback_arg),
void* callback_arg,
void* data);
/* Fallback function. Invoked when a wide character could not be converted to
the target encoding. This function should process the character and may
produce replacement bytes (in the target encoding) by calling the
write_replacement callback repeatedly. */
typedef void (*iconv_wchar_wc_to_mb_fallback)
(wchar_t code,
void (*write_replacement) (const char *buf, size_t buflen,
void* callback_arg),
void* callback_arg,
void* data);
#else
/* If the wchar_t type does not exist, these two fallback functions are never
invoked. Their argument list therefore does not matter. */
typedef void (*iconv_wchar_mb_to_wc_fallback) ();
typedef void (*iconv_wchar_wc_to_mb_fallback) ();
#endif
/* Set of fallbacks. */
struct iconv_fallbacks {
iconv_unicode_mb_to_uc_fallback mb_to_uc_fallback;
iconv_unicode_uc_to_mb_fallback uc_to_mb_fallback;
iconv_wchar_mb_to_wc_fallback mb_to_wc_fallback;
iconv_wchar_wc_to_mb_fallback wc_to_mb_fallback;
void* data;
};
/* Requests for iconvctl. */
#define ICONV_TRIVIALP 0 /* int *argument */
#define ICONV_GET_TRANSLITERATE 1 /* int *argument */
#define ICONV_SET_TRANSLITERATE 2 /* const int *argument */
#define ICONV_GET_DISCARD_ILSEQ 3 /* int *argument */
#define ICONV_SET_DISCARD_ILSEQ 4 /* const int *argument */
#define ICONV_SET_HOOKS 5 /* const struct iconv_hooks *argument */
#define ICONV_SET_FALLBACKS 6 /* const struct iconv_fallbacks *argument */
/* Listing of locale independent encodings. */
#define iconvlist libiconvlist
extern LIBICONV_DLL_EXPORTED void iconvlist (int (*do_one) (unsigned int namescount,
const char * const * names,
void* data),
void* data);
/* Canonicalize an encoding name.
The result is either a canonical encoding name, or name itself. */
extern LIBICONV_DLL_EXPORTED const char * iconv_canonicalize (const char * name);
/* Support for relocatable packages. */
/* Sets the original and the current installation prefix of the package.
Relocation simply replaces a pathname starting with the original prefix
by the corresponding pathname with the current prefix instead. Both
prefixes should be directory names without trailing slash (i.e. use ""
instead of "/"). */
extern LIBICONV_DLL_EXPORTED void libiconv_set_relocation_prefix (const char *orig_prefix,
const char *curr_prefix);
#endif
#ifdef __cplusplus
}
#endif
#endif /* _LIBICONV_H */
libiconv-1.11.1/lib/config.h代码:
/* Copyright (C) 1999-2003, 2005 Free Software Foundation, Inc.
This file is part of the GNU LIBICONV Library.
The GNU LIBICONV Library is free software; you can redistribute it
and/or modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
The GNU LIBICONV Library is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU LIBICONV Library; see the file COPYING.LIB.
If not, write to the Free Software Foundation, Inc., 51 Franklin Street,
Fifth Floor, Boston, MA 02110-1301, USA. */
#if defined(__GNUC__) && !defined(__MINGW32__)
/* Define to 1 if the package shall run at any location in the filesystem. */
#undef ENABLE_RELOCATABLE
/* Define to 1 if you have the setlocale() function. */
#undef HAVE_SETLOCALE
/* Define to 1 if you have the <stddef.h> header file. */
#undef HAVE_STDDEF_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define if the machine's byte ordering is little endian. */
#undef WORDS_LITTLEENDIAN
/* Define to the value of ${prefix}, as a string. */
#undef INSTALLPREFIX
#elif defined(__MINGW32__)
#elif defined(_MSC_VER)
/* Define to 1 if the package shall run at any location in the filesystem. */
#define ENABLE_RELOCATABLE 1
/* Define to 1 if you have the setlocale() function. */
#define HAVE_SETLOCALE 1
/* Define to 1 if you have the <stddef.h> header file. */
#define HAVE_STDDEF_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define if the machine's byte ordering is little endian. */
#define WORDS_LITTLEENDIAN 1
#endif
/* Define to 1 to enable a few rarely used encodings. */
#undef ENABLE_EXTRA
/* Define to a type if <wchar.h> does not define. */
#undef mbstate_t
/* Define if you have <iconv.h>, the iconv_t type, and the
iconv_open, iconv, iconv_close functions. */
#undef HAVE_ICONV
/* Define as const if the declaration of iconv() needs const. */
#define ICONV_CONST const
/* Define to 1 if you have the getc_unlocked() function. */
#undef HAVE_GETC_UNLOCKED
/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
#undef HAVE_LANGINFO_CODESET
/* Define if you have the mbrtowc() function. */
#undef HAVE_MBRTOWC
/* Define to 1 or 0, depending whether the compiler supports simple visibility
declarations. */
#undef HAVE_VISIBILITY
/* Define if you have the wcrtomb() function. */
#undef HAVE_WCRTOMB
/* Define to the value of ${prefix}, as a string. */
libiconv-1.11.1/libcharset/config.h代码:
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
#undef HAVE_LANGINFO_CODESET
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
#if defined(__GNUC__) && !defined(__MINGW32__)
/* Define to 1 if you have the `setlocale' function. */
#undef HAVE_SETLOCALE
/* Define to 1 if you have the <stddef.h> header file. */
#undef HAVE_STDDEF_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
#elif defined(__MINGW32__)
#elif defined(_MSC_VER)
/* Define to 1 if you have the `setlocale' function. */
#define HAVE_SETLOCALE 1
/* Define to 1 if you have the <stddef.h> header file. */
#define HAVE_STDDEF_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
#endif
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 or 0, depending whether the compiler supports simple visibility
declarations. */
#undef HAVE_VISIBILITY
/* Define to the value of ${prefix}, as a string. */
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define to 1 if on AIX 3.
System headers sometimes define this.
We just want to avoid a redefinition error message. */
#ifndef _ALL_SOURCE
# undef _ALL_SOURCE
#endif
/* Define to 1 if on MINIX. */
#undef _MINIX
/* Define to 2 if the system does not provide POSIX.1 features except with
this defined. */
#undef _POSIX_1_SOURCE
/* Define to 1 if you need to in order for `stat' and other things to work. */
#undef _POSIX_SOURCE
libiconv-1.11.1/libcharset/include/localcharset.h代码:
/* Determine a canonical name for the current locale's character encoding.
Copyright (C) 2000-2003 Free Software Foundation, Inc.
This file is part of the GNU CHARSET Library.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published
by the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
USA. */
#ifndef _LOCALCHARSET_H
#define _LOCALCHARSET_H
#ifdef __cplusplus
extern "C" {
#endif
/* Determine the current locale's character encoding, and canonicalize it
into one of the canonical names listed in config.charset.
The result must not be freed; it is statically allocated.
If the canonical name cannot be determined, the result is a non-canonical
name. */
extern const char * locale_charset (void);
#ifdef __cplusplus
}
#endif
#endif /* _LOCALCHARSET_H */
2.2.1.3.增加测试代码
后面为了验证编译的库是否能正常使用,增加一个测试的源代码文件libiconv-1.11.1/iconv_demo.cpp,注意这个文件使用GB2312格式保存。
#include <iostream>
#include <cstring>
#include <iconv.h>
#include <cstdlib>
#include <string>
#include <windows.h>
#define BUFFER_SIZE 1024
// 编码转换函数
std::string convert_encoding(const std::string& input, const std::string& from_encoding, const std::string& to_encoding) {
iconv_t cd;
const char* inbuf = input.c_str();
size_t inbytesleft = input.length();
char* outbuf = new char[BUFFER_SIZE];
char* outptr = outbuf;
size_t outbytesleft = BUFFER_SIZE;
// 打开转换描述符
cd = iconv_open(to_encoding.c_str(), from_encoding.c_str());
if (cd == (iconv_t)-1) {
std::cerr << "iconv_open failed: " << std::strerror(errno) << std::endl;
delete[] outbuf;
return "";
}
// 进行编码转换
if (iconv(cd, &inbuf, &inbytesleft, &outptr, &outbytesleft) == (size_t)-1) {
std::cerr << "iconv failed: " << std::strerror(errno) << std::endl;
iconv_close(cd);
delete[] outbuf;
return "";
}
// 关闭转换描述符
iconv_close(cd);
std::string output(outbuf, BUFFER_SIZE - outbytesleft);
delete[] outbuf;
return output;
}
int main() {
std::string input = "你好,世界!";
std::cout << "转换前(GBK): " << input << std::endl;
std::string gbk_encoding = "GBK";
std::string utf8_encoding = "UTF-8";
// 进行编码转换
std::string output = convert_encoding(input, gbk_encoding, utf8_encoding);
std::cout << "转换后(UTF-8): " << output << std::endl;
if (!output.empty()) {
// 将 GBK 转换回 UTF-8 以便在控制台正确显示
std::string output_utf8 = convert_encoding(output, utf8_encoding, gbk_encoding);
std::cout << "转换回去(GBK): " << output_utf8 << std::endl;
}
// 添加暂停操作
system("pause");
return 0;
}
2.2.2.编写CMake脚本
前面我们已经对libiconv源代码做出了相应的调整,现在按照我们的设计的编译规范来编写CMakeLists.txt脚本进行构建和编译,在源代码根目录下的创建一个CMakeLists.txt。
脚本涉及的内容主要是使用我们编译规范来对工程命名和输出,以及mt工程的链接库设置。
CMakeLists.txt完整内容:
cmake_minimum_required(VERSION 3.15)
project(iconv LANGUAGES C CXX)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../cmake ${CMAKE_MODULE_PATH})
include(${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/third-common.cmake)
set(ICONV_VERSION "1.11.1")
set(INSTALL_BIN_DIR "${third-bin}/${PROJECT_NAME}-${ICONV_VERSION}" CACHE PATH "Installation directory for executables")
set(INSTALL_LIB_DIR "${third-lib}/${PROJECT_NAME}-${ICONV_VERSION}" CACHE PATH "Installation directory for libraries")
set(INSTALL_INC_DIR "${third-include}/${PROJECT_NAME}-${ICONV_VERSION}" CACHE PATH "Installation directory for headers")
set(INSTALL_MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Installation directory for manual pages")
set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files")
add_definitions(-DHAVE_CONFIG_H)
set(iconv_pub_include
include/iconv.h
)
set(libcharset_pub_include
libcharset/config.h
libcharset/include/localcharset.h
)
set(libcharset_privite_src
libcharset/lib/localcharset.c
)
set(lib_pub_include
lib/config.h
)
set(lib_privite_src
lib/iconv.c
)
add_library(iconvlib STATIC
${iconv_pub_include}
${libcharset_pub_include}
${libcharset_privite_src}
${lib_pub_include}
${lib_privite_src})
target_include_directories(iconvlib
PUBLIC
include
libcharset/include
libcharset
)
get_target_property(iconvlib_files iconvlib SOURCES)
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${iconvlib_files})
add_library(iconvdll SHARED
${iconv_pub_include}
${libcharset_pub_include}
${libcharset_privite_src}
${lib_pub_include}
${lib_privite_src})
target_include_directories(iconvdll
PUBLIC
include
libcharset/include
libcharset
)
get_target_property(iconvdll_files iconvdll SOURCES)
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${iconvdll_files})
target_compile_definitions(iconvdll PRIVATE ICONV_DLL BUILDING_LIBICONV)
if(MSVC)
# 静态库mt工程
add_library(iconvlibmt STATIC
${iconv_pub_include}
${libcharset_pub_include}
${libcharset_privite_src}
${lib_pub_include}
${lib_privite_src})
set_property(TARGET iconvlibmt PROPERTY
MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
target_include_directories(iconvlibmt
PUBLIC
include
libcharset/include
libcharset
)
get_target_property(iconvlibmt_files iconvlibmt SOURCES)
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${iconvlibmt_files})
# 动态库mt工程
add_library(iconvdllmt
SHARED
${iconv_pub_include}
${libcharset_pub_include}
${libcharset_privite_src}
${lib_pub_include}
${lib_privite_src})
set_property(TARGET iconvdllmt PROPERTY
MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
target_include_directories(iconvdllmt
PUBLIC
include
libcharset/include
libcharset
)
get_target_property(iconvdllmt_files iconvdllmt SOURCES)
target_compile_definitions(iconvdllmt PRIVATE ICONV_DLL BUILDING_LIBICONV)
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${iconvdllmt_files})
add_executable(iconvlibmt_demo iconv_demo.cpp)
set_property(TARGET iconvlibmt_demo PROPERTY
MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
target_link_libraries(iconvlibmt_demo PRIVATE iconvlibmt)
add_executable(iconvdllmt_demo iconv_demo.cpp)
set_property(TARGET iconvdllmt_demo PROPERTY
MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
target_link_libraries(iconvdllmt_demo PRIVATE iconvdllmt)
# 设置静态库pdb文件
set_lib_pdb_file(iconv lib)
set_lib_pdb_file(iconv libmt)
endif()
add_executable(iconvlib_demo iconv_demo.cpp)
target_link_libraries(iconvlib_demo PRIVATE iconvlib)
add_executable(iconvdll_demo iconv_demo.cpp)
target_link_libraries(iconvdll_demo PRIVATE iconvdll)
# 安装sdk相关文件
# 安装头文件
if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL)
install(FILES ${iconv_pub_include}
DESTINATION "${INSTALL_INC_DIR}"
)
endif()
if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL)
# 安装库文件
set(iconv_targets iconvlib iconvdll)
if(MSVC)
list(APPEND iconv_targets iconvlibmt iconvdllmt)
endif()
install(TARGETS ${iconv_targets}
RUNTIME DESTINATION "${INSTALL_BIN_DIR}"
ARCHIVE DESTINATION "${INSTALL_LIB_DIR}"
LIBRARY DESTINATION "${INSTALL_LIB_DIR}")
endif()
# 安装pdb文件
if(NOT SKIP_INSTALL_PDB AND NOT SKIP_INSTALL_ALL)
install(FILES $<TARGET_PDB_FILE:iconvdll> $<TARGET_PDB_FILE:iconvdllmt>
DESTINATION "${INSTALL_BIN_DIR}"
OPTIONAL)
# 静态库pdb调用函数安装
install_lib_pdb_file(iconv lib)
install_lib_pdb_file(iconv libmt)
endif()
2.2.3.vs2008编译
前面我们已经把vs2008编译需要处理的源代码以及CMakeLists.txt脚本按照规范修改完毕,下面我们将使用cmake来构建vs2008的工程和编译。
2.2.3.1.cmake构建目录设置
选择源代码根目录(CMakeLists.txt文件在这个目录),设置build目录为源代码根目录下的cmake-vs2008绝对路径为D:/x-app/depends/c/libiconv-1.11.1/cmake-vs2008,保证源代码目录干净,会生成工程和临时文件,同时也方便后续有其他的构建工具扩展管理。
2.2.3.2.应用CMake配置
点击“Configure”会弹出编译器选择对话框,这里选择“Visual Studio 9 2008”点击“Finish”按钮等待配置参数完成。
2.2.3.3.生成vs解决方案
下面的红色警告忽略不用管,意思是未来的cmake版本不再支持生成vs2008的解决方案。
2.2.3.4.编译工程
使用vs2008打开“iconv.sln”解决方案文件,分别编译Debug和RelWithDebInfo配置。
2.2.3.5.测试验证
执行libiconv-1.11.1\cmake-vs2008\output\bin\Debug目录下的iconvlib_demo.exe、iconvdll_demo.exe、iconvlibmt_demo.exe、iconvdllmt_demo.exe测试程序,都是能够正常输出结果在控制台中。
2.2.3.6.安装库文件、头文件
编译Install工程的Debug和RelWithDebInfo配置,.h文件和编译生成.dll、.lib、pdb文件会拷贝CMakeList.txt中设置的路径下。
至此通过一个CMakeLists配置文件将windows下vs2008常用编译类型的库全部编译出来了,最终库的对应关系如下。
库类型 | 运行库类型 | 库文件 |
动态库 | mdd | iconvdlld.dll、iconvdlld.lib |
md | iconvdll.dll、iconvdll.lib | |
mtd | iconvdllmtd.dll、iconvdllmtd.lib | |
mt | iconvdllmt.dll、iconvdllmt.lib | |
静态库 | mdd | iconvlibd.lib |
md | iconvlib.lib | |
mtd | iconvlibmtd.lib | |
mt | iconvlibmt.lib |
2.2.4.vs2015编译
vs2015编译与vs2008相同的,只需要在CMake生成工程时选择vs2015即可,其他版本的vs也是一样的,选择需要使用的vs版本即可,此处只演示一下vs2015的编译。
因为前面生成过vs2008的工程,需要将build目录设置成cmake-vs2015,再“Configure”选择vs2015即可,其他操作就是一样的了。
2.2.4.1.vs2015测试
运行cmake-vs2015目录下的编译输出的测试exe文件,在控制台中显示的结果与vs2008编译的一致的,这么vs2015编译的库也是没有问题的。