Как построить ICU, чтобы я мог использовать его в приложении для iPhone? - PullRequest
14 голосов
/ 14 ноября 2011

Как настроить и построить ICU, чтобы я мог связать его с моим приложением для iPhone?

Я поддерживаю приложение для iPhone, которое использует базу данных SQLite. Теперь я должен скомпилировать с включенной поддержкой ICU (SQLITE_ENABLE_ICU). У меня последний источник ICU.

Флаги configure, которые я использую:

./configure --target=arm-apple-darwin --enable-static --disable-shared

После этого запуск gnumake выполняется без ошибок.

Затем я добавляю библиотеки в свой проект Xcode. Но когда я строю, я получаю 50 строк этого:

Undefined symbols:
  "_uregex_close_48", referenced from:
      _icuRegexpDelete in libsqlite3-cerod.a(sqlite3_cerod.o)
  "_ubrk_current_48", referenced from:
      _icuNext in libsqlite3-cerod.a(sqlite3_cerod.o)
  "_ucol_strcoll_48", referenced from:
      _icuCollationColl in libsqlite3-cerod.a(sqlite3_cerod.o)
  "_u_isspace_48", referenced from:
      _icuRegexpFunc in libsqlite3-cerod.a(sqlite3_cerod.o)
  "_utf8_countTrailBytes_48", referenced from:
      _utf8_countTrailBytes_48$non_lazy_ptr in libsqlite3-cerod.a(sqlite3_cerod.o)
     (maybe you meant: _utf8_countTrailBytes_48$non_lazy_ptr)
  "_ubrk_next_48", referenced from:
      _icuNext in libsqlite3-cerod.a(sqlite3_cerod.o)

Есть идеи, что я делаю не так?

Отредактировано, чтобы добавить:

Когда я добавляю библиотеки в проект (щелкните правой кнопкой мыши на имени проекта, затем выберите «Добавить существующий ...»), я получаю следующее:

ld: warning: in /Users/eric.grunin/dev/iOS/icu/source/lib/libicudata.a, file was built for unsupported file format which is not the architecture being linked (i386)
ld: warning: in /Users/eric.grunin/dev/iOS/icu/source/lib/libicui18n.a, file was built for unsupported file format which is not the architecture being linked (i386)
ld: warning: in /Users/eric.grunin/dev/iOS/icu/source/lib/libicuio.a, file was built for unsupported file format which is not the architecture being linked (i386)
ld: warning: in /Users/eric.grunin/dev/iOS/icu/source/lib/libicule.a, file was built for unsupported file format which is not the architecture being linked (i386)
ld: warning: in /Users/eric.grunin/dev/iOS/icu/source/lib/libiculx.a, file was built for unsupported file format which is not the architecture being linked (i386)
ld: warning: in /Users/eric.grunin/dev/iOS/icu/source/lib/libicutu.a, file was built for unsupported file format which is not the architecture being linked (i386)
ld: warning: in /Users/eric.grunin/dev/iOS/icu/source/lib/libicuuc.a, file was built for unsupported file format which is not the architecture being linked (i386)

Вот почему я думаю, что я неправильно строю библиотеку. Это как будто говорит:

  • Он не может сказать, для какой архитектуры создаются файлы .a
  • libsqlite3-cerod.a построен для i386

Я не понимаю ни одной возможности, но я новичок в разработке для iPhone.

Отредактировано для добавления

Я попробовал решение @Sergio Moura и получил ошибку, упомянутую в моем комментарии.

Я попробовал решение @ sergio, которое построил. Но я все еще получаю эквивалентные ошибки, начиная с:

ld: warning: in /Users/eric.grunin/dev/iOS/icu/iosbuild/lib/libicudata.a, file was built for unsupported file format which is not the architecture being linked (i386)

Могу ли я сказать Xcode не то, что нужно? Я щелкаю правой кнопкой мыши по имени проекта, затем выбираю «Добавить-> Существующий файл» и выбираю шесть или семь .a файлов из /icu/iosbuild/lib. Это правильный процесс?

