Как построить ICU, чтобы я мог использовать его в приложении для iPhone?
Как настроить и настроить 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
до 0
(в platform.h
), не имеет никакого значения, увы. Я также понял, что последняя строка ошибки (not found for architecture arm6
) не означает, что она будет работать для arm7
, это было всего лишь fyi, что это было кросс-компиляция. Когда я указал конструкцию arm7
, она не с теми же сообщениями. Увы.
Изменить # 4
Успех!
Сводка: флаги сборки @sergio были в основном правильными. Я добавил -DU_HAVE_GCC_ATOMICS = 0 в iOS build CFLAGS. Единственное, что я делал неправильно, не понимал, что мне нужно перекрестно скомпилировать библиотеку для создания сборки устройства.
Я не пытался повторить это для симулятора, но это выходит за рамки моего вопроса.
Особая благодарность Стивену Лумису за подачу, а также Серхио Муре за то, что он начал кататься.
Ответы
Ответ 1
EDIT:
Я могу подтвердить, что если вы это сделаете, как предлагает Стивен Р. Лумис:
-
установите U_HAVE_GCC_ATOMICS в 0 в icu/source/common/unicode/platform.h
-
сделать distclean
-
sh cross_configure.sh(используя мой script, т.е. если вы его используете)
проблема должна быть решена. Действительно, без этого встроенные библиотеки содержат оскорбительный символ undefined:
[email protected]$ 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
Следуя приведенному выше предложению, это результат для той же команды:
[email protected]$ nm -a ./lib/libicuuc.a | grep __sync_
nm: no name list
nm: no name list
Итак, определенно, нарушительный символ отсутствует в двоичных файлах.
END EDIT.
Кросс-компиляция libicu для iOS требует двух отдельных шагов:
-
компиляция libicu для вашего хоста (MacOS) в каталоге сборки;
-
кросс-компиляция 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
- это оболочка script, аналогичная предложенной Серджио Моурой выше, но настроенная для 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
В приведенном выше script (source), ICU_PATH
- это абсолютный путь, потому что libicu configure так требует для with-cross-build
вариант. Опять же, проверьте свои значения для SDK и компиляторов, но это должно быть нормально для 4.3.
Наконец, вы должны принять во внимание, что Apple (половина) отклонила хотя бы одно приложение, которое было связано с libicu, поскольку оно использует зарезервированные API. Посмотрите на это S.O. тема.
EDIT:
счастлив услышать, что вы можете скомпилировать!
теперь, к проблеме связывания.
прежде всего, убедитесь, что библиотеки libicu находятся в правильном формате:
[email protected]$ lipo -info ./lib/libicuuc.a
вывод должен быть (для любой из lib):
input file ./lib/libicuuc.a is not a fat file
Non-fat file: ./lib/libicuuc.a is architecture: arm
Если это в порядке, то следующий вопрос: строите ли вы для симулятора или для устройства? симулятору нужны библиотеки i386, библиотеки устройств... из сообщения об ошибке, которое вы показываете:
ld: warning:... был создан для неподдерживаемого формата файла, который не связан с архитектурой (i386)
мне кажется, что вы строите против симулятора... для этого вам понадобятся "обычные" макросы x libs...
Ответ 2
Я использовал iOS SDK версии 6.1, с clang и созданием против стандартной библиотеки С++ 11. Я обнаружил, что настройка переменных среды, таких как CXXFLAGS, не повлияла, и попытка передать их в "configure" в командной строке, казалось, полностью нарушила ее. Я закончил создание clang, clang++ и ld скриптов, которые позволили бы мне передать дополнительные параметры. Например, мой clang script:
#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 "[email protected]" $MORE_CFLAGS
Другие идентичны, но заменяйте clang++ и ld, где это необходимо, и используйте MORE_CXXFLAGS и MORE_LDFLAGS соответственно.
Наконец, я сделал это script, который делает сборку хоста, сборку симулятора и сборку iOS. Обратите внимание, что сборка симулятора включает в себя информацию об отладке, а версия iOS оптимизирована -O2. Затем он липос libs (делает универсальный двоичный файл) и копирует их вместе с включенной папкой в цель, указанную INSTALL_PATH. Строки 3-5 используются для настройки script. Поместите все 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"
Ответ 3
Если у вас есть источник, вам действительно нужно связать библиотеку? Просто добавьте источники в свой проект XCode, и вам должно быть хорошо идти...
Если вы действительно хотите создать библиотеку, я бы предложил вам создать проект XCode для библиотеки с iPhone в качестве вашей цели и связать эту библиотеку с вашим кодом, поскольку ваша библиотека построена для работы в вашем MacOS компьютер (согласно вашим журналам ошибок).
ИЗМЕНИТЬ
Чтобы создать его из командной строки и предположив, что вы не используете 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, вам нужно будет изменить имя двоичных файлов компилятора, поскольку они были изменены.
Ответ 4
re: синхронизация синхронизации: кто-то может лгать об атоматике или нужна библиотека gcc. попробуйте #define U_HAVE_GCC_ATOMICS 0
в верхней части icu/source/common/unicode/uconfig.h (обратите внимание: у ARM, похоже, есть слабая модель памяти, поэтому это изменение приведет к большей блокировке/разблокировке, чем в противном случае было бы необходимо, но все еще в безопасности.)