2010-02-16 7 views
12

Ho un Makefile.am che sarà responsabile per la costruzione di un binario di applicazione finale:Come faccio a specificare in uno script Makefile.am che voglio solo compilare oggetti .o file che possono essere successivamente collegati?

progetto/src/Makefile.am

anche nella directory src è un sotto-directory chiamata ctrnn che contiene un ulteriore Makefile.am:

progetto/src/ctrnn/Makefile.am

Ora, ctrnn/Makefile.am dovrebbe generare solo oggetto .o file con l'idea è che il livello superiore Makefile.am dovrebbe utilizzare il file oggetto generati nella sottodirectory ctrnn per costruire il binario.

Questa è la ctrnn/Makefile.am

SOURCES = network.cpp\ 
    neuron.cpp 

AM_CPPFLAGS= @[email protected] 

Sulla base di questo file Makefile.am, voglio finire con network.o e neuron.o. Sto generare il Makefile secondo utilizzando automake ecc, ma quando provo e poi eseguire il file marca, ma non fa nulla e si limita a dire:

marca: Niente da fare per `tutti'

I so perché questo è, ho bisogno di specificare l'obiettivo di costruzione. Ma come faccio a farlo nello script ctrnn/Makefile.am dato che non voglio creare un binario che richieda bin_PROGRAMS ma i file oggetto reali network.o e neuron.o?

(Nota se si specifica un nome bin_PROGRAMS, giustamente finisce per lamentarsi di un riferimento non definito al main).

Cosa faccio di sbagliato?

Grazie, Ben.

risposta

25

Automake non può creare oggetti senza un target esplicito (programma, libreria) che utilizzerà questi oggetti. Una ragione è che le opzioni di compilazione sono specificate per target. Se due obiettivi, ad es. due file binari utilizzano lo stesso oggetto ma hanno un'opzione di compilazione diversa, lo stesso oggetto potrebbe dover essere compilato due volte.

Hai tre modi per fare ciò che vuoi, tutti implicano legare i tuoi file sorgente ad un obiettivo.

  1. Non utilizzare un src/ctrnn/Makefile.am, basta fare riferimento ai file di origine sottodirectory dal src/Makefile.am:

     
    bin_PROGRAMS = foo 
    foo_SOURCES = main.c crtnn/network.cpp crtnn/neuron.cpp 
    
    Si noti che questo costruirà network.o e neuron.o nella stessa directory di main.o. Se vuoi oggetti in sottodirectory, usa AUTOMAKE_OPTIONS = subdir-objects.

  2. Utilizzare una libreria di convenienza. In src/crtnn/Makefile.am fare una libreria di due oggetti:

     
    noinst_LIBRARIES = libcrtnn.a 
    libcrtnn_a_SOURCES = network.cpp neuron.cpp 
    
    e in src/Makefile.am, collegare il tuo eseguibile alla libreria:
     
    bin_PROGRAMS = foo 
    foo_SOURCES = main.c 
    foo_LDADD = crtnn/libcrtnn.a 
    SUBDIRS = crtnn 
    
    Si chiama "convenienza" quando non sta per essere installato (si può dire perché del prefisso noinst_): si è appena usato durante la compilazione. E questa è una libreria statica, quindi il risultato è lo stesso di quello che avevi sostituito crtnn/libcrtnn.a per crtnn/network.o e crtn/neuro.o quando si collegava foo.

  3. Utilizzare una libreria di convenienza Libtool. Ciò richiede più setup se non stai già usando Libtool. È necessario aggiungere una chiamata LT_INIT in configure.ac e rieseguire autoreconf per installare i file libtool. Quindi è possibile aggiornare src/crtnn/Makefile.am per creare una libreria dei due oggetti come segue:

     
    noinst_LTLIBRARIES = libcrtnn.la 
    libcrtnn_la_SOURCES = network.cpp neuron.cpp 
    
    e src/Makefile.am come segue:
     
    bin_PROGRAMS = foo 
    foo_SOURCES = main.c 
    foo_LDADD = crtnn/libcrtnn.la 
    SUBDIRS = crtnn 
    
    Qual è la differenza? potresti chiedere, quasi nessuno. Un vantaggio dell'utilizzo delle librerie di convenienza di Libtool è che possono essere annidate: una libreria Libtool può includere un'altra libreria Libtool (ciò è utile quando si ha una gerarchia profonda del codice sorgente e si costruisce una libreria ad ogni livello). Anche le librerie di convenienza di Libtool possono essere utilizzate per costruire una libreria condivisa, se lo si desidera. Le librerie statiche di Automake non possono.

+1

Grazie! Ho finito per usare il metodo libtool, funziona perfettamente :-) –

+2

Grazie per avermi aiutato a sforzarmi nell'inferno autotools/libtool. E facciamo un favore a tutti noi: vivete a lungo e prosperate! – rockdaboot

+0

foo_LDADD? Non dovrebbe essere foo_LIBADD –

2

Si potrebbe semplicemente specificare i file di origine nel progetto/src/Makefile.am e non hanno un Makefile.am in ctrnn:

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

oppure è possibile utilizzare una libreria libtool convenienza. In ctrnn/Makefile.am, messo:

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

e in src/Makefile.am, messo

 
LDADD = ctrnn/libmylib.la 

Se non si utilizza già libtool, avrete anche bisogno di aggiungere LT_INIT a configure.ac.

0

Meglio ancora, si potrebbe forzare un make utilizzando un target fonte-di meno in questo modo:

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 \ 
... 

Il sugo segreto è nodist_EXTRA_xxxx_la_SOURCES.

Ulteriori dettagli qui: https://www.gnu.org/software/automake/manual/html_node/Libtool-Convenience-Libraries.html

Problemi correlati