IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Systèmes de compilation Discussion :

[CMake]Problème de link avec un executable


Sujet :

Systèmes de compilation

  1. #1
    Nouveau membre du Club
    Inscrit en
    Mars 2010
    Messages
    57
    Détails du profil
    Informations forums :
    Inscription : Mars 2010
    Messages : 57
    Points : 38
    Points
    38
    Par défaut [CMake]Problème de link avec un executable
    Bonjour à tous,

    je suis un peu nouveau sur l'utilisation de CMake, donc ne m'en veuillez pas si j'ai l'air de dire des bêtises.

    Je vous présente mon problème, je travaille sur un projet qui doit compiler sur Windows et sur Linux. Pour la partie Linux, il a été décidé d'utiliser CMake pour compiler le projet. Voici l'arborescence du projet:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    Manager/
         |___ Bin
         |___ Includes
                  |___ lib1
                         |___ lib1.h
                  |___ lib2
                         |___ lib2.h
                  |___ Manager
                         |___ manager.h
         |___ Src
                  |___ lib1
                         |___ lib1.cpp
                         |___ CMakeList.txt (2)
                  |___ lib2
                         |___ lib2.cpp
                         |___ CMakeList.txt (3)
                  |___ Manager
                         |___ Manager.cpp
                         |___ CMakeList.txt (4)
         |___ Project
         |___ CMakeList.txt (1)
    Voici les fichiers CMakeList que j'utilise:
    (1)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # Set the cmake version
    cmake_minimum_required(VERSION 2.6)
     
    set(BUILD_SHARED_LIBS ON)
    set(BUILD_PATH "Bin/${CMAKE_BUILD_TYPE}/")
    MESSAGE( "General build path ${BUILD_PATH}" )
     
    # Set the list of directory which contain the other CMakeList
    add_subdirectory(Src/lib1)
    add_subdirectory(Src/lib2)
    add_subdirectory(Src/Manager)

    (2)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    # Set the cmake version
    cmake_minimum_required(VERSION 2.6)
     
    # Set the project name
    project(lib1)
     
    # Configure project
    set(BUILD_SHARED_LIBS ON)
    set(BUILD_PATH "${CMAKE_BUILD_TYPE}/")
     
    #Display Build path
    set(LIBRARY_OUTPUT_PATH ../../Bin/${BUILD_PATH})
     
    #Include .h files directory
    include_directories(../../Includes/lib1)
     
    #Define librarie
    add_library(
    	lib1
    	SHARED
           ../../Includes/lib1/lib1.h
          lib1.cpp
    )
     
    set_target_properties(lib1 PROPERTIES PREFIX "")
    (3)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
    # Set the cmake version
    cmake_minimum_required(VERSION 2.6)
     
    # Set the project name
    project(lib2)
     
    # Configure project
    set(BUILD_SHARED_LIBS ON)
    set(BUILD_PATH "${CMAKE_BUILD_TYPE}/")
     
    #Display Build path
    set(LIBRARY_OUTPUT_PATH ../../Bin/${BUILD_PATH})
     
    #Include .h files directory
    include_directories(../../Includes/lib1 ../../Includes/lib2)
    link_directories(../../Bin/${BUILD_PATH})
     
    #Define librarie
    add_library(
    	lib2
    	SHARED
           ../../Includes/lib2/lib2.h
          lib2.cpp
    )
     
    target_link_libraries(
    	lib2
    	lib1
    )
     
    set_target_properties(lib2 PROPERTIES PREFIX "")
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
     
    # Set the cmake version
    cmake_minimum_required(VERSION 2.6)
     
    # Set the project name
    project(Manager)
     
    # Configure project
    set(BUILD_SHARED_LIBS ON)
    set(BUILD_PATH "${CMAKE_BUILD_TYPE}/")
    set(EXECUTABLE_OUTPUT_PATH ../../Bin/${BUILD_PATH})
     
    #Include .h files directory
    include_directories(../../Includes/lib1
    ../../Includes/lib2
    ../../Includes/Manager)
     
    #Define link libraries folder
    link_directories(../../Bin/${BUILD_PATH})
     
    add_executable(
    	Manager
    	../../Includes/Manager/Manager.h
    	Manager.cpp
    )
     
    target_link_libraries(
    	Manager
    	lib1
    	lib2
    	pthread
    )
     
    set_target_properties(Manager PROPERTIES PREFIX "")
    Sachant que la librairie lib1 utilise lib2 et que le Manager utilise lib1 et lib2 (plus des threads).

    Ma première question est la suivante: est ce que mes CMakeList sont juste?
    Ensuite, pourquoi, lorsque j'essaie de fournir les fichiers lib1.so, lib2.so et Manager, ceux-ci ne fonctionnent pas sur un autre poste?

    Le problème semble venir du fait que les chemins de link sont en dur dans l’exécutable et je ne vois pas du tout comment corriger cela

    Merci beaucoup de l'aide que vous pourrez m'apporter

    Bonne journée

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    865
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 865
    Points : 1 069
    Points
    1 069
    Par défaut
    Je commencerai par répondre à la seconde question car l'essentiel du problème est ici.

    Citation Envoyé par Anthares Voir le message
    Ensuite, pourquoi, lorsque j'essaie de fournir les fichiers lib1.so, lib2.so et Manager, ceux-ci ne fonctionnent pas sur un autre poste?
    C'est une erreur assez classique, probablement héritée du monde Windows. La génération d'un produit se fait généralement en trois étapes : configuration, compilation puis installation. La dernière étape est souvent omise dans le monde Windows, du moins Visual. Il ne faut pas confondre placer les produits de compilation dans un répertoire (via les variables LIBRARY_OUTPUT_PATH et EXECUTABLE_OUTPUT_PATH) et les installer.

    Ton erreur est due au fait que les librairies sont gérées de manière légèrement différentes suivant qu'elles sont utilisées dans l'environnement de développement (ton répertoire de compilation) et l'environnement d'utilisation (l'autre poste). Dans l'environnement de développement, pour éviter des erreurs de librairies non trouvées, CMake utilise le RPATH pour lier en dur les librairies entre elles. C'est particulièrement pratique pour exécuter des tests automatiquement. Par contre, dans l'environnement d'utilisation, qui ne ressemble pas du tout à l'environnement de développement, il faut enlever les références en dur, ce que CMake fait à l'installation, et les remplacer par une configuration système ou utilisateur (ce que l'on fait avec LD_LIBRARY_PATH, PATH ou des mécanismes systèmes plus compliqués).

    Malheureusement, dans le monde Windows, il n'existe aucun mécanisme pour référencer en dur le chemin vers une librairie. Le seul moyen de pouvoir exécuter des tests automatiquement est donc de tout mettre au même endroit, d'où la raison principale de l'existence des variables EXECUTABLE_OUTPUT_PATH et LIBRARY_OUTPUT_PATH.

    Par conséquent, si tu veux pouvoir utiliser tes librairies sur un autre poste, il faut que tu les installes. Ceci se fait avec la commande
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    install(TARGETS ... DESTINATION...)
    Ensuite, après avoir configuré l'endroit où installer ses produits
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cmake -D CMAKE_INSTALL_PREFIX=<InstallDir> .
    puis compilé
    , il faut installer les produits
    Tu trouveras alors dans <InstallDir> tes librairies parfaitement utilisables sur tout autre poste.

    Il est aussi possible de packager ses binaires en incluant CPack et en faisant make package. On peut ainsi construire une archive auto-extractible. Attention, faire un package nécessite toujours de spécifier les règles d'installation.

    Citation Envoyé par Anthares Voir le message
    Ma première question est la suivante: est ce que mes CMakeList sont juste?
    Quelques commentaires pour le reste:
    • A part compliqué inutilement le projet, je ne vois aucun intérêt à faire un projet par target. Le mieux est de faire un projet à la racine (avec le cmake_minimum_required), y fixer les variables globales (elles sont héritées par les CMakeLists en-dessous) puis ajouter les différents sous-répertoires. Inutile donc de répéter les set BUILD_SHARED_LIBS BUILD_PATH LIBRARY_OUTPUT_PATH EXECUTABLE_OUTPUT_PATH
    • Sauf exception, on ne liste pas les .h dans les sources. La seule raison de les lister est de pouvoir les voir directement dans certains IDE.
    • Sauf exception, on laisse le préfixe par défaut. CMake positionne un préfixe en cohérence avec la plateforme de développement (lib sous Linux, rien sous Windows). Dans ton cas, il suffirait de faire add_library(1 ...) sans changer le préfixe. Au passage, "1" ne me paraît pas être un super nom pour une librairie. Tu me diras, oui, mais il y a lib devant sauf que si je veux compiler avec à la main, je suis obligé de faire gcc ... -l1 ... Pas super clair...
    • Je ne vois pas l'intérêt de faire link_directories.
    • Inutile de linker Manager contre lib1 puisque lib2 linke contre lib1 (sauf si tu utilises directement lib1 dans Manager, et encore ceci ne serait pas nécessaire si tu travaillais en statique). De même, si lib1 ou lib2 utilise pthread, il faut le dire aussitôt. CMake assure la transitivité des librairies, ce qui change un peu des Makefiles faits à la main où on linke généralement tout ensemble au dernier moment. Il ne faut pas hésiter à utiliser la transitivité et à ne lister que les librairies que tu utilises réellement pour la target en cours de construction.

Discussions similaires

  1. Problème de link avec glut et CMake
    Par Ange44 dans le forum C++
    Réponses: 7
    Dernier message: 24/09/2008, 15h33
  2. problème de link avec visual C++ 2005
    Par superC dans le forum OpenGL
    Réponses: 2
    Dernier message: 27/02/2007, 10h35
  3. [Code::Blocks] problème de link avec DevIL
    Par theidiot dans le forum DevIL
    Réponses: 4
    Dernier message: 01/10/2006, 18h26
  4. problème ajout données avec db.execute et access
    Par Dauphind dans le forum Access
    Réponses: 2
    Dernier message: 29/11/2005, 12h03
  5. Problème de link avec Borland C++ 5.5
    Par gelam dans le forum Autres éditeurs
    Réponses: 5
    Dernier message: 24/11/2003, 16h45

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo