Makefile.am

Como escrever um Makefile.am

Este documento foi deliberadamente traduzido do Capítulo 9 do manual do automake-1.7.2 e uma cópia do original pode ser encontrada em http://www.gnu.org/manual/automake-1.7.2. Esta tradução está submetida aos mesmos direitos de licença GPL do manual original; uma cópia da licença pode ser encontrada em http://www.gnu.org/licenses/gpl.html.


9.1 Construindo um programa

Para construir um programa você precisa dizer ao Automake quais fontes o constituem e quais bibliotecas devem ser ligadas à ele.

Esta seção também cobre a compilação condicional de fontes do programa. A maioria dos comentários sobre esse assunto também se aplica às bibliotecas (veja seção 9.2 Construindo uma Biblioteca) e bibliotecas construídas através do Libtool (veja seção 9.3 Construindo uma Biblioteca Compartilhada).


9.1.1 Definindo fontes do programa

Em um diretório contendo fontes constituem um programa (diferentemente de uma biblioteca ou de um script), a primitiva 'PROGRAMS' é usada. Os programas podem ser instalados em bindir, sbindir, libexecdir, pkglibdir, ou não devem ser instalados (noinst). Eles também podem ser compilados apenas em verificações (make check), sendo necessário usar nesse caso o prefixo check.

Por exemplo:

bin_PROGRAMS = hello

Neste caso, o arquivo 'Makefile.in´ resultante irá conter código para gerar um programa chamado hello.

Associado a cada programa existem diversas variáveis auxiliares declaradas após a declaração do nome do programa. Todas essas variáveis são opcionais, e possuem valores padrão razoáveis. Cada variável, seu uso, e seu valor padrão estão descritos abaixo; usaremos o exemplo "hello" nos exemplos que se seguem.

A variável hello_SOURCES é usada para especificar quais arquivos fontes constituem o executável final:

hello_SOURCES = hello.c version.c getopt.c getopt1.c getopt.h system.h

Isto faz com que cada arquivo `.c' listado seja compilado com a extensão `.o' correspondente. Todos eles são ligados para produzir o executável `hello'.

Se `hello_SOURCES' não for especificado, então é assumido `hello.c'; isto é, o padrão é compilar um único arquivo C cujo nome base é o nome do programa propriamente dito. (Este é um péssimo valor padrão, mas precisa ser mantido por razões históricas.)

Múltiplos programas podem ser compilados em um único diretório. Múltiplos programas podem compartilhar o mesmo arquivo fonte, que deve ser listado em cada definição `_SOURCES'.

Arquivos de cabeçalho listados em uma definição `_SOURCES' serão incluídos na distribuição mas ignorados para todos os efeitos. Caso isso não seja óbvio para o seu programa, você não deve incluir o cabeçalho gerado pelo `configure' em uma declaração `_SOURCES'; este arquivo não deve fazer parte da distribuição. Arquivos Lex (`.l') e Yacc (`.y') também podem ser listados.


9.1.2 Ligando o programa

Se você necessitar ligar à bibliotecas que não são encontradas pelo `configure', você pode usar a declaração LDADD. Essa variável é usada especificar objetos ou bibliotecas adicionais para fazer parte da ligação; não é apropriado para se declarar parâmetros específicos ao linker: deve-se usar AM_LDFLAGS para esta finalidade.

Às vezes, múltiplos programas são construídos em um mesmo diretório mas não compartilham os mesmos requisitos de tempo de ligação. Neste caso, você pode usar a variável `prog_LDADD' (onde o prog é o nome do programa da mesma forma  que em declarações `_PROGRAMS', e geralmente são escritos em minúsculas) para sobrescrever a variável global LDADD. Se essa variável existe para um determinado programa, então ele não será ligado usando o LDADD global.

Por exemplo, no GNU cpio, pax, cpio e mt são ligados à biblioteca `libcpio.a'. Entretanto, rmt é construído no mesmo diretório, e não necessita de tal ligação. Ainda, mt e o rmtsrc/Makefile.am' é alguma coisa como:

bin_PROGRAMS = cpio pax @MT@
libexec_PROGRAMS = @RMT@
EXTRA_PROGRAMS = mt rmt

LDADD = ../lib/libcpio.a @INTLLIBS@
rmt_LDADD =

cpio_SOURCES = ...
pax_SOURCES = ...
mt_SOURCES = ...
rmt_SOURCES = ...

`prog_LDADD' é inapropriado para enviar parâmetros específicos ao linker (exceto `-l', `-L', `-dlopen' e `-dlpreopen'). Então, use a variável `prog_LDFLAGS' para esta finalidade.

Ocasionalmente é também útil garantir que uma determinada construção depende de outra. Isto pode ser feito usando a variável `prog_DEPENDENCIES'. Cada programa depende dos conteúdo dessa variável, mas nenhuma interpretação adicional é feita.

Se o `prog_DEPENDENCIES' não for declarado, ele é atribuído pelo Automake. O valor atribuído automaticamente será o conteúdo de `prog_LDADD', com a maioria das configurações provindas de substituições do configure, com as opções `-l', `-L', `-dlopen' e `-dlpreopen' removidas. As únicas substituições do configure mantidas são `@LIBOBJS@' e
`@ALLOCA@'; isso porque que elas não irão provocar um valor inválido para o `prog_DEPENDENCIES' gerado.

9.1.3 Compilação condicional

