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 /bin
diretó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 popen
do 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 root
usuá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 root
usuá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 root
em 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.