Quando devemos usar “binários incorporados” em vez de “Frameworks Vinculados” no Xcode?

140

Há uma boa pergunta sobre a diferença entre essas duas opções, conforme descrito em Link Binary com bibliotecas VS Embed Frameworks .

Parece que temos opções para usá-los, apenas imaginando qual caso devemos usar os binários incorporados melhor ou melhor que a estrutura vinculada?

Algum exemplo sólido para resolver isso mais claramente? obrigado

Forrest
fonte

Respostas:

239

A pergunta que você vinculou faz referência à funcionalidade "Vincular binário com bibliotecas", que é um pouco diferente de um binário incorporado.

"Vincular binário com bibliotecas" significa o que você esperaria com relação à vinculação: independentemente de o binário ser uma biblioteca estática, biblioteca dinâmica ou estrutura, ele será vinculado ao seu código de objeto no momento do link após a compilação.

Quando você pensa em vincular a uma biblioteca estática, o que acontece é bem claro: o vinculador copia o código da biblioteca (por exemplo libFoo.a) para o seu binário de saída. Seu arquivo de saída cresce em tamanho, mas não precisa resolver nenhuma dependência externa em tempo de execução. Tudo o que seu programa precisa executar (com relação à biblioteca estática) está presente após sua compilação.

Com uma biblioteca dinâmica (.dylib ou estrutura fornecida pelo sistema), a expectativa é que a biblioteca à qual você está vinculando esteja presente em algum lugar no caminho do carregador da biblioteca dinâmica do sistema quando você executa o programa. Dessa forma, você não tem a sobrecarga de copiar todas as bibliotecas externas de terceiros para o seu binário, e todos os diferentes programas em um computador que também se vinculam a essa biblioteca poderão encontrá-lo, o que economiza espaço em disco minimamente, mas também potencialmente espaço em memória, dependendo de como e onde o sistema armazena em cache as bibliotecas.

Uma estrutura é muito parecida com uma biblioteca dinâmica, mas pode conter recursos em sua estrutura de diretórios (imagens, áudio, outras estruturas etc.). Neste caso, um arquivo estático-biblioteca ou .dylib simples não vai cortá-la assim que você pode ter que apontam para um quadro tão ele pode encontrar o que ele precisa para funcionar adequadamente.

Quando você vincula a uma estrutura de terceiros (diga algo que você baixou do github e construiu você mesmo), pode não estar presente no sistema em que você pretende executar. Nesse caso, você não apenas vincularia à estrutura, mas a incorporaria ao pacote de aplicativos, usando a fase "Copiar estruturas". Quando o programa é executado, o runtime-linker (também conhecido como resolvedor) examinará o pacote, além do caminho do carregador do sistema, encontrará a estrutura incorporada e vinculará-a para que seu aplicativo tenha o código necessário para executar.

Por fim, o que é propriamente um "binário incorporado" é um executável que ambos incorporam no pacote de aplicativos por meio de uma fase de cópia de arquivos e que você se executa, talvez com uma chamada popen()ou semelhante. O binário incorporado pode ser chamado pelo seu programa, mas não está vinculado a ele. É uma entidade totalmente externa (como programas no /bindiretório).

Na prática, para bibliotecas e estruturas fornecidas pelo sistema, você vinculará a elas e isso é tudo que você precisa fazer.

Se você precisar vincular uma biblioteca criada que não precise de recursos incorporados (ou seja, não exija a existência de uma estrutura), basta vincular uma biblioteca estática. Se você achar que possui vários módulos em seu programa que desejam usar o mesmo código de biblioteca, convertê-lo em uma estrutura ou biblioteca dinâmica e vincular-se a ele podem economizar espaço e podem ser convenientes (principalmente se o uso da memória for uma preocupação).

Finalmente, as estruturas podem incluir não apenas recursos, mas também arquivos de cabeçalho e / ou licença. O uso de uma estrutura para transmitir esses arquivos é, na verdade, um mecanismo de distribuição conveniente; muitas vezes você pode incorporar uma estrutura para que essas coisas possam ser marcadas junto com o seu binário (ou seja, os requisitos de licença podem tornar isso obrigatório).

--- EDIT ---

Adam Johns postou a seguinte pergunta como um comentário:

Esta é uma ótima resposta. Há algo em que ainda estou um pouco confuso. O que significa executar o binário você mesmo? Você quer dizer simplesmente usar o código da estrutura incorporada? Sei que você mencionou popen (), mas está dizendo que meu aplicativo está chamando popen ()? Eu realmente não sei o que isso significa.

Estou dizendo que um binário incorporado é apenas outro arquivo de recurso no seu pacote, como um arquivo ou imagem de áudio, embora o arquivo seja uma ferramenta de linha de comando executável. A popen()função ( man popendo seu terminal para ler mais sobre isso) permite executar programas arbitrários a partir de outro programa em execução. A system()função é outra maneira. Existem outros, e darei um exemplo histórico aqui que pode tornar um pouco mais claro o entendimento do uso de um binário incorporado:

Como você provavelmente sabe, quando você inicia um aplicativo no Mac OS X, ele é iniciado com um ID do usuário atual. Nas instalações mais comuns, esse é o usuário padrão na área de trabalho admin, que recebe o ID do usuário 501.

