2010-02-16 20 views
12

J'ai un Makefile.am qui sera responsable de la construction d'un binaire d'application finale:Comment est-ce que je spécifie dans un manuscrit de Makefile.am que je veux seulement compiler des fichiers d'objet .o qui peuvent être liés plus tard?

projet/src/Makefile.am

également dans le répertoire src est un sous-répertoire appelé ctrnn qui contient un autre Makefile.am:

projet/src/ctrnn/Makefile.am

maintenant, ctrnn/Makefile.am ne doit générer objet .o fichiers avec l'idée étant que le haut niveau Makefile.am doit utiliser le fichiers objet générés dans le sous-répertoire ctrnn pour générer le binaire.

C'est le ctrnn/Makefile.am

SOURCES = network.cpp\ 
    neuron.cpp 

AM_CPPFLAGS= @[email protected] 

Sur la base de ce fichier Makefile.am, je veux finir avec network.o et neuron.o. Je suis générer le Makefile selon l'utilisation automake etc, mais lorsque je tente puis exécutez le fichier makefile, il ne fait rien et dit simplement:

Marque: Rien à faire pour `tous »

I savoir pourquoi c'est, j'ai besoin de spécifier la cible de construction. Mais comment faire cela dans le script ctrnn/Makefile.am étant donné que je ne veux pas construire un binaire qui nécessiterait bin_PROGRAMS mais des fichiers objet réels network.o et neuron.o?

(Notez que si je spécifie un nom bin_PROGRAMS, il finit à juste titre par se plaindre d'une référence indéfinie à main).

Qu'est-ce que je fais mal?

Merci, Ben.

Répondre

25

Automake ne peut pas créer d'objets sans cible explicite (programme, bibliothèque) qui utilisera ces objets. Une raison est que les options de compilation sont spécifiées par cible. Si deux cibles, par ex. deux binaires utilisent le même objet mais ont une option de compilation différente, le même objet peut devoir être compilé deux fois.

Vous avez trois façons de faire ce que vous voulez, elles impliquent toutes d'attacher vos fichiers source à une cible.

  1. Ne pas utiliser un src/ctrnn/Makefile.am, simplement faire référence aux fichiers sources sous-répertoire de votre src/Makefile.am:

     
    bin_PROGRAMS = foo 
    foo_SOURCES = main.c crtnn/network.cpp crtnn/neuron.cpp 
    
    Notez que ce construira network.o et neuron.o dans le même répertoire que main.o. Si vous voulez des objets dans les sous-répertoires, utilisez AUTOMAKE_OPTIONS = subdir-objects.

  2. Utilisez une bibliothèque de commodité. En src/crtnn/Makefile.am faire une bibliothèque de vos deux objets:

     
    noinst_LIBRARIES = libcrtnn.a 
    libcrtnn_a_SOURCES = network.cpp neuron.cpp 
    
    et dans src/Makefile.am, liez votre exécutable à la bibliothèque:
     
    bin_PROGRAMS = foo 
    foo_SOURCES = main.c 
    foo_LDADD = crtnn/libcrtnn.a 
    SUBDIRS = crtnn 
    
    Il est appelé « commodité » quand il ne va pas être installé (vous pouvez dire à cause du préfixe noinst_): il est juste utilisé pendant la construction. Et ceci est une bibliothèque statique, donc le résultat est le même que si vous aviez remplacé crtnn/libcrtnn.a par crtnn/network.o et crtn/neuro.o lors de la liaison foo.

  3. Utilisez une bibliothèque pratique Libtool. Cela nécessite plus d'installation si vous n'utilisez pas déjà Libtool. Vous devez ajouter un appel LT_INIT dans configure.ac et réexécuter autoreconf pour installer les fichiers libtool. Ensuite, vous pouvez mettre à jour src/crtnn/Makefile.am pour faire une bibliothèque de vos deux objets comme suit:

     
    noinst_LTLIBRARIES = libcrtnn.la 
    libcrtnn_la_SOURCES = network.cpp neuron.cpp 
    
    et src/Makefile.am comme suit:
     
    bin_PROGRAMS = foo 
    foo_SOURCES = main.c 
    foo_LDADD = crtnn/libcrtnn.la 
    SUBDIRS = crtnn 
    
    Quelle est la différence? vous pouvez demander, presque aucun. Un avantage de l'utilisation des librairies Libtool est qu'elles peuvent être imbriquées: une librairie Libtool peut inclure une autre librairie Libtool (ceci est pratique lorsque vous avez une hiérarchie profonde de code source et que vous construisez une librairie à chaque niveau). Les librairies Libtool peuvent également être utilisées pour créer une bibliothèque partagée si vous le souhaitez. Les bibliothèques statiques d'Automake ne le peuvent pas.

+1

Merci! J'ai fini par utiliser la méthode libtool, fonctionne parfaitement :-) –

+2

Merci pour un coup de main pour moi luttant dans l'enfer autotools/libtool. Et faites-nous tous une faveur: vivez longtemps et prospérez! – rockdaboot

+0

foo_LDADD? N'est-ce pas supposé être foo_LIBADD –

2

Vous pouvez simplement spécifier les fichiers source dans le projet/src/Makefile.am et non un Makefile.am dans ctrnn:

 
maude_SOURCES = ctrnn/network.cpp ctrnn/neuron.cpp 

ou vous pouvez utiliser une bibliothèque de proximité libtool. Dans ctrnn/Makefile.am, mis:

 
noinst_LTLIBRARIES = libctrnn.la 
libctrnn_la_SOURCES = network.cpp neuron.cpp 

et dans src/Makefile.am, mis

 
LDADD = ctrnn/libmylib.la 

Si vous n'êtes pas déjà utilisé libtool, vous aurez également besoin d'ajouter à LT_INIT configure.ac.

0

Mieux encore, vous pourriez forcer une marque en utilisant une cible de source moins en faisant ceci:

SUBDIRS = sub1 sub2 … 
lib_LTLIBRARIES = libtop.la 
libtop_la_SOURCES = 
# Dummy C++ source to cause C++ linking. 
nodist_EXTRA_libtop_la_SOURCES = dummy.cxx 
libtop_la_LIBADD = \ 
    sub1/libsub1.la \ 
    sub2/libsub2.la \ 
... 

La sauce secrète est nodist_EXTRA_xxxx_la_SOURCES.

Plus de détails ici: https://www.gnu.org/software/automake/manual/html_node/Libtool-Convenience-Libraries.html