Marcelo Cohen, FACIN - PUCRS
Agrupam-se as funções relacionadas em módulos. Para cada módulo são utilizados dois arquivos:
Para usar uma função em outro módulo, basta então incluir o arquivo .h correspondente
Para exemplificar, criaremos uma biblioteca simples de funções matemáticas. Primeiro, escrevemos os protótipos das funções no arquivo bibfunc.h:
float fatorial(int v);
float somatorio(int v);
...
Porém, se por engano esse arquivo for incluído mais de uma vez, haverá uma duplicidade de todas as definições. Como isso pode acontecer facilmente, acrescentamos 3 linhas no arquivo .h:
#ifndef BIBFUNC_H
#define BIBFUNC_H
float fatorial(int v);
float somatorio(int v);
...
#endif
A seguir, escrevemos o arquivo bibfunc.cpp, que contém a implementação das funções definidas anteriormente.
#include "bibfunc.h"
float fatorial(int v) {
int res = 1;
for(int i=1; i<=v; i++)
res = res * i;
return res;
}
...
Finalmente, o programa principal deve ser implementado em um arquivo separado, como por exemplo main.cpp:
#include <iostream>
#include "bibfunc.h"
using namespace std;
int main()
{
cout << "Digite um valor: ";
int v;
cin >> v;
cout << "Fatorial: " << fatorial(v);
cout << "Somatório: " << somatorio(v);
...
}
Para compilar o programa completo, é preciso indicar todos os fontes na linha de comando:
Porém, essa estratégia tem algumas implicacões:
Para um programa tão pequeno, isso não faz tanta diferença...
Mas se o programa for composto por muitos módulos, compilá-los separadamente pode ter um custo considerável, além de não ser muito prático.
Um Makefile é um roteiro de compilação:
O nome do arquivo deve ser preferencialmente Makefile.
Para utilizá-lo, basta digitar o comando make no terminal.
all: main
main: main.o bibfunc.o
g++ -o main main.o bibfunc.o
main.o: main.cpp
g++ -c main.cpp
bibfunc.o: bibfunc.cpp
g++ -c bibfunc.cpp
Os comandos de compilação não parecem meio repetitivos ? Podemos melhorar o Makefile, criando regras genéricas:
CXXFLAGS = -Wall -g # Opções do compilador: todos warnings e debug info
PROG = main
FONTES = main.cpp bibfunc.cpp
OBJETOS = $(FONTES:.cpp=.o)
$(PROG): $(OBJETOS)
g++ $(CXXFLAGS) $(OBJETOS) -o $@
clean:
-@ rm -f $(OBJETOS) $(PROG)
Mas e como especificar dependências automáticas para os .h ?
Uma forma é incluir uma regra que use o comando makedepend:
...
clean:
-@ rm -f $(OBJETOS)
depend:
makedepend -- ${CFLAGS} -- ${FONTES}
Ao digitarmos make depend, o comando makedepend será ativado, e verificará as dependências de cada módulo, incluindo estas no final do próprio Makefile:
...
depend:
makedepend -- ${CFLAGS} -- ${FONTES}
# DO NOT DELETE
main.o: bibfunc.h
bibfunc.o: bibfunc.h
Já existem alguns sistemas alternativos ao make: