如何静态链接我的应用程序与ICU 57.1 MinGW

时间:2016-12-14 13:27:50

标签: c++ static qt-creator mingw32 icu

我用MinGW x32静态构建了ICU 57.1; 结果,我在lib目录中获得了以下文件:

libsicudt.a
libsicuin.a
libsicuio.a
libsicule.a
libsiculx.a
libsicutest.a
libsicutu.a
libsicuuc.a
sicudt.a
sicudt.dll

现在我想运行其中一个示例,但无论我尝试什么 我收到的错误就像 " undeum引用unum _... unum_setAttribute unum_formatInt64 u_isspace&#34 ;. 开头的错误总数约为1700。 分析pkgconfig文件我发现了一些相互依赖关系 重新排序.ddd行中的.a文件将错误减少到82。

但我不知道下一步该往哪里去。 谷歌显示许多人与ICU有同样的问题但是 到目前为止,没有适合我的解决方案并解释原因。

构建时,我使用Qt Creator方便,这是我的.pro文件:

TEMPLATE = app
CONFIG += console c++11
CONFIG -= app_bundle
CONFIG -= qt

SOURCES += main.cpp

ICUDIR=$$(ICU_PATH)
ICU_LIBPATH=$$ICUDIR"/dist/lib/"
INCLUDEPATH += $$ICUDIR"/dist/include"

LIBS += $$ICU_LIBPATH"libsicuuc.a" $$ICU_LIBPATH"libsicudt.a"  \
$$ICU_LIBPATH"libsicuin.a" $$ICU_LIBPATH"libsicuio.a"  \
$$ICU_LIBPATH"libsicule.a" $$ICU_LIBPATH"libsiculx.a"  \
$$ICU_LIBPATH"libsicutu.a" $$ICU_LIBPATH"sicudt.a"

我有以下问题: 1)任何人都可以写一个静态构建的简单的一行命令 使用g ++的最简单的ICU应用程序?它甚至可能吗? 2).a文件传递给链接器时的正确顺序是什么? 3)libsicudt.a,sicudt.a和sicudt.dll所涉及的文件是什么? 4)我上面写的文件列表是完整的还是我的构建是否已损坏? 5)我有什么错过的错误吗?

1 个答案:

答案 0 :(得分:2)

最后,我解决了这个问题。为了与你分享我的经验 我将描述我遇到的四个主要陷阱。 如果你想重复这些步骤,我假设你使用msys2和MinGW-w32。

  1. 对所有内容使用相同的工具链。请注意MinGW,MinGW-w32和MinGW-w64 是3种不同的工具链。如果您有多个MinGW安装 像我一样,确保你只使用其中一个用于整个项目。 出于兼容性原因,我选择了MinGW-w32。

  2. 最新版本的软件通常包含错误和它们 要求你多用铃鼓跳舞。 在写这篇文章的那一刻,ICU v58有些错误。 解决方案是恢复到旧版本(在我的情况下为57.1)。

  3. 在构建ICU库之前,请确保正确设置所有内容。 这里的问题是使用命名空间和重命名命名空间 ICU默认使用。

  4. 找到文件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 / source目录:

    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 lib。如果你有4个核心,-j4可以加速这个过程:

    mingw32-make -j4
    mingw32-make install
    

    清理中间文件:

    mingw32-make clean
    

    现在你应该在icu / dist / lib上有静态库。

    PITFALL 4:静态链接时,应该将库传递给 链接器顺序正确。这仅适用于静态链接。 但是如何确定哪个顺序是正确的? 这里pkg-config工具很方便。 它的作用如下:将库包名称作为 参数,计算依赖关系并返回完整的字符串 可以直接提供给编译器的参数 或者由你了解,了解幕后发生的事情。

    C:\ icu \ dist \ lib \ pkgconfig中有5个软件包。 让我们为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
    

    这是我们必须传递给编译器的字符串。

    作为最终测试,我们将使用命令行编译一个简单的示例应用程序:

    使用文件test.cpp创建文件夹/ c / icu / dist / test:

    #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

相关问题