Когда мы должны использовать «встроенные двоичные файлы», а не «связанные структуры» в XCode?


140

Есть хороший вопрос о разнице между этими двумя вариантами, как описано в Link Binary с библиотеками VS Embed Frameworks .

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

Какие-нибудь убедительные примеры, чтобы решить эту проблему более четко? Спасибо


Ответы:


239

Вопрос, который вы связали, ссылается на функциональность «Связать двоичный файл с библиотеками», которая несколько отличается от встроенного двоичного файла.

«Link Binary With Libraries» означает то, что вы ожидаете от связывания: независимо от того, является ли двоичный файл статической библиотекой, динамической библиотекой или структурой, он будет связан с вашим объектным кодом во время компоновки после компиляции.

Когда вы думаете о связывании со статической библиотекой, то, что происходит, довольно ясно: компоновщик копирует код из библиотеки (например,libFoo.a ) в ваш выходной двоичный файл. Ваш выходной файл увеличивается в размере, но не требует разрешения каких-либо внешних зависимостей во время выполнения. Все, что нужно для запуска вашей программы (относительно статической библиотеки), присутствует после ее сборки.

С динамической библиотекой (.dylib, или системным фреймворком) ожидается, что библиотека, с которой вы связываетесь, будет присутствовать где-то на пути загрузчика динамической библиотеки системы при запуске вашей программы. Таким образом, вам не нужно копировать все сторонние внешние библиотеки в ваш двоичный файл, и все различные программы на компьютере, которые также ссылаются на эту библиотеку, смогут найти его, что экономит минимальное дисковое пространство, но также потенциально пространство памяти, в зависимости от того, как и где система кэширует библиотеки.

Фреймворк очень похож на динамическую библиотеку, но может содержать ресурсы в своей структуре каталогов (изображения, аудио, другие фреймворки и т. Д.). В этом случае простая статическая библиотека или файл .dylib не обрежет его, поэтому вам, возможно, придется ссылаться на фреймворк, чтобы он мог найти то, что ему нужно для правильной работы.

Когда вы ссылаетесь на сторонний фреймворк (скажем, что-то, что вы скачали с github и создали сами), он может отсутствовать в системе, на которой вы собираетесь работать. В этом случае вы не только создадите ссылку на фреймворк, но и внедрите его в свой пакет приложений, используя фазу «Копировать фреймворки». Когда ваша программа запускается, компоновщик времени выполнения (он же распознаватель) будет искать внутри вашего пакета в дополнение к пути системного загрузчика, находить встроенную платформу и связывать ее, чтобы ваше приложение получило код, необходимый для запуска.

Наконец, то, что по сути является «встроенным двоичным файлом», - это исполняемый файл, который вы оба встраиваете в свой пакет приложений на этапе копирования файлов, и который вы выполняете сами, возможно, с помощью вызова popen()или подобного. Встроенный двоичный файл может вызываться вашей программой, но он не связан с ним. Это полностью внешняя сущность (например, программы в /binкаталоге).

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

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

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

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

Адам Джонс опубликовал следующий вопрос в качестве комментария:

Это отличный ответ. Однако есть кое-что, с чем я все еще немного запутался. Что значит выполнить двоичный файл самостоятельно? Вы имеете в виду просто использование кода встроенного фреймворка? Я знаю, что вы упомянули popen (), но вы говорите, что мое приложение вызывает popen ()? Я действительно не знаю, что это значит.

Я говорю, что встроенный двоичный файл - это просто еще один файл ресурсов в вашем комплекте, например аудиофайл или изображение, хотя этот файл является исполняемым инструментом командной строки. popen()Функция ( man popenот вашего терминала , чтобы узнать больше об этом) позволяет выполнять произвольные программы из другой запущенной программы. system()Функция является еще одним способом. Есть и другие, и я приведу здесь исторический пример, который может сделать понимание использования встроенного двоичного файла немного более ясным:

Как вы, вероятно, знаете, при запуске приложения в Mac OS X оно запускается с идентификатором текущего пользователя. В большинстве распространенных установок это пользователь по умолчанию «пользователь на рабочем столе» admin, которому назначается идентификатор пользователя 501.

В операционных системах на основе Unix только rootпользователь (идентификатор пользователя 0) имеет полный доступ ко всей файловой системе. Иногда случается, что программа установки, запущенная пользователем рабочего стола, должна установить файлы в привилегированном каталоге (например, в драйверах). В этом случае прикладная программа должна передать свои привилегии rootпользователю, чтобы она могла писать в эти ограниченные каталоги.

