The Joy of Autotools!

2010 May 24
by Pedro Kiefer

Toda a vez que eu leio Autotools eu lembro dos Autobots, não sei porque a associação. Mas esse post não é sobre isso, e talvez ele renda mais do que um post. Nas últimas semanas ajudei a migrar dois projetos que utilizavam Makefiles hand-crafted para utilizarem todo o pacote das Autotools.O primeiro passo para que a migração fosse tranquila foi ensinar os conceitos básicos das Autotools para todos os envolvidos no projeto.

Existem diversos tutoriais, livros e blogs explicando como utilizar estas ferramentas, mas a maioria exige bastante tempo para deglutir todas as informações expostas e conseguir utilizar o sistema. Para facilitar, criei uma página na wiki interna mostrando os arquivos necessários para se criar um projeto básico utilizando autotools. Este post é uma tentativa de extender este conteúdo e divulgar o uso das Autotools.

Alguns arquivos essênciais

Basicamente todo o conjunto de ferramentas necessita de dois arquivos para funcionar:

  • configure.ac: diretivas para gerar o script de configuração, testar a existência de bibliotecas, headers, comandos, etc.
  • Makefile.am: o que deve ser compilado, bibliotecas, binários, sub-diretórios, programas de teste, etc.

Com esses dois arquivos na raiz do projeto e mais alguns Makefile.am nos subdiretórios, é tudo o que se necessita para utilizar as Autotools. Obviamente isto é só o inicio da brincadeira, diversos detalhes devem ser adicionados para deixar o sistema de build de forma adequada ao projeto.

Aos arquivos!

configure.ac

AC_INIT([project_name],[version],[maintainer_email])
AC_CONFIG_SRCDIR([.])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([config.h])

AM_INIT_AUTOMAKE([foreign])
AM_MAINTAINER_MODE

AC_PROG_LIBTOOL
AC_PROG_CC

AC_CONFIG_FILES([Makefile])
AC_OUTPUT

Bom, olhando assim, esses comandos parecem uma grande sopa de letrinhas, sem sentido algum. Então, como Jack faria (piada fraca, eu sei), vamos por partes. A primeira linha inicializa o autoconf, e portanto ali estão definidos o nome do projeto, a versão, e o endereço de email do mantenedor. As próximas três linhas definem configurações gerais do autoconf, como diretório onde se encontram os arquivos de source, onde devem ser guardadas e lidas as macros utilizadas pelo autoconf, e finalmente qual é o nome do arquivo de header que o autoheader irá gerar.

Destas diretivas, duas devem ser destacadas,AC_CONFIG_SRCDIR que define qual é o diretório onde se encontram os arquivos fontes do programa, que é de escolha do programador; e a AC_CONFIG_MACRO_DIR que define o diretório onde estão as macros do autoconf, no exemplo, os arquivos são salvos no subdiretório m4. É importante que este diretório exista, pois caso contrário, gerará um erro quando rodarmos o autoreconf – mais sobre esta ferramenta no final do post.

Depois de inicializado o autoconf deve-se inicializar o automake, uma vez que optamos por utilizar todo o conjunto das Autotools. As duas diretivas iniciadas em AM são responsáveis por inicializar o automake e por optar pelo modo maintainer, que evita alguns arquivos sejam refeitos quando distribuidos para o usuário final. A diretiva AC_PROG_CC é responsável por testar a existência de um compilador C instalado no sistema. Já a AC_PROG_LIBTOOL testa e inicializa o uso da ferramenta libtool, necessária para gerar bibliotecas.

As últimas duas linhas são extremamente importantes, e deve-se tomar bastante cuidado para que todos os arquivos que se deseja gerar após rodar um ./configure estejam listados na diretiva AC_CONFIG_FILES.

Makefile.am

Com o arquivo configure.ac escrito, é hora de definir o que será gerado: um programa, uma biblioteca, ambos, arquivos extras que devem ser instalados, etc. Para isso é necessário escrever as diretivas necessárias no Makefile.am.

ACLOCAL_AMFLAGS = -I m4

bin_PROGRAMS = myproject
lib_LTLIBRARIES = libproject.la

myproject_SOURCES = \
	myproject.c \
	mymem.c 

libproject_la_SOURCES = \
	myhash.c \
	mylib.c
libproject_ladir = $(includedir)/libproject
libproject_la_HEADERS = \
	mylib.h

A primeira diretiva só adiciona a flag -I m4 quando o aclocal é chamado, indicando qual o diretório que contêm os script m4. Se o seu projeto possuiu um hierarquia de makefiles você só precisa adicionar essa diretiva no Makefile.am da raiz do projeto.

As próximas duas linhas definem o que será gerado pelo automake. A primeira linha define os executáveis a serem gerados, já a segunda define as bibliotecas geradas pelo projeto. Para programas gerados, podemos usar alguns prefixos diferentes a diretiva PROGRAMS como: bin, sbin, libexec e pkglib, isso instruirá o autotools o local onde o binário será instalado. Também há a opção de não instalar o programa usando o prefixo noinst, ou ainda check que só irá gerar o binário quando executado make check. Para bibliotecas os prefixos possíveis são lib, pkglib e noinst, seguidos da diretiva LTLIBRARIES. O que segue após o sinal de igualdade são os nomes dos binários ou bibliotecas que serão gerados.

Para cada objeto a ser gerado é necessário definir quais são os arquivos fontes necessários. Também é possível definir flags, biblotecas, etc. específicas para cada objeto, para mais informações sobre estas outras variáveis leia aqui. O mais comum é usar a diretiva SOURCES com uma lista de arquivos fonte necessários para gerar o objeto em questão. Para a biblioteca também foi definido o diretório de instalação dos headers (ladir) e o header da biblioteca – necessário para outros projetos poderem linkar com a nossa biblioteca.

Com isso temos um Makefile.am básico, hora de gerarmos os scripts de configuração.

Gerando os arquivos!

Tendo os dois arquivos no diretório do projeto (configure.ac e Makefile.am) é hora de gerar o script de configuração e o Makefile do projeto. Por muito tempo os diversos projetos que usam Autotools mantiveram scripts próprios para rodar as diversas ferramentas necessárias (automake, autoconf, autoheader, aclocal, etc) para gerar todo o sistema de build, os famosos scripts autogen.sh. Atualmente não é mais necessário utilizar estes scripts, basta chamar o programa autoreconf. Eu gosto de utilizar as flags -i, para copiar os arquivos necessários para o diretório do projeto, e -v para exibir as mensagens dos programas executados.

autoreconf -iv

Wrap up & Links

Este post talvez nunca esteja pronto, e irá evoluir aos poucos. Seguem alguns link úteis!

No comments yet

Leave a Reply

Note: You can use basic XHTML in your comments. Your email address will never be published.

Subscribe to this comment feed via RSS

Bad Behavior has blocked 57 access attempts in the last 7 days.