Примечание:

@ sergio рекомендует configure --host=arm-apple-darwin, @Sergio Moura использует configure --target=arm-apple-darwin. Увы, ничего не изменилось.

Редактировать # 2

Ориентация на устройстве (а не на эмуляторе) позволила устранить все ошибки, кроме одной! Вот что осталось:

Undefined symbols for architecture armv6:
  "___sync_synchronize", referenced from:
      _ucol_initUCA_48 in libicui18n.a(ucol_res.ao)
      udata_getHashTable()      in libicuuc.a(udata.ao)
      _umtx_init_48 in libicuuc.a(umutex.ao)
      _initCache in libicuuc.a(uresbund.ao)
      icu_48::hasService()       in libicui18n.a(coll.ao)
      _ucol_initInverseUCA_48 in libicui18n.a(ucol_bld.ao)
      icu_48::locale_set_default_internal(char const*)in libicuuc.a(locid.ao)
      ...
ld: symbol(s) not found for architecture armv6

Этому предшествовал каскад следующих предупреждений:

ld: warning: CPU_SUBTYPE_ARM_ALL subtype is deprecated: /Users/eric.grunin/dev/iOS/icu/iosbuild/lib/libicuuc.a(resbund.ao)
ld: warning: CPU_SUBTYPE_ARM_ALL subtype is deprecated: /Users/eric.grunin/dev/iOS/icu/iosbuild/lib/libicuuc.a(ustrfmt.ao)

Редактировать # 3

@ Предложение Стивена Р. Лумиса о том, чтобы я сменил #define U_HAVE_GCC_ATOMICS с 1 на 0platform.h), увы, не имело значения. Я также понял, что последняя строка ошибки (not found for architecture arm6) не означает, что она будет работать для arm7, это была только к сведению, что это была кросс-компиляция. Когда я указал сборку arm7, она не удалась с теми же сообщениями. Увы.

Редактировать # 4

Успех!

Резюме: флаги сборки @ sergio были по существу правильными. Я добавил -DU_HAVE_GCC_ATOMICS = 0 в CFLAGS сборки ios. Единственное, что я делал неправильно, это не осознавал, что мне нужно было кросс-компилировать библиотеку для создания сборки устройства.

Я не пытался повторить это для симулятора, но это выходит за рамки моего вопроса.

Особая благодарность Стивену Р. Лумису за подачу и Серхио Моуре за то, что все началось.

Ответы [ 4 ]

5 голосов
/ 17 ноября 2011

РЕДАКТИРОВАТЬ:

Я могу подтвердить, что если вы делаете, как Стивен Р. Лумис предлагает:

  1. установить U_HAVE_GCC_ATOMICS в 0 в icu / source / common / unicode/platform.h

  2. make distclean

  3. sh cross_configure.sh (используя мой скрипт, т. е. если вы его используете)

проблема должна быть решена.Действительно, без этого встроенные библиотеки содержат некорректный неопределенный символ:

sergio@sfogliatella$ nm -a ./lib/libicuuc.a | grep __sync_
     U ___sync_synchronize
     U ___sync_val_compare_and_swap_4
     U ___sync_synchronize
     U ___sync_synchronize
     U ___sync_synchronize
     U ___sync_synchronize
     U ___sync_synchronize
     U ___sync_synchronize
     U ___sync_synchronize
     U ___sync_synchronize
     U ___sync_synchronize
     U ___sync_synchronize
     U ___sync_synchronize

После выполнения приведенного выше предложения это результат для той же команды:

sergio@sfogliatella$ nm -a ./lib/libicuuc.a | grep __sync_
nm: no name list
nm: no name list

Итак,определенно, символ нарушения не присутствует в двоичных файлах.

END EDIT.

Кросс-компиляция libicu для iOS требует двух отдельных шагов:

  1. компиляция libicu для вашего хоста (MacOS) в каталоге сборки;

  2. кросс-компиляция libicu для iOS, также указав каталог кросс-компиляции.

