Pergunta

Alguém pode explicar como funciona a compilação?

Eu não consigo descobrir como compilação funciona ..

Para ser mais específico, aqui está um exemplo .. Eu estou tentando escrever algum código em MSVC ++ 6 para carregar um estado Lua ..

Eu já:

  • definir os diretórios adicionais para a biblioteca e arquivos de inclusão para os diretórios corretos
  • extern usado "C" (porque Lua é C só pelo que ouço)
  • include'd os arquivos de cabeçalho direito

Mas eu ainda estou recebendo alguns erros no MSVC ++ 6 sobre símbolos externos não resolvidos (para as funções Lua que eu usei).

Por mais que eu gostaria de saber como resolver este problema e seguir em frente, eu acho que seria muito melhor para mim se eu vim a entender os processos subjacentes envolvidos, então alguém poderia talvez escrever uma explicação agradável para este ? O que estou procurando saber é o processo .. Poderia ficar assim:

Passo 1:

  • Input: O código fonte (s)
  • Processo: Parsing (talvez acrescentar mais detalhes aqui)
  • Output: o que é a saída aqui ..

Passo 2:

  • Input: (???? Bibliotecas DLLs .so lib) O que quer que estava de saída do passo 1, mais talvez que mais for necessário
  • Processo: tudo o que é feito com a entrada
  • Saída: tudo o que está de saída

e assim por diante ..

Obrigado ..

Talvez isto explique o que os símbolos são, o que exatamente "ligando" é, o código "objeto" ou o que for ..

Obrigado .. Desculpe por ser tão Noob ..

P.S. Isso não tem que ser específico linguagem .. Mas sinta-se livre para expressá-lo na língua que você está mais confortável em ..:)

Editar : De qualquer forma, eu era capaz de obter os erros resolvidos, verifica-se que eu tenho que adicionar manualmente o arquivo .lib para o projeto; simplesmente especificando o diretório de biblioteca (em que reside .lib) nas configurações de IDE ou configurações projeto não trabalho ..

No entanto, as respostas abaixo têm pouco me ajudou a entender melhor o processo. Muito obrigado .. Se alguém ainda quer escrever um guia completo, por favor ..:!)

Editar : Apenas para referência adicional, eu encontrei dois artigos por um autor (Mike Diehl) para explicar isso muito bem .. :) Examinando o processo de compilação: Parte 1 Examinando o processo de compilação: Part 2

Foi útil?

Solução

De origem para executável é geralmente um processo de dois estágios para C e linguagens associadas, embora o IDE provavelmente apresenta esta como um processo único.

1 / Você código até sua fonte e executá-lo através do compilador. O compilador nesta fase precisa de sua fonte e os arquivos de cabeçalho das outras coisas que você está indo para ligação com (veja abaixo).

Compilação consiste em transformar seus arquivos de origem em arquivos objeto. arquivos de objetos têm seu código e informações suficientes compilados para saber o que outras coisas que eles precisam, mas não onde encontrar as outras coisas (por exemplo, as bibliotecas de LUA).

2 / Linking, a próxima etapa, é a combinação de todos os seus arquivos de objeto com bibliotecas para criar um executável. Eu não vou cobrir dinâmica ligando aqui desde que irá complicar a explicação com pouco benefício.

Não só você precisa especificar os diretórios onde o vinculador pode encontrar o outro código, você precisa especificar a biblioteca real que contém esse código. O fato de que você está recebendo externos não resolvidos indica que você não tenha feito isso.

Como um exemplo, considere o seguinte código simplificado C (xx.c) e de comando.

#include <bob.h>
int x = bob_fn(7);

cc -c -o xx.obj xx.c

Isso compila o arquivo xx.c para xx.obj. O bob.h contém o protótipo para bob_fn() para que a compilação será bem sucedida. O -c instrui o compilador para gerar um arquivo de objeto em vez de um executável e os conjuntos -o xx.obj o nome do arquivo de saída.

Mas o real código para bob_fn() não é no cabeçalho do arquivo, mas em /bob/libs/libbob.so, por assim link, você precisa de algo como:

cc -o xx.exe xx.obj -L/bob/libs;/usr/lib -lbob

Isso cria xx.exe de xx.obj, utilizando bibliotecas (procurou nos caminhos de dados) da libbob.so forma (o lib e .so são adicionados pelo ligante normalmente). Neste exemplo, -L define o caminho de pesquisa para bibliotecas. O -l especifica uma biblioteca para encontrar para inclusão no executável, se necessário. O vinculador geralmente leva a "bob" e encontra o primeiro arquivo de biblioteca relevantes no caminho de pesquisa especificado pelo -L.

Um arquivo de biblioteca é realmente uma coleção de arquivos de objetos (tipo de como um arquivo zip contém vários outros arquivos, mas não necessariamente comprimido) - quando a primeira ocorrência relevante de um link externo indefinido for encontrado, o arquivo objeto é copiado do biblioteca e adicionada ao executável como seu arquivo xx.obj. Isso geralmente continua até que não haja mais externos não resolvidos. A biblioteca 'relevante' é uma modificação do texto "bob", pode procurar libbob.a, libbob.dll, libbob.so, bob.a, bob.dll, bob.so e assim por diante. A relevância é decidido pelo vinculador em si e deve ser documentado.

Como funciona depende do vinculador mas isso é basicamente isso.

1 / Todos os seus arquivos objeto conter uma lista de externos não resolvidos que eles precisam ter resolvido. Os puts vinculador juntos todos estes objetos e conserta as ligações entre eles (Resolve como muitos fatores externos quanto possível).

2 / Então, para cada externo ainda não resolvido, o vinculador penteia os arquivos de biblioteca à procura de um arquivo de objeto que pode satisfazer o link. Se ele encontra-lo, ele puxa-lo em -. Isso pode resultar em mais externos não resolvidos como objeto puxado pode ter sua própria lista de coisas externas que precisam ser satisfeitas

3 / Repita o passo 2 até que haja externos não mais não resolvidos ou nenhuma possibilidade de resolvê-los da lista biblioteca (este é o lugar onde o seu desenvolvimento estava, desde que você não tinha incluído o arquivo de biblioteca LUA).

A complicação já referi anteriormente é a vinculação dinâmica. É aí que você ligar com um esboço de uma rotina (uma espécie de marcador) em vez da rotina real, que mais tarde é resolvido em ltempo oad (quando você executar o arquivo executável). As coisas tais como os controles comuns do Windows são nessas DLLs para que eles possam alterar sem ter que ligar novamente os objetos em um novo executável.

Outras dicas

Passo 1 - Compiler:

  • Entrada: arquivo de código fonte [s]
  • Processo: A análise de código fonte e traduzir em código de máquina
  • Saída: Objeto arquivo [s], que consistem [s] de:
    • Os nomes dos símbolos que são definidos neste objeto, e que esse arquivo objeto "exportações"
    • O código de máquina associado a cada símbolo que está definido neste arquivo objeto
    • Os nomes dos símbolos que não são definidos neste arquivo objeto, mas no qual o software neste arquivo objeto depende e que deve ser posteriormente ligados, ou seja, nomes que este arquivo objeto "importações"

Passo 2 - Ligando:

  • Input:
    • Objeto arquivo [s] a partir do passo 1
    • Bibliotecas de outros objectos (por exemplo, a partir do S / S e outro software)
  • Processo:
    • Para cada objeto que você deseja vincular
    • Obter a lista de símbolos qual esse objeto importações
    • Encontre estes símbolos em outras bibliotecas
    • Fazer a ligação das bibliotecas que corresponde ao seu objeto arquivos
  • Saída:. Um único arquivo executável, que inclui o código de máquina de todos os todos os seus objetos, além dos objetos de bibliotecas que foram importados (ligada) para seus objetos

As duas etapas principais são a compilação e vinculação.

Compilation leva unidades de compilação simples (aqueles são simplesmente arquivos de origem, com todos os cabeçalhos que incluem), e criar arquivos objeto. Agora, naqueles arquivos objeto, há um grande número de funções (e outras coisas, como dados estáticos) definidos em locais específicos (endereços). Na próxima etapa, ligando, também é necessário um pouco de informação extra sobre estas funções: seus nomes. Então, esses também são armazenados. Um arquivo único objeto pode fazer referência a funções (porque quer chamá-los quando o código é executado) que estão realmente em outros arquivos de objeto, mas uma vez que estamos lidando com um único arquivo objeto aqui, apenas referências simbólicas (seus 'nomes') para as outras funções são armazenadas no arquivo objeto.

Em seguida, vem ligando (vamos limitar-nos a estática ligando aqui). Vinculação é o local onde os arquivos de objetos que foram criados no primeiro passo (directamente ou depois de terem sido jogados juntos em um arquivo .lib) são tomados em conjunto e um executável é criado. Na etapa de ligação, todas essas referências simbólicas de arquivo de um objeto ou lib para outro são resolvidos (se eles podem ser), observando-se os nomes do objeto correto, encontrar o endereço da função, e colocando os endereços no direito lugar.

Agora, para explicar algo sobre o 'externo 'C'' coisa que você precisa:

C não tem sobrecarga de funções. A função é sempre reconhecível por seu nome. Portanto, quando você compilar o código como o código C, apenas o nome real da função é armazenado no arquivo objeto.

C ++, no entanto, tem uma coisa chamada 'função / método de sobrecarga'. Isto significa que o nome de uma função não é suficiente para identificá-lo. compiladores C ++, portanto, criar 'nomes' para funções que incluem os protótipos da função (desde o nome mais o protótipo vai identificar exclusivamente uma função). Isto é conhecido como 'deturpação nome'.

A especificação 'extern 'C'' é necessário quando você quiser usar uma biblioteca que foi compilado como código 'C' (por exemplo, os Lua binários pré-compilados) a partir de um C ++ projeto.

Para o seu problema exato: se ainda não funcionar, essas dicas podem ajudar: * Têm os binários Lua foi compilado com a mesma versão do VC ++? * Você pode simplesmente compilar Lua si mesmo, seja dentro de sua solução VC, ou como um projeto separado como código C ++? * Você tem certeza que você tem todas as 'extern 'C'' coisas corrigir?

Você tem que ir para definição de projecto e adicionar um diretório onde você tem essa biblioteca LUA * .lib em algum lugar na aba "ligador". Configuração chamada "incluindo bibliotecas" ou algo, desculpe eu não posso procurá-lo.

A razão que você começa "símbolos externos não resolvidos" é porque a compilação em C ++ funciona em duas etapas. Primeiro, o código é compilado, cada arquivo .cpp em seu próprio arquivo obj, então "vinculador" começa e se juntar a tudo o que obj arquivos em .exe. .lib é apenas um monte de obj arquivos mesclados para fazer distribuição de bibliotecas apenas um pouco simplier pouco. Assim, adicionando todos os "#include" e declaração extern você disse o compilador que em algum lugar que seria possível encontrar o código com essas assinaturas, mas vinculador não consegue encontrar esse código, porque ele não sabe onde esses arquivos .lib com código real é colocado.

REDME Certifique-se de ter lido da biblioteca, a explicação geralmente eles têm bastante detalhada do que você tinha que fazer para incluí-lo em seu código.

Você também pode querer verificar isso: Compiler, Assembler ligador e o carregador: UMA BREVE HISTÓRIA .

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top