2009-06-20 9 views
10

Sto lavorando a un progetto C++ su GNU/Linux e sto cercando un modo per testare l'esistenza e l'usabilità della libreria IBM Informix con gli Autotools, ovvero la modifica di configure.in. Non ho esperienza con Autotools, quindi in pratica sto prendendo spunto dal progetto configure.ine altri. script e copia & cambiare dove ritengo debba essere modificato. IOW, mi sono adattato dal testo esistente in configure.in.Come testare l'usabilità di una libreria C++ in configure.in?

Finora ho utilizzato con successo il AC_CHECK_LIB in configure.in per verificare se esiste una certa libreria ed è utilizzabile. Ma sembra funzionare solo con le librerie con le funzioni , non ad es. classi. Vale a dire, questo non riesce quando il test libifc++.so biblioteca di Informix:

AC_CHECK_LIB(ifc++, ITString, 
     INFORMIX_LIB="-L$INFORMIX_LIB_LOCATION/c++ -lifc++ -L$INFORMIX_LIB_LOCATION -L$INFORMIX_LIB_LOCATION/dmi -L$INFORMIX_LIB_LOCATION/esql -lifdmi -lifsql -lifasf -lifgen -lifos -lifgls -lifglx $INFORMIX_LIB_LOCATION/esql/checkapi.o -lm -ldl -lcrypt -lnsl", 
     echo "* WARNING: libifc++.so not found!" 
     INFORMIX_INC="" 
     INFORMIX_LIB="" 
) 

Ho anche provato ad utilizzare altre combinazioni, come ITString::ITString, ecc

non ho trovato una funzione di "puro" in API di Informix (vale a dire , uno che non è conteso in una classe C++). Quindi spero che o ci sia un modo di usare AC_CHECK_LIB in questo contesto, o c'è un altro /configure.in "comando" per questo uso specifico.

Grazie in anticipo per il vostro feedback.

risposta

5

Potrebbe esserci un modo più semplice per raggiungere questo obiettivo, ma penso che il problema sia che i metodi C++ vengono "storpiati" per consentire ulteriori informazioni sul metodo (argomento & tipi di reso ecc.) Da codificare. Per esempio; il metodo int A::foo(void) verrà manomesso a qualcosa come __ZN1A3fooEv.

Quindi è necessario trovare il nome storpiato di un metodo nella libreria. È possibile farlo utilizzando il nm command su Unix-like sistemi operativi:

$ nm libifc++.so | grep ITString 

Vale la pena ricordare che il formato esatto mutilazione varia a seconda dei diversi compilatori; e quindi incorporando il simbolo di un certo simbolo del compilatore nel tuo configure.in potrebbe non funzionare su altre piattaforme - YMMV.

Nota: è possibile utilizzare l'utilità c++filt per reindirizzare un nome in forma leggibile dall'utente; così per l'esempio che ho dato in precedenza:

$ c++filt __ZN1A3fooEv 
A::foo() 

Vedi Name Mangling in C++ su Wikipedia per ulteriori informazioni.

+0

Works-for-me. Avevo pensato di fare qualcosa del genere, ma sembrava un trucco. Ad esempio, non sono sicuro di cosa succederebbe se il codice venisse ricompilato con una versione diversa della libreria Informix (mi aspetto che cambi il nome mutilato). Ma hey, funziona! :-) – jbatista

+2

Questo dovrebbe continuare a funzionare con una nuova versione di libreria (supponendo che i nomi di classe e metodo non cambino), ma potrebbe interrompersi se la versione del compilatore cambia e quasi sicuramente si interromperà se qualcun altro tenta di compilare il codice su un altro compilatore o versione del compilatore. –

+0

@Tyler: un punto valido; L'ho evidenziato nella risposta. – DaveR

13

Hai scoperto una mancanza di autotools, ma non puoi davvero essere aiutato. Gli autotools controllano i nomi dei simboli nel binario della libreria, e diversamente da C, dove i nomi dei simboli delle funzioni sono identici ai nomi delle funzioni, i nomi dei simboli della funzione "maneggia" del C++ portano a termine cose come l'overloading delle funzioni. Quel che è peggio è che C++ non ha nemmeno una convenzione di "mangling" standard, quindi diversi compilatori C++ possono produrre nomi di simboli diversi per la stessa funzione. Pertanto, gli autotools non possono controllare i nomi dei simboli C++ in modo affidabile.

La libreria che si sta tentando di utilizzare ha funzioni dichiarate con extern "C"? Questo fa sì che il compilatore C++ generi nomi di simboli in stile C standardizzati, e gli autotools saranno in grado di trovarli.

mi sono imbattuto in questo problema cercando di rilevare gtest e gmock (l'unità di test di Google e oggetto quadri beffardo) con Autotools, ed ecco cosa mi si avvicinò con:

# gtest has a main function in the gtest_main library with C linkage, we can test for that. 
AC_CHECK_LIB([gtest_main], [main], [HAVE_GTEST=1] [TEST_LIBS="$TEST_LIBS -lgtest_main"], 
     AC_MSG_WARN([libgtest (Google C++ Unit Testing Framework) is not installed. Will not be able to make check.])) 

# gmock has no functions with C linkage, so this is a roundabout way of testing for it. We create a small test 
# program that tries to instantiate one of gmock's objects, and try to link it with -lgmock and see if it works. 
if test "$HAVE_GTEST"                 
then                     
    saved_ldflags="${LDFLAGS}"               
    LDFLAGS="${LDFLAGS} -lgtest -lgmock"             
    AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <gmock/gmock.h>], [testing::Cardinality dummy])], 
    [TEST_LIBS="$TEST_LIBS -lgmock"] [HAVE_GMOCK=1],           
    [AC_MSG_WARN([libgmock (Google C++ Object Mocking Framework) is not installed. Will not be able to make check.])]) 
    LDFLAGS="${saved_ldflags}"                       
fi   
2

Se la libreria che si sta verificando per supporta pkg-config, questo diventa molto facile. Ecco tutto quello che ho aggiunto alla mia configure.in per verificare e attivare gtest e gmock:

dnl ************************************ 
dnl Check for googletest and googlemock 
dnl ************************************ 

PKG_CHECK_MODULES(gtestmock, libgtest >= 0.4.0, libgmock >= 0.4.0) 
AC_SUBST(gtestmock_LIBS) 
AC_SUBST(gtestmock_CFLAGS) 

E poi nel mio Makefile.am da qualche parte:

sometarget_CXXFLAGS = $(gtestmock_CFLAGS) $(AM_CXXFLAGS) 
sometarget_LDADD = $(gtestmock_LIBS) 

piuttosto banale, eh?

+0

[Ci sono problemi] (http://stackoverflow.com/questions/10220946/pkg-check-modules-considered-harmful/10229811#10229811) con l'uso di pkg-config, comunque. E, più fondamentalmente, pkg-config e gli autotools funzionano in un modo diverso. Autoconf controlla le caratteristiche, mentre pkg-config verifica le versioni dei pacchetti. Se stai provando a fare cose in modo autotools, che dovrebbe darti la massima compatibilità tra i sistemi, non suggerirei affatto di usare pkg-config. – edam