2016-12-14 24 views
1

Я построил ICU 57.1 статически с MinGW x32; В результате я получил следующие файлы в каталоге LIB:Как связать мое приложение статически с ICU 57.1 MinGW

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

Теперь я хочу, чтобы запустить один из примеров, но все, что я пытаюсь его я получаю ошибки «неопределенной ссылки на unum_ .. . unum_setAttribute unum_formatInt64 u_isspace ". Общего количества ошибок в начале было около 1700. Анализа pkg-config файлов я выяснял некоторые взаимные зависимости и после переназначения .a файлов в CMD линий уменьшенных ошибок в 82.

Но я понятия не имею, куда идти дальше , Google показывает, что у многих людей такая же проблема с 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) Кто-нибудь может написать простую команду на одну строки, которая статический строит в Простейшем Приложение ICU с использованием g ++? Возможно ли это? 2) Каков правильный порядок файлов .a при передаче их в компоновщик? 3) Что представляют собой файлы libsicudt.a, sicudt.a и sicudt.dll? 4) Является ли список файлов, который я написал выше, или моя сборка повреждена? 5) Есть ли что-то, что я упустил, чтобы сделать что-то неправильно?

ответ

2

И наконец, я решил проблему. Чтобы поделиться своим опытом с вами Я расскажу о четырех основных подводных камнях, с которыми я столкнулся. Я предполагаю, что вы используете msys2 и MinGW-w32, если хотите повторить шаги.

  1. Используйте ту же самую инструментальную цепочку для всего. Обратите внимание, что MinGW, MinGW-w32 и MinGW-w64 - это 3 различных инструментальных цепочки. Если у вас несколько установок MinGW , как я, убедитесь, что вы используете только один из них для всего проекта. Я выбрал MinGW-w32 по соображениям совместимости.

  2. Новейшие версии программного обеспечения часто содержат ошибки, и они требуют от вас еще нескольких танцев с тамбуринами. ICU v58 был багги в момент написания этого сообщения. Решение состоит в том, чтобы вернуться к более старой версии (57,1 в моем случае).

  3. Перед созданием библиотеки ICU обязательно настройте все правильно. Здесь проблема заключается в использовании пространств имен и переименовании пространств имен, которые по умолчанию имеют ICU.

Найти файл C: \ Icu \ источник \ Common \ юникода \ 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 

Настройка СИС для статической сборки, без переименования и 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. -j4 ускоряет процесс, если у вас есть 4 ядра:

mingw32-make -j4 
mingw32-make install 

Cleanup промежуточные файлы:

mingw32-make clean 

Теперь вы должны иметь статические библиотеки, расположенные в Icu/дист/Lib.

PITFALL 4: при связывании статически вы должны передавать библиотеки на компоновщик в правильном порядке. Это имеет значение только для статической привязки. Но как выяснить, какой заказ правильный? Здесь инструмент pkg-config подходит. Что он делает, это следующее: принимает имена пакетов библиотеки как параметр, вычисляет зависимости и возвращает полную строку параметров, которые могут быть переданы непосредственно компилятору или просмотрены вами, чтобы понять, что происходит под капотом.

Существует 5 пакетов, расположенных по адресу C: \ icu \ dist \ lib \ pkgconfig. Давайте настроим путь для PKG-конфигурации:

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 

Это строка, которую мы должны пройти для компилятора.

В окончательном испытании, мы подготовим простой пример приложения с помощью командной строки:

Создать папку/с/Icu/DIST/тест с файла 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 

Возможно, это не лучший способ, особенно в отношении рабочих областей, но он работает.

Подробнее о ПГК-конфигурации здесь: https://people.freedesktop.org/~dbn/pkg-config-guide.html