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

 C++ Discussion :

cmake, cmakelist & target_link_libraries


Sujet :

C++

  1. #1
    Membre confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    120
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2003
    Messages : 120
    Billets dans le blog
    1
    Par défaut cmake, cmakelist & target_link_libraries
    Bonsoir !

    J'utilise cmake et son cmakelist pour compiler un projet lié à deux lib comme ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    target_link_libraries(cpp-sandbox azdev pthread)
    dans un cmakelist qu'est-ce qui défini la façon dont le lien se fait, est-ce que je lie en incluant dans le binaire les librairie ou est-ce que je lie en laissant les lib en "externe" ?

  2. #2
    Membre confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    120
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2003
    Messages : 120
    Billets dans le blog
    1
    Par défaut
    serait-ce la directive

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    add_library(<name> [STATIC | SHARED | MODULE]
                [EXCLUDE_FROM_ALL]
                source1 [source2 ...])
    avec au choix SHARED ou STATIC ???

  3. #3
    Membre confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    120
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2003
    Messages : 120
    Billets dans le blog
    1
    Par défaut
    Tout comme pour la commande add_executable(), le premier paramètre est le nom de la bibliothèque et le dernier la liste des fichiers sources. Le second paramètre, optionnel, indique le type de bibliothèque à générer :

    STATIC, pour générer une bibliothèque à lier statiquement ;
    SHARED, pour générer une bibliothèque à lier dynamiquement.
    source : https://florian-goujeon.developpez.c...ke/initiation/


    donc si je comprends bien, si j'ai une bibliothèque perso à lier que je mets à jour il vaut mieux utiliser SHARED et si je veux livrer un binaire 'all inclusive' je choisi STATIC ?

    ou plus simplement si je veux créer une lib disponible pour plusieurs projet je choisi SHARED ?!

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 152
    Billets dans le blog
    4
    Par défaut
    static lie un .lib et intègre le code à l'exécutable
    shared est utilisé pour les dll
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  5. #5
    Membre confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    120
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2003
    Messages : 120
    Billets dans le blog
    1
    Par défaut
    merci Bousk

  6. #6
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    En fait, si tu ne spécifies pas "SHARED" ou "STATIC", c'est la variable "BUILD_SHARED_LIBS" qui tranche. Cette variable est OFF par défaut.

  7. #7
    Membre confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    120
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2003
    Messages : 120
    Billets dans le blog
    1
    Par défaut
    merci ternel

    je me pose une autre question, lorsque je recompile ma library mais que mon application n'est pas modifiée, comment forcer mon application à prendre en compte cette nouvelle version ? pour l'instant je supprime le dossier de build et je recompile mon application... est-ce qu'il y a plus rapide ?

  8. #8
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Ca dépend.
    Comment fais-tu pour construire la bibliothèque seule? Et juste le programme?

  9. #9
    Membre confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    120
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2003
    Messages : 120
    Billets dans le blog
    1
    Par défaut
    pour la librairie : (l'essentiel)

    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
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
     
    # Nous voulons un cmake "récent" pour utiliser les dernières fonctionnalités
    cmake_minimum_required(VERSION 3.12.1)
     
    # Notre projet est étiqueté 'oops'
    project(oops VERSION 0.0.18.47)
     
    # https://www.developpez.net/forums/d1915192/c-cpp/cpp/cmake-boost-no-debug-option/
    set(CMAKE_CXX_STANDARD 17)
     
    configure_file(${CMAKE_CURRENT_SOURCE_DIR}/include/oops/version.hpp.in ${CMAKE_CURRENT_SOURCE_DIR}/include/oops/version.hpp)
     
    set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "../lib")
    set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "../bin")
    # set(LIBRARY_OUTPUT_DIRECTORY "lib")
    # set(RUNTIME_OUTPUT_DIRECTORY "bin")
     
    set(
      MY_DEBUG_OPTIONS "-Werror;@../gcc-7.1-warnings;@../gcc-debug"
    )
     
    set(
      MY_RELEASE_OPTIONS "-Werror;@../gcc-7.1-warnings"
    )
     
    #===============================================================================
    #oops-hpp
    #===============================================================================
    file(
      GLOB
      hpp_files
      include/oops/*.hpp
    )
    install (FILES ${hpp_files} DESTINATION "include/oops")
     
    #===============================================================================
    #oops-dev
    #===============================================================================
    # GLOB_RECURSE pour récupérer les fichiers de façon récursive
    file(
      GLOB_RECURSE
      dev_cpp_files
      src/oops/dev/*.cpp
    )
     
    file(
      GLOB_RECURSE
      dev_hpp_files
      include/oops/dev/*.hpp
    )
     
    add_library(
      oops-dev
      SHARED
      ${dev_cpp_files}
    )
     
    target_include_directories(oops-dev PRIVATE "include")
     
    target_compile_options(oops-dev PUBLIC "$<$<CONFIG:DEBUG>:${MY_DEBUG_OPTIONS}>")
    target_compile_options(oops-dev PUBLIC "$<$<CONFIG:RELEASE>:${MY_RELEASE_OPTIONS}>")
     
    target_link_libraries(oops-dev pthread)
     
    # 2018-1027 : When compiling in Debug mode, this will define the DEBUG symbol for use in your code
    target_compile_definitions(oops-dev PUBLIC "$<$<CONFIG:DEBUG>:DEBUG>")
     
    message("CMAKE_CXX_FLAGS_DEBUG is ${CMAKE_CXX_FLAGS_DEBUG}")
    message("CMAKE_CXX_FLAGS_RELEASE is ${CMAKE_CXX_FLAGS_RELEASE}")
     
    install (TARGETS oops-dev DESTINATION "lib")
    install (FILES ${dev_hpp_files} DESTINATION "include/oops/dev")
    pour le programme :

    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
    35
    36
    37
    38
    39
    40
    41
    42
    # GLOB_RECURSE pour récupérer les fichiers de façon récursive
    file(
      GLOB_RECURSE
      source_files
      src/*.cpp
    )
     
    file(
      GLOB_RECURSE
      include_files
      src/*.hpp
    )
     
    message("CMAKE_BUILD_TYPE is ${CMAKE_BUILD_TYPE}")
     
    add_executable(
      cpp-sandbox
      ${source_files}
    )
     
    set(
      MY_DEBUG_OPTIONS "-Werror;@../gcc-7.1-warnings;@../gcc-debug"
    )
     
    set(
      MY_RELEASE_OPTIONS "-Werror;@../gcc-7.1-warnings"
    )
     
    target_include_directories(cpp-sandbox PRIVATE "include")
     
    target_compile_options(cpp-sandbox PUBLIC "$<$<CONFIG:DEBUG>:${MY_DEBUG_OPTIONS}>")
    target_compile_options(cpp-sandbox PUBLIC "$<$<CONFIG:RELEASE>:${MY_RELEASE_OPTIONS}>")
     
    # When compiling in Debug mode, this will define the DEBUG symbol for use in your code 2018-1112
    target_compile_definitions(cpp-sandbox PUBLIC "$<$<CONFIG:DEBUG>:DEBUG>")
     
    target_link_libraries(cpp-sandbox oops-dev oops-gui pthread sfml-graphics sfml-window sfml-system)
     
    install (TARGETS cpp-sandbox DESTINATION "bin")
     
    message("CMAKE_CXX_FLAGS_DEBUG is ${CMAKE_CXX_FLAGS_DEBUG}")
    message("CMAKE_CXX_FLAGS_RELEASE is ${CMAKE_CXX_FLAGS_RELEASE}")

  10. #10
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Il y a quelques aspects dans ton CMakelists.txt, qui fonctionnent mais qui sont considérés comme de véritables horreurs;

    Certaines ne sont qu’anecdotiques (ou presque), et ne vont poser des problèmes "qu'aux autres", ces pauvres malheureux qui utilisent VC++, comme le fait de fournir de manière inconditionnelles des options de compilation spécifiques à un compilateur particulier.

    D'autres seront plus embêtantes dans un contexte de génération "out of the tree" (ailleurs que dans le dossier des sources) comme tes instructions set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "../lib") et set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "../bin")

    Mais certaines vont carrément t'obliger à "plus de travail" lors de l'ajout d'éléments à ton projet, comme l'utilisation de GLOB_RECURSE. Et ca, c'est vraiment pas cool

    En effet, GLOB_RECURSE n'est évalué que ... quand CMake (ou CMake-gui) est exécuté. Si bien que, si tu en viens (et tu en viendras forcément) à un moment ou à un autre à décider de rajouter un fichier (et même souvent, tu voudras en rajouter deux : un fichier d'en-tête et un fichier d'implémentation), tu te retrouves face à l'obligation de ... relancer CMake pour que ce(s) nouveau(x) fichier(s) soie(nt) pris en compte.

    C'est moche parce que, a priori, il ne faut lancer CMake (ou CMake-gui) que pour avoir la "configuration de base", qui se limite à
    1. s'assurer des capacités du compilateur
    2. s'assurer de la présence des bibliothèques tierces dont on a besoin
    3. définir les options de compilation "qui vont bien"
    4. (éventuellement) permettre de choisir d'activer (ou non) des fonctionnalités "optionnelles".


    Et le tout en sachant cmake est fait de telle sorte que l'ajout de nouveau(x) fichier à la liste puisse occasionner la "mise à jour automatique".

    Pire encore, si j'ai bien compris (mais bon, je peux me tromper), tu te trouves face à une arborescence proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    <root_dir>    // le dossier parent de ton projet
    |-> src       // contient les fichiers de ton PROGRAMME
    |    |-> dev  // contient les fichiers de ta bibliothèque
    C'est une organisation qui en vaut une autre, et je n'ai absolument aucune raison de vouloir t'en imposer une différente.

    Mais le fait est que, tu le met toi-même en commentaire, GLOB_RECURSE permet de récupérer les fichiers de façon récursive

    Cela signifie que GLOB_RECURSE va récupérer tous les fichier qui se trouvent dans src/dev lorsqu'il sera question de créer la bibliothèque (ce qui correspond à ce que l'on veut), mais surtout qu'il va récupérer non seulement les fichiers qui se trouvent dans src, mais aussi ceux qui se trouvent dans src/dev lorsqu'il sera question de créer le programme.

    Et ca, c'est vraiment pas la chose à faire:
    1. parce que tu te retrouve à compiler deux fois les sources de la bibliothèque
    2. parce que tu pourrait tout aussi bien en arriver à ne même pas compiler la bibliothèque pour créer le programme.

    La situation "idéale" devant te permettre
    1. faire en sorte que la compilation (comprend : la génération du code binaire exécutable, uniquement) du programme puisse être "aussi indépendante" que possible de la bibliothèque
    2. de faire en sorte que l'ajout d'un fichier lance la procédure de mise à jour du script de compilation
    3. de faire en sorte à ne compiler dans le pire des cas qu'une fois chaque fichier source (s'il a été modifié)
    4. de faire en sorte qu'il suffise d'indiquer au compilateur la dépendance du programme vis-à-vis de la bibliothèque pour qu'il utilise les "flags qui vont bien"
    5. de faire en sorte que l'édition de liens ne soit effectuées (au niveau du programme) que si l'ABI de la bibliothèque (qui est partagée) est modifiée.


    Voici donc quelques modifications que je te conseillerais au niveau de tes fichiers:
    pour la bibliothèque
    définir une variable (oops_dev_dir ) qui pointe sur le dossier src/dev, et l'utiliser pour dresser les listes exhaustives des fichiers d'en-tête et des fichiers d'implémentation sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    set(oops_dev_dir ${CMAKE_CURRENT_SOURCE_DIR}/src/dev)
    #INC_FILES est l'équivalent de la variable dev_hpp_files dans ton code
    set(INC_FILES ${oops_dev_dir}/a.hpp
                  ${oops_dev_dir}/b.hpp
                  ${oops_dev_dir}/c.hpp
                  ... )
    #SRC_FILES est l'équivalent de la variable dev_cpp_files dans ton code
    set(SRC_FILES ${oops_dev_dir}/a.cpp
                  ${oops_dev_dir}/b.cpp
                  ${oops_dev_dir}/c.cpp
                  ... )
    add_library(oops-dev SHARED ${SRC_FILES} ${INC_FILES})
    # ...tout le reste, j'ai juste remplacer l'utilisation de GLOB_RECURSE
    pour le programme
    définir une variable (oops_prg_dir ) qui pointe sur le dossier src, et l'utiliser pour dresser les listes exhaustives des fichiers d'en-tête et des fichiers d'implémentation sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    set(oops_dev_dir ${CMAKE_CURRENT_SOURCE_DIR}/src)
    #INC_FILES est l'équivalent de la variable include_files dans ton code
    set(INC_FILES ${oops_prg_dir}/a.hpp
                  ${oops_prg_dir}/b.hpp
                  ${oops_prg_dir}/c.hpp
                  ... )
    #SRC_FILES est l'équivalent de la variable source_files dans ton code
    set(SRC_FILES ${oops_prg_dir}/a.cpp
                  ${oops_prg_dir}/b.cpp
                  ${oops_prg_dir}/c.cpp
                  ... )
    add_executable(cpp-sandbox ${SRC_FILES} ${INC_FILES})
    # ...tout le reste, j'ai juste remplacer l'utilisation de GLOB_RECURSE
    NOTA :Il va de soi que tu peux adapter les noms de variables que j'utilise ici... Il n'y aurait aucun problème à utiliser SRC_FILES et INC_FILES pour les deux (la bibliothèque et le programme) pour autant que nous travaillions dans des fichiers séparés.

    Il se peut que l'utilisation de noms identiques pose problème si l'idée est de regrouper la création de la bibliothèque et du programme au sein d'un seul et unique fichier CMakeLists.txt (mais, comme c'est le genre de chose que je ne fais jamais, je laisse la place au doute )

    Ces simples modifications vont littéralement changer ta vie, parce que:
    1. tous les fichiers ne seront compilés qu'une seule fois au maximum (pour autant qu'il soit nécessaire de le faire), ce qui te fera gagner énormément de temps
    2. il te "suffira" de rajouter le nom d'un nouveau fichier dans la liste ad-hoc (selon qu'il s'agit d'un fichier d'en-tête ou d'un fichier d'implémentation, selon qu'il est destiné à être utilisé pour la bibliothèque ou pour l'exécutable) pour qu'il soit systématiquement pris en compte la prochaine fois que tu lancera la compilation
    3. si tu utilise un EDI qui supporte CMake, tout fichier ajouté à la liste ad-hoc sera automatiquement ajouté à la liste des fichiers que ton EDI t'affiche
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. CMAKE (cmakelists.txt) / cogitant/COGUI
    Par helpus dans le forum Build
    Réponses: 0
    Dernier message: 03/11/2010, 16h28
  2. [CMAKE] création d'un CMakeLists.txt
    Par AuraHxC dans le forum CUDA
    Réponses: 3
    Dernier message: 12/10/2010, 19h29

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