Статическая сборка ICU4С 69.1

Что хочу? Получить статическую сборку 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;
}

Прежде всего нам понадобятся:

  1. MinGW
  2. MSYS2
  3. Python

Приступаем к сборке.

  1. Переходим по ссылке, выбираем нужную версию и скачиваем архив с исходным кодом (icu4c-69_1-src.zip)
  2. Распаковываем, например в корень T:\
  3. В 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

<...>
  1. Запускаем MSYS2 и переходим в /t/icu/source
  2. Настраиваем окружение так, чтобы использовался наш MinGW и Python:
export PATH=/c/dev/8.1.0/x64/mingw/bin:/c/dev/tools/python39:$PATH
  1. Настраиваем флаги компилятора для правильной статической сборки:
export CFLAGS="-DU_STATIC_IMPLEMENTATION=1 -DU_DISABLE_RENAMING=1 -static"
export CXXFLAGS="-DU_STATIC_IMPLEMENTATION=1 -static-libstdc++ -static -std=c++11"
  1. Конфигурируем 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
  1. Пытаемся собрать:
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

поэтому…

  1. Переименовываем библиотеки:
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
  1. Продолжаем сборку:
mingw32-make

Сборка должна завершиться успешно. На данный момент мы имеем статически собранный ICU, без внешних зависимостей от библиотек, но с заглушкой вместо библиотеки данных. Исправим это.

  1. Копируем библиотеку данных на место заглушки:
cp lib/libsicudt.a stubdata/libsicudt.a
cp lib/libsicudt.a stubdata/libicudt.a
  1. Удаляем собранные исполнимые файлы, поскольку они собраны с заглушкой:
rm ./bin/*
  1. Повторно собираем исполнимые файлы и, наконец, устанавливаем библиотеку:
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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *