Ferramentas do usuário

Ferramentas do site


prog2:edicao_e_compilacao_c_em_unix

Diferenças

Aqui você vê as diferenças entre duas revisões dessa página.

Link para esta página de comparações

prog2:edicao_e_compilacao_c_em_unix [2019/01/31 17:28]
127.0.0.1 edição externa
prog2:edicao_e_compilacao_c_em_unix [2019/04/09 13:28] (atual)
maziero
Linha 1: Linha 1:
 +====== Edição e Compilação C em UNIX ======
 +
 +No processo de codificação de um software, são atividades básicas:
 +
 +  * Edição
 +  * Compilação
 +  * Execução
 +  * Depuração
 +
 +Além destas, também são atividades necessárias,​ sobretudo à medida em que os softwares desenvolvidos crescem em tamanho e complexidade:​
 +
 +  * Construção de bibliotecas
 +  * Gerência de versões
 +  * Documentação
 +
 +Neste módulo serão enumeradas algumas ferramentas (a maioria de código aberto -//open source//) disponíveis para auxiliar nas diversas etapas do desenvolvimento de programas C/C++ em plataformas UNIX, mais particularmente no mundo Linux.
 +
 +===== Edição de código =====
 +
 +Para a edição de código-fonte pode-se optar por editores de código-fonte como [[http://​www.gnu.org/​software/​emacs/​emacs.html|Emacs]] (ou [[http://​www.xemacs.org|XEmacs]]),​ [[http://​www.vim.org/​|Vi]],​ [[http://​www.nano-editor.org/​|Nano]],​ [[http://​www.jedsoft.org/​jed/​|Jed]],​ [[http://​kate.kde.org/​|Kate]] (no ambiente KDE), [[http://​gedit.sourceforge.net/​|Gedit]] (no ambiente Gnome), [[https://​www.sublimetext.com|Sublime Text]], [[https://​atom.io/​|Atom]] e muitos outros. Pode-se também optar por ambientes de desenvolvimento integrado (IDEs) como [[http://​www.eclipse.org/​|Eclipse]],​ [[http://​www.kdevelop.org/​|Kdevelop]],​ [[http://​anjuta.sourceforge.net/​|Anjuta]],​ [[http://​www.codeblocks.org/​|Code::​Blocks]] e diversos outros.
 +
 +Qual é a melhor opção ? Esta é uma pergunta difícil de responder, pois há muitas controvérsias...
 +
 +===== Compilação =====
 +
 +Existem vários compiladores C/C++ disponíveis livremente em ambiente Linux, mas o [[http://​gcc.gnu.org/​|GCC]] (GNU Compiler Collection) é de longe o compilador mais popular e certamente um dos melhores. O GCC compreende compiladores de front-end e geradores de código para várias linguagens de programação (C, C++, ObjC, Fortran, Ada, Java, ...) em [[http://​gcc.gnu.org/​install/​specific.html|diversas plataformas]]. Além dele, sugere-se o compilador [[http://​clang.llvm.org/​|CLANG]] (para C/​C++/​ObjC),​ pela qualidade do código gerado e suas mensagens de erro bem mais compreensíveis que as do GCC.
 +
 +O GCC é um compilador que opera em linha de comando. Por default, o compilador irá realizar a compilação e ligação do(s) fonte(s), gerando um arquivo executável denominado ''​a.out''​ (que tem esse nome por razões históricas). Para executar esse arquivo basta invocá-lo, em uma linha de comando:
 +
 +<code C hello.c>
 +#include <​stdio.h>​
 +
 +int main ()
 +{
 +  printf ("​Hello,​ world\n"​) ;
 +  return (0) ;
 +}
 +</​code>​
 +
 +<​code>​
 +~> gcc hello.c
 + 
 +~> ls -l
 +-rwxr-xr-x 1 prof 11724 Set 28 16:25 a.out
 +-rw-r--r-- 1 prof 45 Set 28 16:13 hello.c
 + 
 +~> a.out
 +Hello, world
 +</​code>​
 +
 +Pode-se redefinir o arquivo de saída com a opção ''​-o'': ​
 +
 +<​code>​
 +~> cc -o hello hello.c
 +</​code>​
 +
 +É possível compilar diversos arquivos interdependentes simultaneamente,​ como mostra o seguinte exemplo:
 + 
 +
 +<code C hello.c>
 +int main ()
 +{
 +  escreva ("​Hello,​ world\n"​) ;
 +  return (0) ;
 +}
 +</​code>​
 + 
 +<code C escreva.c>​
 +#include <​stdio.h>​
 +
 +void escreva (char *msg)
 +{
 +  printf ("​%s",​ msg) ;
 +}
 +</​code>​
 + 
 +<​code>​
 +~> cc -o hello hello.c escreva.c
 +</​code>​
 +
 +Também é possível efetuar somente a compilação dos códigos-fonte,​ sem efetuar a ligação e a geração do executável. Nesse caso, serão gerados os arquivos com o código-objeto (''​*.o''​) dos correspondentes arquivos de código fonte (''​*.c''​),​ como mostra o exemplo abaixo:
 + 
 +<​code>​
 +~> cc -c hello.c escreva.c
 + 
 +~> ls -l
 +-rw-r--r-- ​ 1  prof     ​50 ​ Set 28 16:13  escreva.c
 +-rw-r--r-- ​ 1  prof    788  Set 28 16:16  escreva.o
 +-rw-r--r-- ​ 1  prof     ​45 ​ Set 28 16:13  hello.c
 +-rw-r--r-- ​ 1  prof    800  Set 28 16:16  hello.o
 +</​code>​
 +
 +Esses arquivos objeto poderão posteriormente ser ligados, gerando o executável:​
 +
 +<​code>​
 +~> cc -o hello *.o
 +
 +~> ls -l
 +-rw-r--r-- ​ 1  prof     ​50 ​ Set 28 16:13  escreva.c
 +-rw-r--r-- ​ 1  prof    788  Set 28 16:16  escreva.o
 +-rwxr-xr-x ​ 1  prof  11724  Set 28 16:25  hello
 +-rw-r--r-- ​ 1  prof     ​45 ​ Set 28 16:13  hello.c
 +-rw-r--r-- ​ 1  prof    800  Set 28 16:16  hello.o
 +</​code>​
 +
 +As opções usuais de execução do compilador GCC podem ser consultadas em sua página de manual (''​man gcc''​).
 +
 +===== Opções de compilação =====
 +
 +O compilador GCC (e os demais compiladores,​ em geral) aceitam uma grande quantidade de opções na linha de comando, para ativar funcionalidades específicas. As opções mais usuais são:
 +
 +  * ''​-Wall''​ : gera avisos sobre problemas no código que não impedem a compilação,​ mas podem constituir erros, como o uso de variáveis não inicializadas.
 +  * ''​-Wextra''​ : versão ainda mais exigente do ''​-Wall''​.
 +  * ''​-Werror''​ : transforma todos os avisos de ''​-Wall''​ ou ''​-Wextra''​ em erros, abortando a compilação.
 +  * ''​-o''​ : define o nome do arquivo executável.
 +  * ''​-c''​ : faz somente a etapa de compilação,​ gerando o código-objeto do fonte informado.
 +  * ''​-E''​ : faz somente a etapa de preprocessamento.
 +  * ''​-S''​ : gera um arquivo com o código //​Assembly//​ do programa.
 +  * ''​-l''​ : serve para ligar o código com bibliotecas dinâmicas.
 +  * ''​-D''​ : serve para definir macros na linha de comando (substitui o ''#​define''​).
 +  * ''​-O''​ : define níveis de otimização do código (ex: ''​-O1''​)
 +  * ''​-ansi''​ : força o uso do padrão C89/C90 (C ANSI).
 +  * ''​--std=''​ : força o uso de um padrão específico da linguagem (ex: ''​--std=c99''​).
 +
 +<note important>​
 +Todos os programas desta disciplina devem ser compilados com ''​-Wall'';​ a ocorrência de avisos gera perda de pontos na nota.
 +</​note>​
 +
 +===== Usando bibliotecas =====
 +
 +A linguagem C é rica em poder de expressão, mas relativamente pobre em funcionalidades. Para construir aplicações que fazem uso de funcionalidades específicas,​ como interfaces gráficas, comunicação via rede, fórmulas matemáticas complexas, etc, devem ser usadas bibliotecas. Algumas bibliotecas encapsulam chamadas do sistema operacional,​ sendo então chamadas de //​bibliotecas de sistema//, enquanto outras provêm funcionalidades no espaço de usuário, como funções matemáticas e interfaces gráficas.
 +
 +As bibliotecas mais comuns, utilizadas por todas as aplicações e utilitários do sistema, são:
 +
 +  * ''​libc'':​ na verdade um grande pacote de bibliotecas que provê funcionalidades básicas de entrada/​saída,​ de acesso a serviços do sistema, à rede, etc.
 +
 +  * ''​ld-linux'':​ provê as funções necessárias para a carga de bibliotecas dinâmicas, durante a inicialização do programa.
 +
 +Por default, essas duas bibliotecas são automaticamente incluídas e ligadas em todos os programas. Para compilar um programa que utiliza outras bibliotecas externas, algumas opções devem ser informadas ao compilador. Por exemplo, considere o seguinte programa, que faz o cálculo de Pi através de uma série de Gregory:
 +
 +<code c pi.c>
 +#include <​stdio.h>​
 +#include <​math.h>​
 +
 +#define TERMOS 1000000
 +
 +int main ()
 +{
 +  int i ;
 +  double pi = 0 ;
 + 
 +  for (i=0; i < TERMOS; i++)
 +    pi += pow (-1,i) / (2*i+1) ;
 +  pi *= 4 ;
 + 
 +  printf ("O valor aproximado de Pi é: %f\n", pi) ;
 +  return (0) ;
 +}
 +</​code>​
 +
 +Ao compilar esse programa, obtemos:
 +
 +<​code>​
 +~> cc pi.c -o pi
 +/​tmp/​ccCANYTf.o(.text+0x42):​ In function `main':​
 +: undefined reference to `pow'
 +collect2: ld returned 1 exit status
 +</​code>​
 +
 +Esse erro ocorre porque o ligador não conseguiu encontrar a função ''​pow''​ em nenhum dos arquivos fonte ou objeto informados no comando, nem nas bibliotecas padrão. Essa função se encontra na biblioteca matemática ''/​usr/​lib/​libm'',​ que deve ser informada ao ligador da seguinte forma:
 +
 +<​code>​
 +~> cc pi.c -o pi -lm
 +</​code>​
 +
 +A opção ''​-lm''​ indica o uso da biblioteca ''​libm''​. Da mesma forma, ''​-lpthread''​ indica o uso da biblioteca ''​libpthread'',​ e assim por diante. O ligador irá procurar por arquivos de bibliotecas nos diretórios padrão (''/​lib'',​ ''/​usr/​lib'',​ ...). Pode-se informar outros diretórios de bibliotecas ao ligador através da opção ''​-L''​ (detalhada mais adiante neste texto).
 +
 +===== Ligação estática e dinâmica =====
 +
 +Há duas formas básicas de ligar as bibliotecas a um programa executável:​
 +
 +  * Na **ligação estática** (//static linking//), o código da biblioteca é incorporado ao executável. O executável fica maior, mas não depende de bibliotecas instaladas no sistema para poder executar.
 +  * Na **ligação dinâmica** (//dynamic linking//), o executável guarda apenas referências às bibliotecas necessárias,​ que são resolvidas somente quando o programa executável for lançado. O executável fica muito menor, mas precisa que todas as bibliotecas necessárias estejam presentes no sistema para executar.
 +
 +A ligação dinâmica é feita por default. Para compilar um programa, ligando-o estaticamente à bibliotecas,​ devemos executar:
 +
 +<​code>​
 +~> cc -static pi.c -o pi -lm
 +</​code>​
 +
 +O utilitário ''​ldd''​ permite verificar de quais bibliotecas dinâmicas um executável depende:
 +
 +<​code>​
 +~> ldd pi
 +    libm.so.6 => /​lib/​i686/​libm.so.6 (0x40028000)
 +    libc.so.6 => /​lib/​i686/​libc.so.6 (0x4004b000)
 +    /​lib/​ld-linux.so.2 => /​lib/​ld-linux.so.2 (0x40000000)
 +</​code>​
 +
 +Para encontrar as bibliotecas dinâmicas, são percorridos os diretórios indicados pelo arquivo de configuração ''/​etc/​ld.so.conf''​ e pela variável de ambiente ''​LD_LIBRARY_PATH''​. O utilitário ''​ldconfig''​ permite atualizar as informações sobre bibliotecas dinâmicas nos diretórios padrão (ou nos diretórios informados via linha de comando).
 +
 +===== Documentação =====
 +
 +O sistema UNIX implementa um sistema de documentação //on-line// simples, mas bastante útil e eficiente, chamado **páginas de manual** (//man pages//). As páginas de manual estão estruturadas em sessões:
 +
 +  * Sessão 1: Comandos do usuário.
 +  * Sessão 2: Chamadas ao sistema
 +  * Sessão 3: Bibliotecas e funções standard
 +  * Sessão 4: Descrição de dispositivos e formatos de arquivos de dados
 +  * Sessão 5: Formato de arquivos de configuração
 +  * Sessão 6: Jogos
 +  * Sessão 7: Diversos
 +  * Sessão 8: Comandos de administração do sistema
 +
 +O acesso às páginas de manual é normalmente efetuado através do comando ''​man''​. Assim, ''​man ls''​ apresenta a página de manual do comando ''​ls'',​ enquanto ''​man man''​ apresenta a página de manual do próprio comando ''​man''​. Ambientes gráficos normalmente oferecem ferramentas mais versáteis para consulta às páginas de manual.
 +
 +Além do comando ''​man'',​ outros comandos são úteis para a busca de informações no sistema:
 +
 +  * ''​whatis'',​ ''​apropos''​ :  para localizar páginas de manual que contenham informações sobre algum assunto específico.
 +  * ''​locate''​ :  para localizar arquivos no sistema
 +  * ''​which''​ : para informar onde se encontra um determinado executável
 +  * ''​info''​ : sistema de informações mais completo que o ''​man'',​ mas não disponível em todas as plataformas UNIX.
  
prog2/edicao_e_compilacao_c_em_unix.txt · Última modificação: 2019/04/09 13:28 por maziero