Подтвердить что ты не робот

Статическая библиотека с использованием фреймворков в конкретных проектах

Я создал статическую библиотеку, содержащую все мои общие классы. Некоторые из этих классов используют фреймворки.

Теперь у меня есть два проекта, один из которых использует некоторые классы, которые используют фреймворки, и тот, который не использует ни один из классов, которые используют фреймворки.

Потому что Static Libraries не поддерживают в том числе фреймворки (если я прав). Я должен включить рамки в проект, который их использует. Но когда я компилирую проект, который не использует какой-либо из фрейм-классов, компилятор ломается, потому что он все еще требует фреймворков. Теперь я знаю, что он пытается скомпилировать все (неиспользуемые) классы из библиотеки, потому что я использую флаг компоновщика '-ObjC' для предотвращения ошибок "непризнанного селектора".

Кто-нибудь знает, как компилировать только требуемые исходные файлы для каждого проекта? И предотвратить включение всех фреймворков во все проекты, использующие мою статическую библиотеку?

4b9b3361

Ответ 1

Прежде всего, вы правы в том, что статическая библиотека не может включать какую-либо фреймворк или другие статические библиотеки, это всего лишь коллекция всех объектных файлов (*.obj), которые составляют эту конкретную статическую библиотеку.

Кто-нибудь знает, как скомпилировать только требуемые исходные файлы для каждого проекта?

Линкером по умолчанию будет ссылка только в объектных файлах из статической библиотеки, содержащей символы, на которые ссылается приложение. Итак, если в вашей статической библиотеке есть два файла a.m и b.m, и вы используете только символы из a.m в своей основной программе, тогда b.o (объектный файл, сгенерированный из b.c) не будет отображаться в ваш окончательный исполняемый файл. В качестве подфайла, если b.m использует функцию/класс c, которая объявляется (не реализована), то вы не получите никаких ошибок компоновщика. Как только вы включите некоторые символы из b.m в вашу программу, b.o также будет связан, и вы получите ошибки компоновщика из-за отсутствия реализации c.

Если вы хотите, чтобы этот вид выбора выполнялся с символом, а не на уровне детализации уровня объекта, включите удаление кода в Xcode. Это соответствует опции gcc -Wl, -dead_strip (= linker option -dead_strip в панели сведений о настройках сборки для вашего проекта). Это обеспечит дальнейшую оптимизацию.

В вашем случае, однако, как вы правильно говорите, это использование флага компоновщика "-ObjC", который побеждает этот механизм. Так что это на самом деле зависит от вас. Если вы удаляете флаг -Objc, вы получаете бесплатное поведение, но теряете более строгую проверку на селекторах.

И предотвратить включение всех фреймворков во все проекты, использующие мою статическую библиотеку?

Xcode/GCC поддерживает ссылку, которая называется " слабая связь", которая позволяет лениво загружать фреймворк или статическую библиотеку, т.е. только когда используется один из его символов. "слабая связь" может быть активирована либо через флаг компоновщика (см. документ Apple выше), либо через интерфейс Xcode (Target → Info → General → Linked Libraries).

Во всяком случае, фреймворк или библиотека должны быть доступны во всех случаях во время компиляции/ссылки: параметр "слабый" влияет только на момент, когда среда сначала загружается во время выполнения. Таким образом, я не думаю, что это полезно для вас, так как вам все равно понадобится включить фреймворк во все ваши проекты, чего вы не хотите.

В качестве дополнительной заметки, weak_linking - это вариант, который в основном имеет смысл при использовании функций, доступных только на более новой версии SDK (скажем, 4.3.2), а также поддерживает развертывание в более старых версиях SDK (скажем, 3.1.3). В этом случае вы полагаетесь на то, что новые каркасы SDK будут фактически доступны на новых устройствах развертывания, и вы условно компилируете требуемые функции, чтобы на старых устройствах они не требовались (и не будут выдаваться таким образом попытка загрузки новой версии фреймворка и сбоя).


Чтобы ухудшить ситуацию, GCC не поддерживает функцию, называемую "автосвязь" с компиляторами Microsoft, которые позволяют указать, какую библиотеку связывать с помощью комментария #pragma в исходном файле. Это может предложить обходной путь, но его нет.


Итак, мне очень жаль, что нужно сказать, что вы должны использовать другой подход, который в равной степени может удовлетворить ваши потребности:

  • удалить флаг -ObjC;

  • разделяет вашу статическую библиотеку в двух или более частях в зависимости от их зависимостей от внешних фреймворков;

  • обратиться к исходным файлам напрямую.

Ответ 2

В качестве второй части вашего вопроса вы можете пометить связанную структуру как Optional: Optional framework

О первой части мне непонятно, что вы намереваетесь сделать:

  • Библиотека, объявленная в проекте
  • Проект, объявляющий, какие файлы скомпилированы (через Target > Build phase > Compile sources)
  • Если не устанавливать сложные правила сборки для включения или отсутствия файлов, которые, если я хорошо помню, могут быть выполнены с использованием файлов .xcconfig, я не вижу других решений, кроме разделения вашей библиотеки. Который я бы рекомендовал, для его легкости. Вы должны сделать несколько целей в одном проекте... Вы также можете использовать прекомпилятор MACROS (#ifdef...), но это зависит от того, что вы хотите сделать.

Ответ 3

Похоже, у вас есть раздувание библиотеки. Чтобы все было немного, я думаю, вам нужно реорганизовать вашу библиотеку в отдельные библиотеки с минимальными зависимостями. Вы можете попробовать включить "Dead Code Stripping" в разделе "Linker Flags" в информации о цели сборки (Xcode 3.x), чтобы узнать, делает ли это то, что вы хотите (не требует фреймворков, используемых классами,.)

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

Ответ 4

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

Поскольку у вас есть исходный код для библиотеки, почему бы просто не добавить код непосредственно в каждое приложение? Таким образом, вы можете точно контролировать, что входит в каждое приложение. Вы все равно можете объединить свои общие классы в одном месте и использовать один и тот же код в обоих приложениях, но вы избегаете проблем с использованием библиотеки.