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
BIBFUNC_H
caso este ainda não existaSe existir, é porque o arquivo já foi incluído e portanto, o pré-processador pula o código até o #endif
A seguir, escrevemos o arquivo bibfunc.c, que contém a implementação das funções definidas anteriormente
#include "bibfunc.h"
float fatorial(int v) {
int res = 1, i;
for(i=1; i<=v; i++) res = res * i;
return res;
}
float somatorio(int v) {
float soma = 0, i;
for(i=1; i<=v; i++) soma += i;
return soma;
}
Note que este arquivo deve incluir o arquivo bibfunc.h
Finalmente, o programa principal deve ser implementado em um arquivo separado, como por exemplo main.c:
#include <stdio.h>
#include "bibfunc.h"
int main()
{
int v;
printf("Digite um valor: ");
scanf("%d", &v);
printf("Fatorial: %f\n", fatorial(v));
printf("Somatório: %f\n", somatorio(v));
...
}
Observe que o arquivo bibfunc.h também deve ser incluído, pois contém a definição das funções
Para compilar o programa completo, é preciso indicar todos os fontes na linha de comando:
gcc -o main main.c bibfunc.c
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
Uma solução é compilar individualmente cada módulo:
gcc -c bibfunc.c
gcc -c main.c
O comando gcc -c...
apenas compila um módulo, gerando o código objeto (arquivo .o)
Finalmente, geramos o programa executável, ligando os módulos e as bibliotecas do sistema:
gcc -o main main.o bibfunc.o
Mas como decidir quais módulos precisam ser compilados?
Um Makefile é um roteiro de compilação:
Para utilizá-lo, basta digitar o comando make no terminal
all: main
main: main.o bibfunc.o
gcc -o main main.o bibfunc.o
main.o: main.c
gcc -c main.c
bibfunc.o: bibfunc.c
gcc -c bibfunc.c
O comando gcc -c ...
apenas compila o módulo especificado, produzindo um arquivo .o, que é o chamado código-objeto (sem ligação com bibliotecas)
Os comandos de compilação não parecem meio repetitivos? Podemos melhorar o Makefile, criando regras genéricas:
CFLAGS = -Wall -g # Opções do compilador: todos warnings e debug info
PROG = main
FONTES = main.c bibfunc.c
OBJETOS = $(FONTES:.c=.o)
$(PROG): $(OBJETOS)
gcc $(CFLAGS) $(OBJETOS) -o $@
clean:
-@ rm -f $(OBJETOS) $(PROG)
PROG = ...
define o nome do programa executávelFONTES = ...
define todos os módulosOBJETOS = ...
define como transformar um .cpp em um .oclean
permite apagar os arquivos .o e executável gerados (make clean
)Se estiver disponível, o comando makedepend
pode ser usado para gerar automaticamente todas as dependências dos módulos:
...
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:
Scons - escrito em Python, oferece uma sintaxe mais flexível, é multiplataforma e tem diversos recursos interessantes
CMake (Cross-Platform Make) - este sistema tem o objetivo de gerar Makefiles adaptados para a plataforma de compilação
QMake - outro sistema semelhante, normalmente distribuído com o toolkit Qt, também multiplataforma
Boost.Build - específico para C++, também multiplataforma e com uma sintaxe simples
GNU Build System (autotools) - sistema mais utilizado atualmente para instalação de software no Linux/Unix (Com software adicional instalado, pode ser utilizado também no Windows)
Obs: projetos criados em IDEs como Visual Studio, Code::Blocks, Qt Creator, XCode, NetBeans, etc... simplesmente automatizam essa tarefa