最后,我解决了这个问题。为了和你分享我的经验
我将描述我遇到的四个主要陷阱。
如果您想重复这些步骤,我假设您使用 msys2 和 MinGW-w32。
对所有内容使用相同的工具链。注意 MinGW、MinGW-w32 和 MinGW-w64
是 3 个不同的工具链。如果您有多个 MinGW 安装
像我一样,确保在整个项目中只使用其中一个。
出于兼容性原因,我选择了 MinGW-w32。
最新版本的软件通常包含错误,并且它们
需要你再用铃鼓跳舞。
ICU v58 在写这篇文章的时候有问题。
解决方案是恢复到旧版本(在我的情况下为 57.1)。
在构建 ICU 库之前,请确保正确设置所有内容。
这里的问题是使用命名空间和重命名命名空间
ICU 默认情况下会这样做。
找到文件 C:\icu\source\common\unicode\uconfig.h 并添加以下内容
在包括警卫之后的开头:
#define U_DISABLE_RENAMING 1
#define U_USING_ICU_NAMESPACE 0
保存文件。打开 MSYS2 终端并将 mingw-w32 设置为工作工具集:
export PATH="/c/msys64/mingw32/bin:$PATH"
转到 icu/源目录:
cd /c/icu/source
将 ICU 配置为不重命名且 U_USING_ICU_NAMESPACE=0 的静态构建:
export CFLAGS="-DU_CHARSET_IS_UTF8=1 -DU_GNUC_UTF16_STRING=1 -DU_STATIC_IMPLEMENTATION"
export CXXFLAGS="-DU_USING_ICU_NAMESPACE=0 -std=gnu++11 -DU_CHARSET_IS_UTF8=1 -DU_GNUC_UTF16_STRING=1 -DU_HAVE_CHAR16_T=1 -DUCHAR_TYPE=char16_t -Wall --std=c++11 -DU_STATIC_IMPLEMENTATION" -static-libstdc++ -fno-exceptions
export CPPFLAGS="-DU_DISABLE_RENAMING=1 -DU_CHARSET_IS_UTF8=1 -DU_STATIC_IMPLEMENTATION"
export LDFLAGS="-std=gnu++11"
./runConfigureICU MinGW prefix=$PWD/../dist -enable-static -disable-shared --disable-renaming
构建和安装 ICU 库。 -j4 如果您有 4 个内核,则加快进程:
mingw32-make -j4
mingw32-make install
清理中间文件:
mingw32-make clean
现在您应该有位于 icu/dist/lib 的静态库。
坑 4:静态链接时,您应该将库传递给
链接器以正确的顺序。这只对静态链接很重要。
但是如何确定哪个顺序是正确的呢?
这里 pkg-config 工具派上用场了。
它的作用如下:将库包名称作为
参数,计算依赖关系并返回完整的字符串
可以直接提供给编译器的参数
或由您查看以了解幕后情况。
有 5 个软件包位于 C:\icu\dist\lib\pkgconfig。
让我们为 pkg-config 配置路径:
export PKG_CONFIG_PATH="/c/icu/dist/lib/pkgconfig:$PKG_CONFIG_PATH"
为了测试它,输入:
pkg-config --static --cflags --libs icu-uc icu-i18n icu-io icu-le icu-lx
输出应该是:
-IC:/icu/dist/include -LC:/icu/dist/lib -lsicuio -lsicuin -lsiculx -lsicule -lsicuuc -lsicudt -lpthread -lm
这是我们必须传递给编译器的字符串。
作为最终测试,我们将使用命令行编译一个简单的示例应用程序:
创建文件夹/c/icu/dist/test,里面有文件test.cpp:
#include <unicode/unistr.h>
#include <unicode/ustdio.h>
#include <unicode/brkiter.h>
#include <stdlib.h>
using namespace icu;
void printUnicodeString(UFILE *out, const UnicodeString &s) {
UnicodeString other = s;
u_fprintf(out, "\"%S\"", other.getTerminatedBuffer());
}
int main( void )
{
UFILE *out;
UErrorCode status = U_ZERO_ERROR;
out = u_finit(stdout, NULL, NULL);
if(!out) {
fprintf(stderr, "Could not initialize (finit()) over stdout! \n");
return 1;
}
ucnv_setFromUCallBack(u_fgetConverter(out), UCNV_FROM_U_CALLBACK_ESCAPE,
NULL, NULL, NULL, &status);
if(U_FAILURE(status)) {
u_fprintf(out, "Warning- couldn't set the substitute callback - err %s\n", u_errorName(status));
}
/* End Demo boilerplate */
u_fprintf(out,"ICU Case Mapping Sample Program\n\n");
u_fprintf(out, "C++ Case Mapping\n\n");
UnicodeString string("This is a test");
u_fprintf(out, "\nstring: ");
printUnicodeString(out, string);
string.toUpper(); /* string = "THIS IS A TEST" */
u_fprintf(out, "\ntoUpper(): ");
printUnicodeString(out, string);
return 0;
}
转到测试目录:
cd /c/icu/dist/test
g++ -o test test.cpp \
`pkg-config --cflags --libs --static icu-uc icu-i18n icu-io icu-le icu-lx`
运行应用程序:
./test
也许这不是最好的方法,
特别是关于工作空间,但它确实有效。
更多关于 pgk-config 的信息在这里:
https://people.freedesktop.org/~dbn/pkg-config-guide.html