Você não pode pôr uma substituição do configure (p.e., `@FOO@') em uma definição `_SOURCES'. A razão para isso é um pouco complexa para se explicar, mas bastar dizer que simplesmente não funciona. O Automake irá gerar um erro se você tentar fazer isso.

Felizmente há outras duas maneiras conseguir o mesmo resultado. Um é usar substituições do configure nas declarações `_LDADD' e a outra é usar uma condicional do Automake.

9.1.3.1 Compilação condicional usando substituições em _LDADD

Automake deve saber de todos os arquivos fonte que poderiam se tornar parte de um programa, mesmo que alguns sejam opcionais para compilações específicas. Todos os arquivos compilados de forma opcional devem ser listados na declaração `EXTRA_' apropriada. Por exemplo, se `hello-linux.c' ou `hello-generic.c' fossem condicionalmente incluídos em hello, o `Makefile.am' conteria:

bin_PROGRAMS = hello
hello_SOURCES = hello-common.c
EXTRA_hello_SOURCES = hello-linux.c hello-generic.c
hello_LDADD = @HELLO_SYSTEM@
hello_DEPENDENCIES = @HELLO_SYSTEM@

Você pode então criar a substituição de @HELLO_SYSTEM@ no `configure.in' da seguinte maneira:

...
case $host in
*linux*) HELLO_SYSTEM='hello-linux.$(OBJEXT)' ;;
*) HELLO_SYSTEM='hello-generic.$(OBJEXT)' ;;
esac
AC_SUBST([HELLO_SYSTEM])
...

Neste caso, HELLO_SYSTEM deve ser substituído por `hello-linux.o' ou por `hello-bsd.o', e adicionado a hello_DEPENDENCIES e a hello_LDADD a fim ser compilado e ligado.

9.1.3.2 Compilação condicional usando condicionais Automake

Uma maneira geralmente mais simples de incluir condicionalmente arquivos fonte na compilação é usar as condicionais Automake. Por exemplo, você poderia usar este `Makefile.am' para construir o mesmo exemplo `hello':

bin_PROGRAMS = hello
if LINUX
hello_SOURCES = hello-linux.c hello-common.c
else
hello_SOURCES = hello-generic.c hello-common.c
endif

Neste caso, o `configure.in' deve definir a condicional LINUX usando AM_CONDITIONAL (ver a seção 20. Condicionais).

Ao usar condicionais como esta você não irá necessitar usar a variável `EXTRA_', já que o Automake irá examinar o conteúdo de cada variável para construir a lista completa dos arquivos fonte.

Se o seu programa usar muitos arquivos, você provavelmente vai preferir usar uma condicional +=.

bin_PROGRAMS = hello
hello_SOURCES = hello-common.c
if LINUX
hello_SOURCES += hello-linux.c
else
hello_SOURCES += hello-generic.c
endif

9.1.4 Compilação condicional de programas

Em alguns casos é útil determinar quais programas serão construídos em tempo de configuração. Por exemplo, o GNU cpio constrói  mt e rmt somente em alguns casos.

Neste caso, você deve indicar para o Automake todos os programas que podem ser construídos, mas ao mesmo tempo fazer com que o `Makefile.in' gerado use somente os programas especificados pelo `configure'. Isto é feito fazendo configure substituir valores em cada declaração `_PROGRAMS', ao mesmo tempo em que a listagem de todos os programas opcionais são listados em EXTRA_PROGRAMS.

Naturalmente você pode usar condicionais Automake para determinar quais programas devem ser construídos.

9.2 Construindo uma Biblioteca

Construir uma biblioteca é bem parecido com a construção de um programa. Neste caso, o nome da primitiva usada é `LIBRARIES'. As bibliotecas podem ser instaladas em libdir ou pkglibdir.

Veja a seção 9.3 Construindo uma Biblioteca Compartilhada, para informações sobre como construir bibliotecas compartilhadas usando Libtool e a primitiva `LTLIBRARIES'.

Cada variável `_LIBRARIES' é uma listagem de bibliotecas a serem construídas. Por exemplo, para criar a biblioteca denominada `libcpio.a', mas sem instalá-la, você escreveria:

noinst_LIBRARIES = libcpio.a

As fontes que constituem uma biblioteca são determinadas exatamente da mesma forma que para programas, através das variáveis `_SOURCES'. Note que o nome da biblioteca segue uma estrutura definida (ver a seção 2.4 Como variáveis derivadas são nomeadas), então a variável `_SOURCES' correspondente a `liblob.a' é `liblob_a_SOURCES', e não o `liblob.a_SOURCES'.

Objetos extras podem ser adicionados a uma biblioteca usando a variável `library_LIBADD'. Isso deve ser usado em objetos determinados pelo configure. Novamente do cpio:

libcpio_a_LIBADD = @LIBOBJS@ @ALLOCA@

Ainda, os fontes para objetos criados em tempo de configuração devem ser adicionados à variável BUILT_SOURCES.

9.3 Construindo uma Biblioteca Compartilhada

Construir bibliotecas compartilhadas é um assunto relativamente complexo. Para esta razão, o GNU Libtool (ver a seção `Introdução' no Manual do Libtool) foi criado para ajudar a construir bibliotecas compartilhadas de uma maneira independente de plataforma.

O Automake usa o Libtool para construir bibliotecas declaradas com a primitiva `LTLIBRARIES'. Cada variável `_LTLIBRARIES' é uma lista de bibliotecas compartilhadas para serem construídas. Por exemplo, para criar uma biblioteca denominada `libgettext.a' e suas bibliotecas compartilhadas correspondentes, e instalá-las no em `libdir', escreva:

lib_LTLIBRARIES = libgettext.la

Note que as bibliotecas compartilhadas devem ser instaladas para funcionarem corretamente, dessa forma check_LTLIBRARIES não é permitido. Entretanto, noinst_LTLIBRARIES é permitido. Esta característica é usada em "bibliotecas de conveniência" do libtool.

Para cada biblioteca, a declaração `library_LIBADD' contém os nomes de objetos extras do libtool (arquivos `.lo') a serem adicionados à biblioteca compartilhada. A variável `library_LDFLAGS' contém todos os parâmetros para o libtool, tais como `-version-info' ou `-static'.

Onde em uma biblioteca comum inclui @LIBOBJS@, uma biblioteca libtool deve usar @LTLIBOBJS@. Isto é necessário porque os arquivos objeto que o libtool trabalha não possuem necessariamente a extensão `.o'. O manual do libtool contem mais detalhes sobre esse assunto.

Para as bibliotecas instaladas em algum diretório, Automake fornecerá automaticamente a opção `-rpath' adequada. Entretanto, para bibliotecas determinadas em tempo de configuração (e por sua vez listadas em EXTRA_LTLIBRARIES), Automake pode não saber eventualmente qual será o diretório da instalação; para tais bibliotecas você deve adicionar a opção `-rpath' à variável `_LDFLAGS' apropriada manualmente.

Normalmente, o Automake requer que uma biblioteca compartilhada tenha o prefixo `lib'. Entretanto, se você está construindo um módulo de carga dinâmica então você pode desejar usar um nome "não-padrão". Neste caso, ponha -module na variável `_LDFLAGS'.