Você está na página 1de 11

Universidade de Sao Paulo Instituto de Ciencias Matematicas e de Computacao

Uma breve introduo a criao de ca ` ca bibliotecas e makeles em C/C++

Moacir Pereira Ponti Jr.

2011

Arquivos de cabealho e bibliotecas c

E muito interessante criar bibliotecas cujas funes (classes e mtodos, no caso de linco e guagens orientadas a objetos) possam ser reutilizadas em diversos programas. Voc pode e inclusive distribuir essas bibliotecas, com a opo de esconder o cdigo fonte utilizado ca o nas funoes. Geralmente ao programar em C/C++, j utilizamos muitas bibliotecas com c a funoes prontas como quando inclu c mos <stdio.h> ou <iostream>. Para criarmos nossa prpria biblioteca preciso ter arquivos de cabealho (com exo e c tenso .h) e arquivos de biblioteca (com extenso dependente do compilador e sistema a a operacional, no gcc a extenso geralmente utilizada .a). a e Vamos mostrar um exemplo em C de biblioteca contendo uma unica funao, que receba c um valor inteiro e retorne seu fatorial. O arquivo cabealho ser funcoes.h, e o arquivo c a com o cdigo fonte da funo ser nomeado funcoes.c e tem o seguinte contedo: o ca a u #include "funcoes.h" int fatorial(int x) { int a, fatx=1; for (a=x; a>1; a--) { fatx = fatx*a; } return fatx; } Veja que j inclu a mos funcoes.h. Isso ser necessrio para o compilador reconhecer a a a funao como sendo parte da biblioteca. c O arquivo cabealho ir conter informaes apenas da interface, tipicamente as assic a co naturas (ou prottipos) das funes. A extenso .h vem da palavra header (cabealho o co a c em ingls). Nesse caso teremos o arquivo cabealho, nomeado funcoes.h, denido da e c seguinte forma: #ifndef FUNCOES_H #define FUNCOES_H int fatorial(int); #endif As primeiras linhas (#ifndef e #define) tem a funao de vericar se o arquivo c cabealho j foi inclu num projeto, antes de inclu novamente de forma desnecessria. c a do -lo a 1

Temos ento dois arquivos: funcoes.c e funcoes.h. Para utiliz-los, devemos gerar a a o arquivo objeto da biblioteca: $ gcc -c funcoes.c -o funcoes.o Se desejar criar um arquivo .a, que possa ser distribu do, utilize o comando: $ ar -cru libfuncoes.a funcoes.o Os arquivos .a so bibliotecas estticas, que tem a vantagem de poder carregar vrios a a a objetos. Nesse caso no faz muita diferena, mas o comando bastante util em projetos a c e maiores. Se quiser saber mais sobre o ar entre em seu manual digitando $ man ar. Agora podemos copiar todos os arquivos para um diretrio separado, por exemplo o ./biblioteca.

1.1

Utilizando a biblioteca

Agora, sempre que for necessrio usar funes denidas no arquivo funcoes.c, incluimos a co o arquivo funcoes.h no programa que vamos implementar. Abaixo um exemplo de cdigo o fonte, que iremos nomear programa.c, que utiliza a biblioteca funcoes: #include <stdio.h> #include "funcoes.h" int main(void) { int b; printf("Valor para calcular o fatorial: "); scanf("%d", b); printf("\n O fatorial de %d = %d", b, fatorial(b)); return 0; } Repare que no utilizamos os sinais de menor/maior para incluir funcoes.h, como na a biblioteca stdio.h. Eles so usados quando o arquivo cabealho estiver instalado num a c diretrio padro do sistema. o a Agora h duas opes de compilaao: uma usando o arquivo objeto e outra usando a a co c biblioteca esttica a Usando biblioteca esttica: preciso instruir o compilador com as opoes de a e c includes e ediao de ligaoes (linker ) para que a biblioteca possa ser inclu no programa c c da executvel. No gcc isso feito utilizando: a e 2

$ gcc programa.c -I./biblioteca -L./biblioteca -lfuncoes -o programa Onde os ags signicam: -I inclui diretrios onde existam cabealhos utilizados no cdigo fonte. o c o -L inclui diretrios onde existam bibliotecas estticas que devem ser inclu o a das no programa. -lfuncoes utiliza o arquivo de biblioteca criado, libfuncoes.a -o programa gera como sa o executvel programa da a Usando o arquivo objeto: preciso instruir o compilador com as opoes de includes e c e manualmente indicar onde est o arquivo objeto. No gcc isso feito utilizando: a e $ gcc programa.c ./biblioteca/funcoes.o -I./biblioteca -o programa Repare que, nesse caso, no utilizamos os ags de diretrios de biblioteca -L nem a o inclu mos a biblioteca esttica -lfuncoes, pois utilizamos o arquivo objeto diretamente. a

Compilao e makeles ca

A compilaao e ligaao de cdigos fonte pode ser uma tarefa complexa quando se utiliza c c o referncias a diversas bibliotecas e quando temos muitos arquivos fonte (.c, .cpp, ...) e para juntar a compilao e gerar o programa. A forma mais simples de compilar arquivos ` ca e obter um executvel utilizando o gcc , por exemplo: a e $ gcc programa.c biblioteca.c funcoes.c -o programa Repare que, nesse exemplo, para obtermos o programa precisamos de trs arquivos de e cdigo fonte. Muitas vezes temos tambm que adicionar o caminho para bibliotecas que o e usamos no nosso programa, o que aumenta a linha de comando, como por exemplo: $ gcc programa.c biblioteca.c funcoes.c -o programa -L/home/lib Ainda, quando alteramos apenas um dos fontes, geralmente compilamos tudo novamente, de forma manual, para obter o programa desejado. Para minimizar esse esforo, c podemos utilizar arquivos makele em conjunto com o utilitrio make. a Makeles so arquivos com um formato especial que auxiliam na compilaao e ligao a c ca de projetos. Make um programa especialmente criado para ler esses arquivos, que e contm as instruoes para tudo o que deve ser feito (make). e c Se voc executar: e 3

$ make esse programa ir procurar por um arquivo chamado Makefile no diretrio atual, e a o ir executar utilizando as instruoes desse arquivo. Se voc tiver mais do que um makele a c e ou seu arquivo possuir um nome diferente, voc pode usar o comando: e $ make -f MeuMakefile que especica o arquivo que voc quer utilizar para gerar seu programa. e

2.1

Arquivos Makele

Um makele um arquivo texto composto basicamente de alvos (target), dependncias e e (dependencies) e comandos (system commands), na forma: target: dependencies <TAB>system command onde <TAB> representa uma tabulao. No arquivo voc realmente precisa usar essa ca e tabulaao para o programa identicar corretamente os comandos a serem executados. c Podemos denir um arquivo da seguinte forma: all: <TAB>gcc programa.c biblioteca.c funcoes.c -o programa -L/home/lib e salv-lo com o nome Makele. Para executar: a $ make No exemplo acima usamos o alvo padro, chamado all. Esse alvo ser executado sem a a qualquer dependncia, ou seja, no precisamos que nenhum outro arquivo exista para e a executar all. Nesse caso, a linha de comando executada diretamente. e

2.2

Dependncias e

Podemos denir mltiplos alvos, cada um com dependncias diferentes, para que o make u e possa executar alvos a partir das dependncias, ou ento para que possamos escolher qual e a alvo desejamos executar. Suponha que tenhamos apenas dois arquivos para compilar, por exemplo, programa.c e funcoes.c, e queremos gerar o executvel programa. Podemos denir o Makefile da a seguinte forma:

programa: funcoes.o programa.o gcc programa.o funcoes.o -o programa programa.o: programa.c gcc -c programa.c funcoes.o: funcoes.c gcc -c funcoes.c Repare que no usamos mais o indicador <TAB>, mas voc dever utilizar uma taa e a bulaao para que o arquivo funcione. Agora temos trs alvos. O utilitrio make ir tentar c e a a resolver as dependncias dentro de cada alvo dispon e vel, executando o comando para gerar cada arquivo necessrio. Caso um dos arquivos j exista e no tenha sido modicado, a a a ele no recompilado. a e No exemplo, inicialmente o make ir tentar executar o alvo programa. Como este a possui duas dependncias: programa.o e funcoes.o, ser preciso antes executar os rese a pectivos alvos para satisfazer as dependncias e compilar o programa. e Supondo que no diretrio existam apenas os arquivos .c, ao executarmos make, a o sequncia de comandos seria: e gcc -c funcoes.c gcc -c programa.c gcc programa.o funcoes.o -o programa Ou seja, primeiro preciso criar o arquivo objeto funcoes.o, a seguir o arquivo e objeto programa.o, para nalmente realizar a ligaao e obter o executvel. Experimente c a alterar apenas um dos arquivos e executar make para vericar que ele recompila apenas as dependncias de arquivos que foram alterados. e Podemos denir dependncias com funes espec e co cas como, por exemplo: programa: funcoes.o programa.o gcc programa.o funcoes.o -o programa programa.o: programa.c gcc -c programa.c funcoes.o: funcoes.c gcc -c funcoes.c clean: rm -rf programa *.o 5

Veja que adicionamos o alvo clean que responsvel por apagar o binrio programa, e a a todos os objetos , ou seja, todos os arquivos com extenso .o. Para que o make execute a apenas a limpeza, utilizamos: $ make clean Denir esse tipo de dependncia util quando queremos rapidamente excluir arquivos e e para recompilar completamente o projeto.

2.3

Variveis, comentrios e detalhes a a

E poss utilizar variveis e comentrios uteis quando queremos denir caminhos, opes vel a a co de compilaao, entre outros. Por exemplo: c # Comentario do makefile # utilizaremos a variavel CP para definir o compilador a ser utilizado CP=gcc # a variavel COPT sera utilizada para adicionar opcoes a compilacao COPT=-c -Wall programa: funcoes.o programa.o $(CP) programa.o funcoes.o -o programa programa.o: programa.c $(CP) $(COPT) programa.c funcoes.o: funcoes.c $(CP) $(COPT) funcoes.c clean: rm -rf *o programa A varivel criada simplesmente atribuindo um valor. E pode ser usada utilizando o a e operador cifro, na forma $(VARIAVEL). Nesse exemplo, poder a amos facilmente trocar o compilador para g++ ou alterar alguma opao de compilao. c ca Se uma linha muito grande, voc pode inserir uma barra invertida, seguida imediatamente e e por uma quebra de linha (ou seja, pressionando ENTER). Um exemplo: CP=gcc 6

p1: $(CP) p1.o biblioteca.h biblioteca.o funcoes.h funcoes.o \ lista.h lista.o -o p1

2.4

Criando mais do que um executvel a

Para criar mais do que um executvel podemos usar o alvo all. Por exemplo, para criar a trs executveis p1, p2 e p3: e a all: p1 p2 p3 p1: funcoes.o prog1.o gcc prog1.o funcoes.o -o p1 p2: biblioteca.o prog2.o gcc prog2.o biblioteca.o -o p1 p3: biblioteca.o funcoes.o prog3.o gcc prog3.o biblioteca.o funcoes.o -o p1

Nesse caso cada executvel tem suas dependncias, que devem ser denidas, se nea e cessrio no arquivo. a

2.5

Gerando um arquivo tar

Muitas vezes precisamos gerar um arquivo compactado com todos os arquivos do projeto. Adicionando um alvo extra podemos gerar por exemplo um arquivo tar: tar: tar cfv programa.tar funcoes.h funcoes.c biblioteca.h \ biblioteca.c lista.h lista.c programa.c Nesse caso, assim como no clean, no h dependncias, sendo o arquivo programa.tar a a e criado quando chamado o comando: $ make tar

2.6

Erros comuns

