Что хочу? Получить статическую сборку icu, без внешних зависимостей от библиотек и файлов данных. В качестве подопытной буду использовать программу, которая должна правильно посчитать длину строки в “китайских буквах” 😉
#include <iostream>
#include <fstream>
#include <unicode/unistr.h>
#include <unicode/locid.h>
#include <unicode/brkiter.h>
int main() {
const icu::UnicodeString str(L"नमस्ते");
UErrorCode err = U_ZERO_ERROR;
std::unique_ptr<icu::BreakIterator> iter(icu::BreakIterator::createCharacterInstance(icu::Locale::getDefault(), err));
if (U_FAILURE(err)) {
std::cout << u_errorName(err) << std::endl;
return -1;
}
iter->setText(str);
int count = 0;
while (iter->next() != icu::BreakIterator::DONE) {
++count;
}
std::cout << std::string((3==count)?"GREAT SUCCESS":"EPIC FAIL") << std::endl;
return 0;
}
Прежде всего нам понадобятся:
Приступаем к сборке.
- Переходим по ссылке, выбираем нужную версию и скачиваем архив с исходным кодом (icu4c-69_1-src.zip)
- Распаковываем, например в корень T:\
- В icu\source\common\unicode\uconfig.h сразу после header guards добавляем строчку
#define U_DISABLE_RENAMING 1
чтобы получилось примерно так:
// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
**********************************************************************
* Copyright (C) 2002-2016, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
* file name: uconfig.h
* encoding: UTF-8
* tab size: 8 (not used)
* indentation:4
*
* created on: 2002sep19
* created by: Markus W. Scherer
*/
#ifndef __UCONFIG_H__
#define __UCONFIG_H__
#define U_DISABLE_RENAMING 1
<...>
- Запускаем MSYS2 и переходим в /t/icu/source
- Настраиваем окружение так, чтобы использовался наш MinGW и Python:
export PATH=/c/dev/8.1.0/x64/mingw/bin:/c/dev/tools/python39:$PATH
- Настраиваем флаги компилятора для правильной статической сборки:
export CFLAGS="-DU_STATIC_IMPLEMENTATION=1 -DU_DISABLE_RENAMING=1 -static"
export CXXFLAGS="-DU_STATIC_IMPLEMENTATION=1 -static-libstdc++ -static -std=c++11"
- Конфигурируем ICU:
./runConfigureICU MinGW prefix=/c/dev/8.1.0/x64/icu4c-69_1/static -disable-shared -enable-static --disable-renaming --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 --with-data-packaging=static
- Пытаемся собрать:
mingw32-make
У меня сборка сломается на makeconv из-за того, что имена статических библиотек icu отличаются от ожидаемых
x86_64-w64-mingw32-g++ -O3 -DU_STATIC_IMPLEMENTATION=1 -static-libstdc++ -static -std=c++11 -W -Wall -pedantic -Wpointer-arith -Wwrite-strings -Wno-long-long -mthreads -o ../../bin/makeconv.exe gencnvex.o genmbcs.o makeconv.o ucnvstat.o -L../../lib "-licutu" -L../../lib "-licuin" -L../../lib "-licuuc" -L../../stubdata "-licudt" -lpthread -lm
C:/dev/8.1.0/x64/mingw/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find -licutu
C:/dev/8.1.0/x64/mingw/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find -licuin
C:/dev/8.1.0/x64/mingw/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find -licuuc
C:/dev/8.1.0/x64/mingw/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find -licudt
collect2.exe: error: ld returned 1 exit status
mingw32-make[2]: *** [Makefile:81: ../../bin/makeconv.exe] Error 1
mingw32-make[2]: Leaving directory 'T:/icu/source/tools/makeconv'
mingw32-make[1]: *** [Makefile:47: all-recursive] Error 2
mingw32-make[1]: Leaving directory 'T:/icu/source/tools'
mingw32-make: *** [Makefile:153: all-recursive] Error 2
поэтому…
- Переименовываем библиотеки:
mv lib/lib{s,}icuin.a
mv lib/lib{s,}icuio.a
mv lib/lib{s,}icutu.a
mv lib/lib{s,}icuuc.a
mv stubdata/lib{s,}icudt.a
- Продолжаем сборку:
mingw32-make
Сборка должна завершиться успешно. На данный момент мы имеем статически собранный ICU, без внешних зависимостей от библиотек, но с заглушкой вместо библиотеки данных. Исправим это.
- Копируем библиотеку данных на место заглушки:
cp lib/libsicudt.a stubdata/libsicudt.a
cp lib/libsicudt.a stubdata/libicudt.a
- Удаляем собранные исполнимые файлы, поскольку они собраны с заглушкой:
rm ./bin/*
- Повторно собираем исполнимые файлы и, наконец, устанавливаем библиотеку:
mingw32-make all install
Всё. Можно скомпилировать и запустить нашу программу.
$ g++ main.cpp -o main -static -L/c/dev/8.1.0/x64/icu4c-69_1/static/lib/ -I/c/dev/8.1.0/x64/icu4c-69_1/static/include -lsicuuc -lsicudt
$ ./main.exe
GREAT SUCCESS
$
Если используется система сборки qmake, в pro файле библиотека подключается так:
LIBS += -LC:/dev/8.1.0/x64/icu4c-69_1/static/lib/
LIBS += -lsicuin
LIBS += -lsicutest
LIBS += -lsicutu
LIBS += -lsicuio
LIBS += -lsicuuc
LIBS += -lsicudt
INCLUDEPATH += C:/dev/8.1.0/x64/icu4c-69_1/static/include
DEPENDPATH += C:/dev/8.1.0/x64/icu4c-69_1/static/include