Скомпилируйте несколько статических библиотек в одну платформу iOS
У меня есть большая статическая библиотека, которую я хотел бы упаковать в статическую платформу iOS для простоты использования. Библиотека на самом деле несколько .a
файлы, по одному на логический модуль библиотеки.
У меня есть скомпилированный .a
файлы, созданные для устройства (толстый файл с armv7
, armv7s
, arm64
) и для симулятора (толстый файл с i386
, x86_64
).
Теперь, AFAIK, мне нужно объединить все эти файлы в один большой файл, чтобы создать правильную структуру.
Используя описанную здесь технику ( объединение статических библиотек), я мог бы сделать:
libtool -static -o new.a old1.a old2.a
Но, видимо, оба old1.a
а также old2.a
включать в себя те же символы. Таким образом, при связывании с моей структурой, я получаю ошибку компоновщика (по уважительной причине) duplicate symbols
,
Более правильный способ сделать это (таким образом избегая повторяющихся символов), кажется, распаковывает .o
файлы, и объединяя их в большой .a
файл ( Как упаковать несколько библиотечных архивов (.a) в один архивный файл?)
ar x old1.a
ar x old2.a
ar rcs new.a *.o
Теперь запомни, old1.a
а также old2.a
толстые файлы, поэтому мне нужно отделить их для каждой архитектуры.
Итак, вот что я делаю:
lipo old1.a -thin armv7 -output armv7/old1.a
cd armv7; ar x old1.a; cd ..
...
lipo old1.a -thin x86_64 -output x86_64/old1.a
cd x86_64; ar x old1.a; cd ..
// Same goes for old2.a ...
// Then,
libtool -static -o new.a armv7/*.o armv7s/*.o arm64/*.o // ... etc
Но по какой-то причине при связывании с созданным таким образом фреймворком компоновщик не может найти какой-либо символ (хотя nm
раскрывает их всех).
Любая идея, как построить эту статическую структуру?
2 ответа
Вы можете предварительно связать ваши объекты статической библиотеки в один, также вы можете предварительно связать другие статические библиотеки в один. На самом деле он будет связывать объекты с компоновщиком (почти как в динамической библиотеке).
- В вашей единственной библиотеке (основной) перейдите в "Настройки сборки" и найдите "Выполнить предварительную ссылку на один объект" в разделах "Связывание". Переключите это на Да
- В Prelink библиотеки вы можете указать другие библиотеки, которые вы хотите включить. Там нужно указывать не только имена, но и полное имя файла. Если другие библиотеки также из вашего проекта, то вы можете использовать переменную $(CONFIGURATION_BUILD_DIR). Так что если у вас есть библиотека foo, то это будет $(CONFIGURATION_BUILD_DIR)/libfoo.a
- Вы можете добавить дополнительные флаги в флаги предварительной ссылки на один объект
- Если вы хотите удалить локальные символы, убедитесь, что для параметра Постобработка развертывания установлено значение Да, поскольку статические библиотеки по умолчанию не удаляются.
Если в ваших библиотеках есть повторяющиеся символы, значит, что-то не так в структуре ваших модулей.
- Если они являются одинаковыми функциями, то разделите их в отдельной статической библиотеке и используйте повторно из других мест.
- Если эти символы на самом деле отличаются и имеют одно и то же имя, рассмотрите возможность объявления их как статических (если это ANSI C). Вы также можете
- Вы можете настроить некоторые локальные символы с помощью настройки видимости ( http://llvm.org/docs/LangRef.html, http://gcc.gnu.org/wiki/Visibility).
Действительно ли libtool создает толстую библиотеку? Мы делаем что-то похожее, но напрямую используем "lipo-create"
ar -r armv7.a a/armv7/*.o b/armv7/*.o c/armv7/*.o d/armv7/*.o e/armv7/*.o
ar -r armv7s.a a/armv7s/*.o b/armv7s/*.o c/armv7s/*.o d/armv7s/*.o e/armv7s/*.o
ar -r i386.a a/i386/*.o b/i386/*.o c/i386/*.o d/i386/*.o e/i386/*.o
$LIPO \
-create \
-arch armv7 "objs/armv7.a" \
-arch i386 "objs/i386.a" \
-o "$FRAMEWORK_INSTALL_NAME" \
|| abort "Lipo $1 failed"
Мы также столкнулись с проблемой, когда isv делал то же самое с нашими фреймворками, чтобы создать их фреймворк, так что, хотя a/foo.o и b/foo.a отлично подходили для нашего armv7.o. когда они извлекают "ar -x", ar не сохраняет пути, поэтому пишется только один файл foo.o.
Мы исправили это, просто переименовав каждый.o и присвоив ему префикс a_foo.o, перед созданием target.a.