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!

Miniature Effect

2010 May 23
by Pedro Kiefer

Depois de ver tantas propagandas e fotos usando este efeito, ontem resolvi brincar um pouco e aplica-lo à esta foto. Acho que o resultado ficou bem interessante. Vou procurar outras fotos minhas que possam ficar legal com esse efeito.

Miniature

Praia do rosa em miniatura

Miniature 3

Torres, Praia Grande

Miniature 2

Porto Alegre

API para UART

2010 May 12
by Pedro Kiefer

Problema do dia: como definir uma API para uma porta serial, quando ela não existe e é emulada em software através de uma porta USB? Condições de contorno, pra variar não são triviais: não há libc, não há kernel, nem select’s, nem fopen’s.
Fazer a USB se anunciar como um device serial foi a parte trivial do problema, ok, não tão trivial, pois a spec da USB é bastante gigante.

Update: Decidida a API necessária, com essas quatro funções pode-se manipular a vontade uma porta serial-usb:

  • getc
  • putc
  • read
  • write

I’m Nerd!

2010 April 22
by Pedro Kiefer

Vi o link pra esse meme num blog e resolvi fazer o teste… bom sou 82% nerd :-P (na real, acho que bem mais, mas ok)

I am nerdier than 82% of all people. Are you a nerd? Click here to take the Nerd Test, get nerdy images and jokes, and talk on the nerd forum!

Histórias de ninar de um engenheiro

2009 December 14
by Pedro Kiefer

Hoje no trabalho, enquanto escrevia um driver novo pra kernel do linux, tivemos uma discussão sobre histórias de ninar de engenheiros, físicos, computólogos, matemáticos, etc… esse povo todo das exatas. A primeira história que lembramos foi a versão ‘exatas’ para os três porquinhos que começa assim:

… Era uma vez três porquinhos ( P1, P2 e P3) e um Lobo Mau, por definição, LM, que vivia os atormentando. P1 era sabido e fazia Engenharia Elétrica e já era formado em Engenharia Civil.
P2 era arquiteto e vivia em fúteis devaneios estéticos absolutamente desprovidos de cálculos rigorosos. P3 fazia Comunicação e Expressão Visual na ECA. LM, na Escala Oficial da ABNT, para medição da Maldade (EOMM) era Mau nível 8,75 (arredondando a partir da 3ª casa decimal para cima)…

Obviamente começamos a pensar em outras histórias, contando as coisas divertidas que fazemos diariamente. Falando de Linux, transistores, FPGAs, spinlock’s, threads, BUG_ON()… não sei se daria uma história muito engraçada, afinal, que criança iria entender! Mas com certeza demos muitas risadas. Algo nessa linha representa as bobagens que inventamos:

Era uma vez um Driver feliz, que funcionava perfeitamente na sua kernel 2.6.18… mas os tempos passaram, e melhorias foram feitas no código da kernel. O Driver feliz estava ficando triste por estar desatualizado, então seu fiel programador resolveu atualizar suas funcionalidades para ele ser ainda mais feliz.

O seu fiel programador não sabia muito sobre as grandes novidades do kernel, e também tinha dormindo nas aulas sobre kernel threads e spinlock’s. Não sabendo dessas novidades, o programador achou melhor não incluir todos aqueles spinlock’s que o Driver feliz tinha.

O Driver feliz então ficou muito triste, pois só fazia kernel panic’s, não conseguia mais ser feliz. Era agora um Driver infeliz… Mas eis que então um superprogramador surge para salvar o Driver feliz da sua infelicidade. O superprogramador não tinha dormido nas aulas de spinlock’s, e em pouco tempo fez o Driver feliz voltar a ser o mais feliz de todos os drivers.

Espero nunca contar algo tipo isso pros meus futuros filhos! Mas, talvez seja inevitável… vou ter que esperar para descobrir.

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