Os erros geralmente esto relacionados ao uso incorreto da tabulaao (<TAB>). Infeliza c mente elas so dif a ceis de visualizar. Uma dica entrar no editor, posicionar o cursor no e in da linha e mover o cursor para a frente uma vez, se ele pular vrios espaos, temos cio a c uma tabulaao. c Os erros mais comuns so: a 1. Esquecer de inserir a tabulao antes do in dos comandos, ca cio 2. Inserir uma tabulaao no in de uma linha em branco, c cio 3. No inserir uma quebra de linha logo aps uma barra invertida (quando se utiliza a o esse recurso).

2.7

Compilando um projeto com subdiviso em diretrios a o

Muitos projetos em C/C++ utilizam diretrios diferentes para armazenar o cdigo fonte, o o os objetos e bibliotecas. Geralmente utilizam a estrutura: ./projeto ./include ./obj ./lib ./src No diretrio include esto todos os cabealhos, no diretrio obj todos os arquivos objeto, o a c o no diretrio lib as bibliotecas utilizadas e em src os fontes. O uso de make auxilia muito o nesses casos. Suponha um projeto em C++ que ir possuir um unico executvel manage, e que a a utilize uma biblioteca Product que contm a implementao de uma classe de mesmo e ca nome. Assim, temos os seguintes arquivos e diretrios: o ./projeto ./include Product.h ./obj ./lib ./src Product.cc manage.cc

Queremos compilar manage.cc, gerando um executvel manage no diretrio do projeto a o e ao mesmo tempo gerar uma biblioteca para Product, no diretrio lib. No nal teremos: o ./projeto ./include Product.h ./obj Product.o ./lib libProduct.a ./src Product.cc manage.cc Makefile manage Para isso criaremos um Makele com as seguintes variveis: a CC=g++ LIB=./lib INCLUDE=./include SRC=./src OBJ=./obj LIBFLAGS = -lProduct FLAGS = -Wall A primeira varivel dene o g++ como compilador, as prximas quatro nos auxiliaro a a o a controlar os diretrios, e a seguir as vriaveis de ag iro informar ao compilador quais o a a opoes utilizar. Como iremos criar uma biblioteca para Product, inclu c mos a biblioteca como se j estivesse criada em LIBFLAGS (que dever conter todas as bibliotecas estticas a a a a serem inclu das no projeto). J em FLAGS colocamos opoes que desejamos incluir na a c compilaao. c Como o objetivo gerar um s executvel a partir de manage.cc e esse depende da e o a existncia de uma biblioteca, teremos: e manage: Product $(CC) $(SRC)/manage.cc $(FLAGS) -I$(INCLUDE) -L$(LIB) $(LIBFLAGS) \ -o manage

Product: $(CC) -c $(SRC)/Product.cc $(FLAGS) -I$(INCLUDE) -o $(OBJ)/Product.o ar -cru $(LIB)/libProduct.a $(OBJ)/Product.o Ao iniciar, o make ir tentar resolver manage, que depende de Product. O target a Product primeiro compila o arquivo Product.cc, gerando um objeto Product.o na pasta obj. A seguir, cria uma biblioteca no diretrio lib. Finalizada a dependncia, manage.cc o e compilado e um arquivo executvel criado no diretrio do projeto. e a e o Opcionalmente, podemos incluir uma opao para limpar o projeto: c clean: rm manage $(SRC)/*~ $(OBJ)/*o $(LIB)/*a Apaga o executavel, todos os arquivos textos de backup, objetos e a biblioteca. O arquivo Makele nal ca assim: # compilador CC=g++ # variaveis com diretorios LIB=./lib INCLUDE=./include SRC=./src OBJ=./obj # opcoes de compilacao LIBFLAGS = -lProduct FLAGS = -Wall manage: Product $(CC) $(SRC)/manage.cc $(FLAGS) -I$(INCLUDE) -L$(LIB) $(LIBFLAGS) \ -o manage Product: $(CC) -c $(SRC)/Product.cc $(FLAGS) -I$(INCLUDE) -o $(OBJ)/Product.o ar -cru $(LIB)/libProduct.a $(OBJ)/Product.o clean: rm *~ manage $(OBJ)/*o $(LIB)/*a 10

Você também pode gostar