cmake: try_compile gibt falsches Resultat



  • Hi.

    Wir testen in unserem Projekt das Vorhandensein bestimmter Bibliotheken indirekt mit einem try_compile von cmake. Wenn die Bibliothek nicht gefunden wird, dann sagen wir cmake, dass es selbst mal nach der Bibliothek suchen soll und machen das dann noch mal.

    Das funktioniert auch ganz gut. Jetzt ist es allerdings auf einem System so, dass try_compile im ersten Schritt sagt, dass das Kompilieren geklappt hat, das hat es aber gar nicht. Entsprechend sagen wir cmake dort nicht, dass es mal selbst nach einer entsprechenden Bibliothek suchen soll und letztendlich gibt es ein Problem beim Linken des echten Projekts.

    Kennt sich jemand mit cmake aus und hat eine Idee, was hier das Problem sein koennte? Ist das vielleicht ein bekannter Fehler in cmake?



  • Gregor schrieb:

    Kennt sich jemand mit cmake aus und hat eine Idee, was hier das Problem sein koennte? Ist das vielleicht ein bekannter Fehler in cmake?

    CMake sollte eigentlich irgendwo die exakte Kommandozeile des try_compile loggen. Schau mal in das Verzeichnis mit den ganzen Dateien die CMake während der Konfigurationsphase erstellt.
    Diesen Befehl würde ich mir dann mal genauer unter die Lupe nehmen (manuell in der Konsole ausführen), und schauen, weshalb der offenbar 0 zurückgibt - soweit ich weiss machen solche Tests
    Erfolg und Fehlschlag an dem Fehlercode fest, den der Compiler zurückgibt. Auch würde ich prüfen, ob der Test auch versucht das Programm zu linken und es nicht nur kompiliert. Wenn z.B. nur die
    Header einer Bibliothek gefunden werden, könnte das dann z.B. den von dir beschriebenen Effekt haben.



  • Also auf beiden Systemen wird ein Makefile generiert. In diesem Makefile tritt der Fehler auf.

    Hier mal der make Output (zusammengeschnitten) fuer den Test, der (wie er soll) fehlschlaegt:

    /usr/local/.../mpiifort        -mkl -r8 -openmp  CMakeFiles/cmTC_de0e6.dir/test_XML.f90.o  -o cmTC_de0e6  -lmkl_scalapack_lp64 -lmkl_blacs_intelmpi_lp64
    CMakeFiles/cmTC_de0e6.dir/test_XML.f90.o: In function `MAIN__':
    /usr/.../test_XML.f90:(.text+0x43): undefined reference to `xmlInitParser'
    make[2]: *** [cmTC_de0e6] Error 1
    make[2]: Leaving directory `/usr/.../build/CMakeFiles/CMakeTmp'
    make[1]: *** [CMakeFiles/cmTC_de0e6.dir/all] Error 2
    make[1]: Leaving directory `/usr/.../build/CMakeFiles/CMakeTmp'
    make: *** [all] Error 2
    m...:CMakeTmp% echo $?
    2
    m...:CMakeTmp% make --version
    GNU Make 3.81
    Copyright (C) 2006  Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.
    There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
    PARTICULAR PURPOSE.
    
    This program built for x86_64-redhat-linux-gnu
    

    Hier jetzt der make Output fuer den Fall, der faelschlicherweise ohne Fehler abgeschlossen wird:

    /usr/local/.../mpiifort        -mkl -r8 -qopenmp  CMakeFiles/cmTC_11dc8.dir/test_XML.f90.o  -o cmTC_11dc8  -lmkl_scalapack_lp64 -lmkl_blacs_intelmpi_lp64
    CMakeFiles/cmTC_11dc8.dir/test_XML.f90.o: In function `MAIN__':
    /usr/.../test_XML.f90:(.text+0x43): undefined reference to `xmlInitParser'
    make[2]: Leaving directory `/usr/.../build.3543/CMakeFiles/CMakeTmp'
    [100%] Built target cmTC_11dc8
    make[1]: Leaving directory `/usr/.../build.3543/CMakeFiles/CMakeTmp'
    /tmp_mnt/el6/bin/cmake -E cmake_progress_start /usr/.../build/CMakeFiles/CMakeTmp/CMakeFiles 0
    m...:CMakeTmp% echo $?
    0
    m...:CMakeTmp% make --version
    GNU Make 3.81
    Copyright (C) 2006  Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.
    There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
    PARTICULAR PURPOSE.
    
    This program built for x86_64-redhat-linux-gnu
    

    Ich habe einige Pfade und den Prompt durch ... abgekuerzt. Einige Dateien haben temporaere Namen, so dass sie nicht in beiden Faellen gleich sind. Es kommen in den beiden Faellen _unterschiedliche_ mpiifort Compiler zum Einsatz.

    Der eigentliche Punkt ist aber wohl, dass make im zweiten Fall behauptet:

    [100%] Built target cmTC_11dc8
    

    Die Datei wurde natuerlich nicht erstellt. Entsprechend hoert make da ohne Fehlercode auf, im ersten Fall aber schon. Es ist also anscheinend keine cmake Sache, sondern ein make Problem. ...oder vielleicht ein Problem das an den unterschiedlichen mpiifort Compilern haengt. Denn die make-Versionen scheinen ja identisch zu sein.

    Die Frage bleibt aber bestehen: Hat schon mal jemand etwas aehnliches gesehen und hat eine Idee, was hier Sache ist?



  • Mpiifort Versionen, die hier genutzt werden:

    Erster Fall (richtiges Verhalten):

    m...:CMakeTmp% /usr/.../mpiifort --version
    ifort (IFORT) 12.1.3 20120212
    Copyright (C) 1985-2012 Intel Corporation.  All rights reserved.
    

    Zweiter Fall (falsches Verhalten):

    m...:CMakeTmp% /usr/.../mpiifort --version
    ifort (IFORT) 15.0.1 20141023
    Copyright (C) 1985-2014 Intel Corporation.  All rights reserved.
    

    EDIT: Ja, ein einfacher Aufruf des jeweiligen Compilers fuehrt auch schon zu dem Problem: Im zweiten Fall ist trotz Fehler der Return Code 0.



  • Gregor schrieb:

    EDIT: Ja, ein einfacher Aufruf des jeweiligen Compilers fuehrt auch schon zu dem Problem: Im zweiten Fall ist trotz Fehler der Return Code 0.

    Das sieht mir aber stark nach einem Compiler-Bug aus. Ich sehe nicht wie man einen Compiler, der sich so verhält, sinnvoll in igrendwelche Skripte integrieren kann, zumal ein "Target" nicht immer eine Datei erzeugen muss.
    So wie ich das sehe bleibt dir wahrscheinlich vorerst wohl nur in CMake einen Workaround zu bauen, der auf die Datei prüft (wobei man wenn man Pech hat auch noch hoffen muss, dass der Compiler nicht irgendeine
    Mülldatei erstellt hat, weil er auf irgendeinen Fehler gelaufen ist). Mir ist das jedenfalls noch nicht untergekommen dass ein Compiler einen Fehler geworfen, und dann 0 zurückgegeben hätte, und ich habe schon viele Skripte
    geschrieben, die sich darauf verlassen - das dürften auch so ziemlich alle Build-Systeme tun. Workaround und Problem an Intel melden, mehr fällt mir dazu leider nicht ein.



  • Eigentlich scheint das Problem ja beim Linken aufzutreten, es ist also vielleicht ein Linker-Problem. Ich muss leider sagen, dass ich mich da nicht gut auskenne. Ist der Linker eigentlich ein extra Programm, das von dem Compiler aufgerufen wird? Wenn ja, wie finde ich heraus, welcher Linker verwendet wird? Oder ist das alles in den Compiler integriert?



  • Gregor schrieb:

    Eigentlich scheint das Problem ja beim Linken aufzutreten, es ist also vielleicht ein Linker-Problem. Ich muss leider sagen, dass ich mich da nicht gut auskenne. Ist der Linker eigentlich ein extra Programm, das von dem Compiler aufgerufen wird? Wenn ja, wie finde ich heraus, welcher Linker verwendet wird? Oder ist das alles in den Compiler integriert?

    Linker sind zwar meistens separate Programme, werden aber oft automatisch vom Compiler aufgerufen. Zumindest ist das bei GCC und Clang so - da kann man dem Compiler auch gleich die Linker-Flags mit übergeben. Leider kenne ich mich mit Intels Fortan-Compiler überhaupt nicht aus, aber wie es scheint unterstützt der, wie auch GCC und Clang die Option -Wl,<linker-flags> , mit der man Parameter an den Linker weiterreichen kann:

    -Wl,<o1>[,<o2>,...]
    	      Passes options <o1>, <o2>, and  so  forth,  to  the
    	      linker  for  processing.	 If  the  linker  is  not
    	      invoked, these options are ignored.
    

    Wenn man dem Compiler jetzt -Wl,-v mit übergibt, sollte das eigentlich den Linker auffordern etwas gesprächiger zu sein (-v: verbose). Zumindest bei einer GCC/GNU ld Compiler/Linker-Kombination kann ich so herausfinden dass der Linker "GNU ld" verwendet wird, und wie die Linker-Kommandozeile aussieht. Hoffe das hilft weiter. Wäre jedenfalls tatsächlich gut zu wissen, ob der Linker schon die 0 zurückgibt, oder ob der Compiler den Fehlercode falsch weiterreicht.

    Ansonsten verwenden zumindest GCC und Clang entweder einen explizit in der Kommandozeile angegebenen Linker, den Linker der in der Umgebungsvariable LD angegeben ist, ein hartcodiertes Programm (meistens ld ) welches sich im gleichen Verzeichnis wie der Compiler befindet, oder über den PATH erreichbar ist (ich denke auch in der Reihenfolge).



  • Wir haben das Problem jetzt umgangen, indem fuer die betroffene Maschine das Testskript etwas anders aufgerufen wird. Wir haben jetzt per Hand die richtigen Bibliotheken verlinkt und lassen die nicht mehr durch das Skript ermitteln.

    EDIT: Die Linker sind natuerlich unterschiedlich. Bei der funktionierenden Variante ist es

    GNU ld version 2.17.50.0.6-26.el5 20061020

    Bei der Variante, die zum fehlerhaften Verhalten fuehrt ist es

    GNU ld version 2.20.51.0.2-5.36.el6 20100205

    Leider scheint es nicht so ganz trivial zu sein, ld genau so aufzurufen, wie es der Compiler intern macht. Ich kriege da immer mehr Fehlermeldungen neben der oben angegebenen. Der Rueckgabewert ist immer 1.



  • Dieser Thread wurde von Moderator/in nachtfeuer aus dem Forum Rund um die Programmierung in das Forum Compiler- und IDE-Forum verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.


Anmelden zum Antworten