Чтобы облегчить это в операционных системах через OS X 10.7, Apple предоставила в своем API-интерфейсе служб авторизации функцию AuthorizationExecuteWithPrivileges () (сейчас это устарело, но все еще является полезным примером).

AuthorizationExecuteWithPrivileges()принял в качестве аргумента путь к инструменту командной строки для выполнения как root. Инструмент командной строки представлял собой исполняемый сценарий оболочки или скомпилированный двоичный файл, который вы написали для запуска логики установки. Этот инструмент был установлен внутри вашего пакета приложений, как и любой другой файл ресурсов.

При вызове ОС выдает диалоговое окно авторизации с запросом пароля пользователя (вы видели это раньше!) И при входе запускает программу rootот имени вашего приложения. Этот процесс похож на простое выполнение программы с popen()самим собой, хотя сам по popen()себе он не дает вам преимущества повышения привилегий.


62
Откуда ты знаешь эти вещи?
Ян Варбертон,

56
@IanWarburton Я программирую операционные системы Apple уже более 20 лет, и тут и там уловил несколько лакомых кусочков. :)
пар

1
@ JustMartin Я имею в виду link, но вы правы, что вы должны также встраивать его через этап копирования файлов (иначе как бы вы его использовали?). Целью использования стороннего фреймворка или встроенного двоичного файла является выполнение кода, который предоставляет объект. При встроенном бинарном коде связывание не происходит. Во время выполнения вы создаете путь к двоичному файлу, а затем выполняете его вручную. С помощью фреймворка компоновщик времени компиляции связывает его при сборке приложения, затем (если это сторонний фреймворк) вы встраиваете его через этап копирования файлов, и, наконец, компоновщик во время выполнения снова связывает его при запуске приложения. ,
номинальная

1
Все немного неясно, что вы ответили @JustAMartin. Целью использования стороннего фреймворка или встроенного двоичного файла является выполнение кода, который предоставляет объект. В настоящее время встроенные двоичные файлы также могут быть сторонними фреймворками. Я пытаюсь понять, что вы имеете в виду здесь ... AFA, как я понял, встроенные двоичные файлы означают, что отдельный двоичный файл встроенной платформы будет введен в комплект приложений, и если вы просто свяжете одну и ту же инфраструктуру, он поместит ее в тот же двоичный файл, что и что из приложения. Пожалуйста, поправьте меня, если я ошибаюсь ...
hariszaman

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

35

Коротко,

  • системные библиотеки, свяжите их;
  • Сторонние библиотеки, встраивать их.

Зачем?

  • если вы попытаетесь встроить системные библиотеки, вы не найдете их во всплывающем списке;
  • если вы связываете сторонние библиотеки, вы, вероятно, получите сбой.

7

Это часть Dependencyуправления [О компании]

Обратите внимание, что Xcode 11содержит только Frameworks, Libraries, and Embedded Contentраздел на Generalвкладке

Link Binary

Build Phases -> Link Binary With Librariesэто зеркало General -> Linked Frameworks and Libraries.

Статическая библиотека и фреймворк

Если вы добавите a Static Library or Static Frameworkв этот раздел, он появится в Frameworks группе [About] ( Project Navigator -> <workspace/project> -> Frameworks), и для него будет добавлена ​​ссылка на ваш проект. Тогда он будет использоваться Static Linker. Static Linkerво время компиляции будет включать / копировать весь код из библиотеки в исполняемый объектный файл. Static linkerработает в паре сBuild Settings -> <Library/Framework> Search Paths

Static Library

Static Framework

  • Build Settings -> Framework Search Paths, Если вы не добавите a static frameworkв этот раздел, вы получите ошибку компиляции [Нет такого модуля]

Вставить двоичный файл

Статическая библиотека и статическая структура

Встраивание не имеет никакого смысла для a Static Libraryи Static Frameworkпотому, что символы из них скомпилированы в исполняемый двоичный файл. XCode не позволит вам оставить в static libraryразделе Embed.

Динамическая структура

Build Phases -> Embed Frameworksэто зеркало General -> Embedded Binaries. Встраивание фактически добавляет копию фреймворка в ваш пакет приложений. В результате, когда фреймворк добавляется / удаляется в Embedсекцию, он автоматически добавляется / удаляется в Linkedсекцию. По умолчанию папка комплекта есть, Frameworksно вы можете изменить ее, используя Destinationполе. Кроме того, вы можете указать Subpath.

Dynamic linker :dyldпри загрузке или во время выполнения попытается найти встроенную среду, используя @rpath[О программе]. Если она не найдена, произойдет ошибка [dyld: Библиотека не загружена]

[При использовании Link and Embed]

[Словарь]

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.