Pages

Monday, January 30, 2012

Uma visão básica e essencial sobre Autotools - Parte II


Nessa segunda parte veremos como gerar um makefile a partir do comando Automake, inserir bibliotecas e outros comandos e informações necessárias.

Na Parte I, geramos um script que verifica as dependências e configurações do sistema para a compilação dos códigos-fonte: o 'configure'. A partir da execução desse script, temos a geração do Makefile e assim podemos compilar nosso código.

Antes de continuarmos, vamos sanar o problema da falta do arquivo "config.h.in". Para isso, executamos simplesmente,

autoheader

Verificamos que, se executarmos o script 'configure' novamente, o erro "config.status: error: cannot find input file: `config.h.in'" não será exibido e ao invés disso, ele criará o arquivo "config.h".

Tal arquivo é o que garante a portabilidade do código no momento da compilação. Nele é possível colocar as definições necessárias para as diretivas de compilação, por exemplo.


Gerando um Makefile a partir do Automake

Uma das características mais interessantes dessas ferramentas, na minha opinião, é justamente essa: poder gerar um makefile completo e de forma automática. Primeiramente, devemos incluir o comando no nosso script que indica a criação de um Makefile automatico. Portanto, no arquivo "configure.ac" incluímos o seguinte trecho,

...
C_PREREQ([2.67])
AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([src/helloworld.c])
AC_CONFIG_HEADERS([config.h])
...

Continuando, devemos agora renomear nosso simples Makefile criado inicialmente para 'Makefile.in',

mv Makefile Makefile.in

Ou seja, nosso makefile servirá como input para a criação do novo arquivo. E, antes de executar o comando principal, executamos,

aclocal

A execução cria o arquivo aclocal.m4 que por sua vez une todas as macros necessárias para a compilação, inclusive as definidas pelo programador, em um único arquivo.

Criamos o arquivo 'Makefile.am' para especificar os parametros a serem definidos pelo Automake. Abaixo um exemplo para nosso programa "hello world".

# Exemplo de Makefile.am

bin_PROGRAMS=helloworld
helloworld_SOURCES=src/helloworld.c

CLEANFILES=./*.o \
        helloworld

Enfim, executamos,

automake --add-missing --copy

Os parametros "--add-missing" e "--copy" fazem com que o automake copie arquivos necessários como o "install-sh" e "missing" que ainda não estão presente no nosso projeto.

A Saída da execução do comando em questão identificará a falta de alguns arquivos. A simples criação deles resolve o problema!

touch ./NEWS ./README ./AUTHORS ./ChangeLog

Os nomes dos arquivos são bem sugestivos às suas reais finalidades.


Incluindo bibliotecas específicas

Muitas vezes, nosso projeto necessita da importação de algumas bibliotecas e como elas são inseridas na configuração e geração do Makefile? A resposta é continuação desse tutorial.

Iremos utilizar duas bibliotecas a "math.h" e as bibliotecas da Glib.

Começando pela "math.h", alteremos o código do helloworld.c na pasta 'src/'.

// helloworld.c com Math.h

#include <stdio.h>
#include <math.h>

#define PI 3.1415926

int main(int argc, char *argv[]) {

float x = sin(PI/6);

printf("Seno de 60: %f\n", x);

return 0;
}

Inicialmente, devemos abrir o arquivo "configure.ac" e inserir o seguinte trecho em vermelho.

...
# Checks for libraries.
AC_CHECK_LIB(m, sin)
...

Lembre-se que quando compilamos, passamos o parâmetro "-lm" para incluir a "math.h". Logo o "m" representa tal parametro. A segunda entrada checa se existe a função "sin()" na biblioteca verificada.

Salve o arquivo "configure.ac" e execute,

autoreconf
make
./helloworld

Agora, a biblioteca "math.h" pode ser usada tranquilamente no projeto.

E se por um acaso, as libs estão em pastas específicas? Você pode adicioná-las antes da checagem acima usando,

LDFLAGS = "$LDFLAGS -L/local_da_sua_lib/"
CFLAGS = "$CFLAGS -I/local_da_sua_lib/"

No caso da Glib, quando pretendemos compilar um código-fonte que faz o uso da biblioteca usamos comumente o pkg-config passando o parametro: `pkg-config --cflags --libs glib-2.0`.

Para configurá-lo adequadamente devemos inserir o seguite código no arquivo 'configure.ac',

...
AC_CONFIG_HEADERS([config.h])

# Check libraries with pkg-config
PKG_CHECK_MODULES(GLIB, glib-2.0)

# Checks for programs.
AC_PROG_CC
...

Dessa forma, o script 'configure' irá verificar as dependências e adicionar o parâmetro citado automaticamente no Makefile gerado.

Por fim, toda a configuração necessária para incluir uma biblioteca na configuração do Automake usando duas maneiras diferentes de inclusão foi demonstrada acima.


O diretório autom4te.cache

Como fora dito na Parte I, nota-se que quando é executado o 'autoconf' uma pasta chamada autom4te.cache é criada. O intuito dela é guardar informações para que a execução de outras ferramentas como o 'autoheader' e o 'automake' seja facilitada. Ou seja, quando reconfiguramos alguns arquivos referentes ao 'automake' não é necessário executar toda vez o 'autoconf' porque os dados necessário já estão salvos (cached) no diretório 'autom4te.cache'. A sua presença não é vital para o projeto, mas a sua remoção força a execução do 'autoconf' toda vez que um comando precisar dos dados de saída do mesmo.


Conclusão

O Tutorial apresentado foi uma visão extremamente básica sobre a ferramenta GNU Autotools para que qualquer desenvolvedor interessado possa já configurar seu projeto facilmente e torná-lo portável. Há materiais na literatura e na internet de fácil acesso que abordam assuntos mais aprofundados. Inclusive, o próprio manual da ferramenta (como exemplo o Autoconf Manual) é um excelente guia de estudo avançado.


Referências Extras

Friday, October 21, 2011

Uma visão básica e essencial sobre Autotools - Parte I


O que é o Autotools?

O Autotools ou, como também é chamado, GNU build system é comumentemente utilizado por desenvolvedores de software livre para tornar seu programa bastante portável e, principalmente, para prover uma automatização ao projeto.
Com o GNU Make já é possível obter uma automatização sensível na elaboração e construção de qualquer projeto, entretanto, quando usamos o GNU Automake até o próprio arquivo de Makefile é gerado automaticamente, ou seja, não é mais necessário gastar tempo na codificação de um arquivo Makefile, por exemplo.
A Ferramenta GNU Autoconf é mais interessante ainda. Com ela é possível gerar scripts que configuram seu projeto de forma automática, adaptando-o ao sistema que está sendo usado e verificando as dependências necessárias.


Colocando a mão na massa!

Neste post, abordaremos uma visão simples e fácil para utilizarmos o Autotools em nossos projetos.

Antes de iniciar, devemos baixar os pacotes essenciais. Com um simples apt-get (para sistemas Debian-like) resolvemos o problema.

$ sudo apt-get install autoconf automake

Depois de instalados, podemos iniciar a automatização de nosso projeto com um "Hello World!" básico a seguir,

// helloworld.c
#include <stdio.h>

int main(int argc, char *argv[]) {

printf("Hello world!\n");

return 0;
}

Para dificultar colocaremos o código-fonte em uma pasta chamada "src" e na pasta base criaremos o makefile a seguir,

#makefile

all:
gcc -o helloworld src/helloworld.c

clean:
rm -r -f helloworld *.o src/*.o

Portanto, já temos nosso código base na pasta "src" e o makefile na pasta raiz. Agora iniciaremos o uso do GNU Autotools. Para isso, realizaremos todas as operações na pasta raiz (onde se encontra o makefile). Portanto, no shell devemos efetuar primeiramente,

$ autoscan

Gerando dois arquivos: o autoscan.log e o configure.scan. Devemos renomear esse útlimo para que ele sirva como entrada para geração do script de configuração pelo comando autoconf.

$ mv configure.scan configure.ac

e por fim,

$ autoconf

Notemos que foi criado um script chamado "configure" e uma pasta chamada "autom4te.cache". Veremos mais a frente o porquê esta pasta é necessária.

Antes de executarmos nosso script devemos renomear o nosso makefile para "makefile.in". Afinal, ele será um input para o script gerar o makefile.

mv makefile makefile.in

Já podemos então executar o script configure.

./configure

A saída esperada será:

checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
configure: creating ./config.status
config.status: creating makefile
config.status: error: cannot find input file: `config.h.in'

Notemos que ele não achou o arquivo de entrada "config.h.in", porém ele gerou o makefile.
Logo, podemos executar esse script em qualquer máquina para gerar o makefile automaticamente, verificando as dependências.

Agora basta um simples comando make para compilar e gerar o binário desejado.

Por fim, chegamos aos primeiros passos da utilização do GNU Autotools, mais a frente iremos aprender novos conceitos, inserir bibliotecas e gerar um makefile a partir do Automake.


Referências

Algumas Referências interessantes sobre Autotools:

http://www.lrde.epita.fr/~adl/autotools.html
http://markuskimius.wikidot.com/programming:tut:autotools