Причина, по которой шаг 1 необходим, заключается в том, что libicu немного загрузится, то есть скомпилирует некоторые промежуточные инструменты, которые затем будут использованы в оставшейся части процесса сборки;эти инструменты должны быть запущены на платформе хоста, поэтому они должны быть доступны.

Ну, в общем, вы можете выполнить шаги (1. скомпилировать для хоста):

$ cd $icu
$ mkdir hostbuild
$ cd hostbuild
$ ../icu/source/configure <configure settings you need>
$ gnumake

Как только это будет сделано, пришло время кросс-компилировать (2. компилировать для iOS):

$ cd $icu  (or cd ../ from the previous directory)
$ mkdir iosbuild
$ cd iosbuild
$ sh ../cross_configure_icu.sh
$ gnumake

Где cross_configure_icu.sh - сценарий оболочки, аналогичный предложенному Серхио Моурой выше, но настроенныйдля libicu и использования более продвинутого компилятора llvm:

DEVROOT=/Developer/Platforms/iPhoneOS.platform/Developer
SDKROOT=$DEVROOT/SDKs/iPhoneOS4.3.sdk
SYSROOT=$SDKROOT

ICU_PATH=<ABSOLUTE_PATH_TO_YOUR_ICU_DIR>
ICU_FLAGS="-I$ICU_PATH/source/common/ -I$ICU_MYSRC/source/tools/tzcode/ "

export CXXPP=
export CXXPPFLAGS=
export CPPFLAGS="-I$SDKROOT/usr/lib/gcc/arm-apple-darwin10/4.2.1/include/ -I$SDKROOT/usr/llvm-gcc-4.2/lib/gcc/arm-apple-darwin10/4.2.1/include/ -I$SDKROOT/usr/include/ -I$SDKROOT/usr/include/c++/4.2.1/armv7-apple-darwin10/ -I./include/ -miphoneos-version-min=2.2 $ICU_FLAGS"

export CFLAGS="$CPPFLAGS -pipe -no-cpp-precomp -isysroot $SDKROOT"
export CPP="$DEVROOT/usr/bin/cpp $CPPFLAGS"
export CXXFLAGS="$CFLAGS" 
export CC="$DEVROOT/usr/llvm-gcc-4.2/bin/arm-apple-darwin10-llvm-gcc-4.2"
export CXX="$DEVROOT/usr/llvm-gcc-4.2/bin/arm-apple-darwin10-llvm-g++-4.2"
export LDFLAGS="-L$SDKROOT/usr/lib/ -isysroot $SDKROOT -Wl,-dead_strip -miphoneos-version-min=2.0"

sh $ICU_PATH/source/configure --host=arm-apple-darwin --enable-static --disable-shared -with-cross-build=$ICU_PATH/hostbuild

В приведенном выше сценарии ( source ) ICU_PATH является абсолютным путем, так как для настройки libicu требуется with-cross-buildвариант.Опять же, проверьте ваши значения для SDK и компиляторов, но это должно быть хорошо для 4.3.

Наконец, вы должны принять во внимание, что Apple (наполовину) отклонила хотя бы одно приложение, связанное с libicu, поскольку оно использует зарезервированные API.Взгляните на эту SO тему .

РЕДАКТИРОВАТЬ:

рад слышать, что вы могли скомпилировать!

сейчас, к проблеме связывания.

Прежде всего, пожалуйста, убедитесь, что библиотеки libicu имеют правильный формат:

sergio@sfogliatella$ lipo -info ./lib/libicuuc.a 

вывод должен быть (для любой библиотеки):

input file ./lib/libicuuc.a is not a fat file
Non-fat file: ./lib/libicuuc.a is architecture: arm

Если это нормально, тогда следующий вопрос: вы строите для симулятора или для устройства?симулятору нужны библиотеки i386, библиотеки устройств устройств ... из отображаемого сообщения об ошибке:

ld: warning: ... файл создан для неподдерживаемого формата файлов, который не связан с архитектурой (i386)