Nos sistemas operacionais baseados em Unix, apenas o rootusuário (ID do usuário 0) tem acesso total a todo o sistema de arquivos. Às vezes, acontece que um programa instalador iniciado pelo usuário da área de trabalho precisa instalar arquivos em um diretório privilegiado (drivers, por exemplo). Nesse caso, o programa de aplicativo precisa escalar seus privilégios para o rootusuário, para que ele possa gravar nesses diretórios restritos.

Para facilitar isso em sistemas operacionais através do OS X 10.7, a Apple forneceu em sua API dos Serviços de Autorização a função AuthorizationExecuteWithPrivileges () (agora está obsoleta, mas ainda é um exemplo útil).

AuthorizationExecuteWithPrivileges()tomou como argumento um caminho para uma ferramenta de linha de comando para executar como root. A ferramenta de linha de comando era um shell script executável ou binário compilado que você escreveu para executar sua lógica de instalação. Essa ferramenta foi instalada dentro do pacote de aplicativos, como qualquer outro arquivo de recurso.

Quando chamado, o sistema operacional exibe uma caixa de diálogo de autorização solicitando a senha do usuário (você já viu isso antes!) E, quando inserida, executaria o programa como rootem nome do seu aplicativo. Esse processo é semelhante a apenas executar um programa consigo popen()mesmo, embora popen()sozinho não ofereça o benefício da escalação de privilégios.

par
fonte
62
Como você sabe essas coisas?
11117 Ian Ian
56
@IanWarburton Venho programando os sistemas operacionais da Apple há mais de 20 anos e recebi algumas dicas aqui e ali. :)
par
1
@JustAMartin, quero dizer link, mas você está certo de que também deve incorporá-lo através de uma fase de cópia de arquivos (caso contrário, como você o usaria?). O objetivo de usar uma estrutura de terceiros ou um binário incorporado é executar o código que a entidade fornece. Com um binário incorporado, nenhum vínculo está envolvido. No tempo de execução, você constrói um caminho para o binário e o executa manualmente. Com uma estrutura, o vinculador em tempo de compilação o vincula quando você cria seu aplicativo, e (se for uma estrutura de terceiros), você o incorpora por meio de uma fase de cópia de arquivos e, finalmente, o vinculador em tempo de execução o vincula novamente quando você executa o aplicativo. .
par
1
As coisas não estão claras quanto ao que você respondeu ao @JustAMartin. O objetivo de usar uma estrutura de terceiros ou um binário incorporado é executar o código que a entidade fornece. Atualmente, os binários incorporados também podem ser estruturas de terceiros. Estou tentando entender o que você quer dizer aqui ... AFA entendi, binários incorporados significa que o binário separado da estrutura incorporada será introduzido no pacote App, e se você apenas vincular a mesma estrutura, isso será colocado no mesmo binário que o do app. Corrija-me se estou errado ...
hariszaman
1
Talvez haja uma nova mágica do Xcode que carregue uma estrutura incorporada. Já faz um tempo desde que eu precisava dessa funcionalidade. Se você quiser explorar mais o que está acontecendo, poste uma nova pergunta aqui no SO.
Par
35

Em resumo,

  • bibliotecas do sistema, vincule-as;
  • Bibliotecas de terceiros, incorpore-as.

porque?

  • se você tentar incorporar bibliotecas do sistema, não as encontrará na lista pop-up;
  • se você vincular bibliotecas de terceiros, provavelmente ocorrerá uma falha.
Futuro brilhante
fonte
7

É uma parte da Dependencyadministração [Sobre]

Observe que Xcode 11contém apenas a Frameworks, Libraries, and Embedded Contentseção na Generalguia

Link Binário

Build Phases -> Link Binary With Librariesé um espelho General -> Linked Frameworks and Libraries.

Biblioteca e estrutura estática

Se você adicionar um Static Library or Static Frameworka esta seção, ele aparecerá no Frameworks grupo [Sobre] ( Project Navigator -> <workspace/project> -> Frameworks) e haverá uma referência adicionada ao seu projeto. Então será usado por Static Linker. Static Linkerno momento da compilação, incluirá / copiará todo o código da biblioteca no arquivo de objeto executável. Static linkertrabalha em par comBuild Settings -> <Library/Framework> Search Paths

Static Library

Static Framework

  • Build Settings -> Framework Search Paths. Se você não adicionar um static frameworka esta seção, receberá um erro de compilação [Nenhum módulo desse tipo]

Incorporar binário

Biblioteca estática e estrutura estática

Embedding não faria qualquer sentido para um Static Librarye Static Frameworkporque os símbolos a partir deles são compilados no binário executável. O Xcode não permite que você solte um static libraryna seção Incorporar.

Estrutura dinâmica

Build Phases -> Embed Frameworksé um espelho de General -> Embedded Binaries. A incorporação realmente adiciona uma cópia da estrutura ao seu pacote de aplicativos. Como resultado, quando uma estrutura é adicionada / removida à Embedseção, ela será automaticamente adicionada / removida à Linkedseção. Por padrão, a pasta do pacote configurável é, Frameworksmas você pode alterá-la usando o Destinationcampo Além disso, você pode especificar a Subpath.

Dynamic linker :dyldno carregamento ou no tempo de execução , tentará encontrar a estrutura incorporada usando @rpath[Sobre]. Se não for encontrado, o erro ocorrerá [dyld: Biblioteca não carregada]

[Quando usar Link e Incorporar]

[Vocabulário]

yoAlex5
fonte