И наконец, я решил проблему. Чтобы поделиться своим опытом с вами Я расскажу о четырех основных подводных камнях, с которыми я столкнулся. Я предполагаю, что вы используете msys2 и MinGW-w32, если хотите повторить шаги.
Используйте ту же самую инструментальную цепочку для всего. Обратите внимание, что MinGW, MinGW-w32 и MinGW-w64 - это 3 различных инструментальных цепочки. Если у вас несколько установок MinGW , как я, убедитесь, что вы используете только один из них для всего проекта. Я выбрал MinGW-w32 по соображениям совместимости.
Новейшие версии программного обеспечения часто содержат ошибки, и они требуют от вас еще нескольких танцев с тамбуринами. ICU v58 был багги в момент написания этого сообщения. Решение состоит в том, чтобы вернуться к более старой версии (57,1 в моем случае).
Перед созданием библиотеки 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