мне кажется, что вы строите против симулятора ... для этого вам понадобятся "нормальные" macos x libs ...

2 голосов
/ 02 мая 2013

Я использовал iOS SDK версии 6.1 с clang и сборкой на основе стандартной библиотеки c ++ 11.Я обнаружил, что установка переменных среды, таких как CXXFLAGS, не имела никакого эффекта, и попытка передать их в «configure» в командной строке, казалось, полностью его сломала.В итоге я создал скрипты clang, clang ++ и ld, которые позволили бы мне передавать дополнительные параметры.Например, мой скрипт clang:

#This script circumvents gnumake getting rid of our flags. Use the environment variable $MORE_CFLAGS
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang "$@" $MORE_CFLAGS

Остальные идентичны, но при необходимости замените clang ++ и ld и используйте MORE_CXXFLAGS и MORE_LDFLAGS соответственно.

Наконец, я создал этот скриптвыполняет сборку хоста, сборку симулятора и сборку iOS.Обратите внимание, что сборка симулятора включает отладочную информацию, а версия iOS оптимизирована для -O2.Затем он создает файлы libs (создает универсальный бинарный файл) и копирует их вместе с папкой include в цель, указанную в INSTALL_PATH.Строки 3-5 используются для настройки скрипта.Поместите все 4 этих сценария в одну папку и выполните последний из командной строки:

#unpack the ICU source and point $ICU_PATH at it

ICU_PATH="$HOME/Downloads/icu"
ICU_FLAGS="-I$ICU_PATH/source/common/ -I$ICU_PATH/source/tools/tzcode/ "
INSTALL_PATH="$HOME/Documents/git/gamelib/Graphics/Text/icu/51.1"
SDKROOT=`xcrun --sdk iphoneos --show-sdk-path`
SIMULATOR_SDKROOT=`xcrun --sdk iphonesimulator --show-sdk-path`


SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
SAVEPATH=$PATH

cd $ICU_PATH
mkdir host_build
cd host_build
../source/configure
gnumake

PATH=$SCRIPT_DIR:/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/:/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:$SAVEPATH
cd $ICU_PATH
mkdir iPhoneSimulator_build
cd iPhoneSimulator_build
#PATH points to the folder that contains this script, which should also contain scripts titled clang, clang++, and ld
#those scripts call the actual clang, clang++, and ld, appending MORE_CFLAGS, MORE_CXXFLAGS, and MORE_LDFLAGS respectively
export MORE_CFLAGS="-arch i386 -pipe -std=c99 -fmessage-length=0 -fvisibility=hidden -miphoneos-version-min=5.0 -isysroot $SIMULATOR_SDKROOT $ICU_FLAGS"
export MORE_CXXFLAGS="-arch i386 -pipe -std=c++11 -stdlib=libc++ -fmessage-length=0 -fvisibility=hidden -miphoneos-version-min=5.0 -isysroot $SIMULATOR_SDKROOT $ICU_FLAGS"
export MORE_LDFLAGS="-arch i386 -isysroot $SIMULATOR_SDKROOT -miphoneos-version-min=5.0"
$ICU_PATH/source/configure --enable-debug --disable-release --with-cross-build="$ICU_PATH/host_build" --prefix="$ICU_PATH/iPhoneSimulator_build/install" --enable-static=yes --enable-shared=no
gnumake clean
gnumake VERBOSE=1 install

