Ответ 1
Связанный с вами вопрос ссылается на функциональность Link Binary With Libraries, которая несколько отличается от встроенного двоичного файла.
"Link Binary With Libraries" означает то, что вы ожидаете от него в отношении привязки: независимо от того, является ли бинарный файл статической библиотекой, динамической библиотекой или фреймворком, она будет связана с вашим объектным кодом во время ссылки после компиляции.
Когда вы думаете о связывании со статической библиотекой, что происходит довольно ясно: компоновщик копирует код из библиотеки (например, libFoo.a
) в ваш выходной двоичный файл. Ваш выходной файл растет в размерах, но не требует разрешения каких-либо внешних зависимостей во время выполнения. Все, что нужно выполнить вашей программе (относительно статической библиотеки), присутствует после ее создания.
С динамической библиотекой (.dylib или системной базой) ожидается, что библиотека, с которой вы связываете, будет присутствовать где-нибудь в пути загрузки динамической библиотеки системы при запуске вашей программы. Таким образом, у вас нет накладных расходов на копирование всех внешних сторонних библиотек в ваш двоичный файл, и все различные программы на компьютере, которые также ссылаются на эту библиотеку, смогут найти его, что экономит минимальное дисковое пространство, но также потенциально пространство памяти, в зависимости от того, как и где система кэширует библиотеки.
Структура похожа на динамическую библиотеку, но может содержать ресурсы в структуре каталогов (изображения, аудио, другие фреймворки и т.д.). В этом случае простой файл static-library или .dylib не будет вырезать его, поэтому вам может потребоваться ссылка на структуру, чтобы он мог найти, что нужно для правильной работы.
Когда вы ссылаетесь на стороннюю структуру (скажите что-то, что вы загрузили из github и создали самостоятельно), она может отсутствовать в системе, которую вы собираетесь запускать. В этом случае вы не только привязываетесь к инфраструктуре, но также встраиваете ее в свой пакет приложений, используя фазу "Копирование фреймворков". Когда ваша программа запускается, runtime-linker (ака резольвер) будет заглядывать в ваш комплект в дополнение к пути загрузчика системы, найти встроенную инфраструктуру и связать ее, чтобы ваше приложение получило необходимый код для запуска.
Наконец, то, что является надлежащим образом "встроенным двоичным файлом", является исполняемым файлом, который вы вставляете в свой пакет приложений через фазу "Файлы копирования" и выполняете сами, возможно, с вызовом popen()
или аналогичным. Встроенная двоичная система может быть вызвана вашей программой, но она не связана с ней. Это полностью внешняя сущность (например, программы в каталоге /bin
).
На практике для системных библиотек и фреймворков вы свяжетесь с ними и все, что вам нужно сделать.
Если вам нужно связать библиотеку, которую вы создали, которая не нуждается в каких-либо встроенных ресурсах (т.е. не требует существования фреймворка), вы можете просто связать ее со статической библиотекой. Если вы обнаружите, что у вас есть несколько модулей в вашей программе, которые хотят использовать один и тот же код библиотеки, то преобразование его в структуру или динамическую библиотеку и привязку к ней может сэкономить место и может быть удобным (особенно, если использование памяти является проблемой).
Наконец, фреймворки могут включать не только ресурсы, но и файлы заголовков и/или лицензий. Использование фреймворка для передачи этих файлов на самом деле является удобным механизмом распределения, поэтому часто вам может понадобиться включить фреймворк, чтобы эти вещи могли маркироваться вместе с вашим двоичным кодом (то есть требования к лицензии могут сделать это обязательным).
--- EDIT ---
Адам Джонс написал следующий вопрос в качестве комментария:
Это отличный ответ. Однако я кое-что немного запутался. Что значит выполнять сам бинар? Вы имеете в виду просто использование встроенного кода рамки? Я знаю, что вы упомянули popen(), но вы говорите, что мое приложение вызывает popen()? Я действительно не знаю, что это значит.
Я говорю, что встроенный двоичный файл - это еще один файл ресурсов в вашем комплекте, например, аудиофайл или изображение, хотя файл является исполняемым средством командной строки. Функция popen()
(man popen
из вашего терминала, чтобы узнать больше об этом) позволяет выполнять произвольные программы из другой запущенной программы. Функция system()
- это другой способ. Есть и другие, и я приведу здесь исторический пример, который может лучше понять использование встроенного двоичного кода:
Как вам известно, при запуске приложения в Mac OS X он запускается с идентификатором пользователя текущего пользователя. В большинстве обычных установок пользователь user-at-the-Desktop admin
по умолчанию, которому присваивается идентификатор пользователя 501
.
В операционных системах на базе Unix только пользователь root
(идентификатор пользователя 0
) имеет полный доступ ко всей файловой системе. Иногда бывает, что программа установки, запускаемая пользователем Desktop, должна устанавливать файлы в привилегированном каталоге (например, драйверы). В этом случае прикладная программа должна эскалировать свои привилегии пользователю root
, чтобы он мог писать в этих ограниченных каталогах.
Чтобы облегчить это в операционных системах через OS X 10.7, Apple предоставила в Авторизованных сервисах API функцию AuthorizationExecuteWithPrivileges() (теперь это устарело, но по-прежнему является полезным примером).
AuthorizationExecuteWithPrivileges()
принял в качестве аргумента путь к инструменту командной строки для выполнения как root
. Инструмент командной строки представлял собой исполняемую оболочку script или скомпилированный двоичный файл, который вы написали для запуска вашей логики установки. Этот инструмент был установлен внутри вашего пакета приложений так же, как и любой другой файл ресурсов.
При вызове ОС выдает диалог авторизации с запросом пароля пользователя (вы видели это раньше!), и при вводе будет выполняться программа как root
в вашем приложении. Этот процесс похож на выполнение самой программы с помощью popen()
самостоятельно, хотя popen()
сам по себе не дает вам преимуществ эскалации привилегий.