PATH=$SCRIPT_DIR:/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin:/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:$SAVEPATH
cd $ICU_PATH
mkdir iPhoneOS_build
cd iPhoneOS_build
#PATH points to the folder that contains this script, which should also contain scripts titled clang, clang++, and ld
#those scripts call the actual clang, clang++, and ld, appending MORE_CFLAGS, MORE_CXXFLAGS, and MORE_LDFLAGS respectively
export MORE_CFLAGS="-arch armv7 -pipe -std=c99 -O2 -fmessage-length=0 -fvisibility=hidden -miphoneos-version-min=5.0 -isysroot $SDKROOT $ICU_FLAGS"
export MORE_CXXFLAGS="-arch armv7 -pipe -std=c++11 -stdlib=libc++ -O2 -fmessage-length=0 -fvisibility=hidden -miphoneos-version-min=5.0 -isysroot $SDKROOT $ICU_FLAGS"
export MORE_LDFLAGS="-arch armv7 -isysroot $SDKROOT -miphoneos-version-min=5.0"
$ICU_PATH/source/configure --host=arm-apple-darwin --with-cross-build="$ICU_PATH/host_build" --prefix="$ICU_PATH/iPhoneOS_build/install" --enable-static=yes --enable-shared=no
gnumake clean
gnumake VERBOSE=1 install

PATH=$SAVEPATH

mkdir "$INSTALL_PATH/lib"
for file in $ICU_PATH/iPhoneOS_build/install/lib/*.a; do
    BASENAME="${file##*/}"
    lipo "$ICU_PATH/iPhoneOS_build/install/lib/$BASENAME" "$ICU_PATH/iPhoneSimulator_build/install/lib/$BASENAME" -create -output "$INSTALL_PATH/lib/$BASENAME"
done

rm -r "$INSTALL_PATH/include"
cp -r "$ICU_PATH/iPhoneOS_build/install/include" "$INSTALL_PATH/include"
1 голос
/ 18 ноября 2011

re: sync synchronize: кто-то может лгать об атомах, или нужна какая-то библиотека gcc. попробуйте #define U_HAVE_GCC_ATOMICS 0 в верхней части icu / source / common / unicode / uconfig.h (примечание: ARM, по-видимому, имеет слабую модель памяти, поэтому это изменение приведет к большему количеству блокировок / разблокировок, чем было бы необходимо, но все еще в безопасности.)

1 голос
/ 17 ноября 2011

Если у вас есть источник, вам действительно нужно связать библиотеку? Просто добавьте исходники в ваш проект XCode, и вам будет хорошо ...

Если вы действительно хотите собрать библиотеку, я бы предложил вам создать проект XCode для библиотеки с iPhone в качестве вашей цели и связать эту библиотеку с вашим кодом, поскольку ваша библиотека создана для работы в MacOS компьютер (согласно вашим журналам ошибок).

EDIT

Чтобы собрать его из командной строки и предположить, что вы не используете iOS 5 (из-за вашей версии XCode), я позаимствовал и адаптировал этот набор инструкций для правильной настройки флагов для правильной настройки и построения двоичных файлов. на вашу платформу с здесь :

export IOS_BASE_SDK=4.2
export IOS_DEPLOY_TGT=4.2
export DEVROOT=/Developer/Platforms/iPhoneOS.platform/Developer
export SDKROOT=$DEVROOT/SDKs/iPhoneOS$IOS_BASE_SDK.sdk
export CFLAGS="-arch armv7 -pipe -no-cpp-precomp -isysroot $SDKROOT -miphoneos-version-min=$IOS_DEPLOY_TGT -I$SDKROOT/usr/include/"

export CPP=$DEVROOT/usr/bin/cpp-4.2
export CXX=$DEVROOT/usr/bin/g++-4.2
export CXXCPP=$DEVROOT/usr/bin/cpp-4.2
export CC=$DEVROOT/usr/bin/gcc-4.2
export LD=$DEVROOT/usr/bin/ld
export AR=$DEVROOT/usr/bin/ar
export AS=$DEVROOT/usr/bin/as
export NM=$DEVROOT/usr/bin/nm
export RANLIB=$DEVROOT/usr/bin/ranlib
export LDFLAGS="-L$SDKROOT/usr/lib/"

export CPPFLAGS=$CFLAGS
export CXXFLAGS=$CFLAGS

./configure --target=arm-apple-darwin --enable-static --disable-shared

Пожалуйста, правильно установите версию IOS в первых двух инструкциях на правильное значение вашей среды.

Если вы собираетесь использовать iOS 5 SDK, вам нужно изменить имя двоичных файлов компилятора, поскольку они изменились.

...