2010-12-07 7 views
0

Hallo,Variables globales dans CMake pour le suivi des dépendances

J'utilise CMake comme système de construction dans un de mes projets, ce qui est assez complexe. Le projet comprend plusieurs bibliothèques et plusieurs applications. Mon but est, de faire le possible suivant:

  1. Les bibliothèques peuvent être construites sur demande par l'utilisateur (réalisé par la variable CMake mis en cache)
  2. Les applications sont construites sur demande par l'utilisateur (voir ci-dessus), mais une application peut sélectionner les bibliothèques nécessaires et les construire sans que l'utilisateur en les sélectionnant
  3. Cela ne devrait pas changer la sélection de l'utilisateur mis en cache sur lequel les bibliothèques de construire (pour désactiver la construction des bibliothèques automatiquement si le bâtiment d'application est désactivée)

Mon système de construction layo ut est la suivante: J'ai un répertoire parent qui contient un CMakeLists.txt qui ajoute les bibliothèques et les applications en tant que sous-répertoire. Chaque bibliothèque et application possède son propre CmakeLists.txt qui définit les options de configuration définissables par l'utilisateur à stocker dans le cache, les cibles à construire et les autres bibliothèques du projet dont il dépend. Les applications ne sont pas nécessairement situées dans le sous-répertoire suivant du répertoire parent, mais peuvent également avoir des niveaux inférieurs, de sorte que je ne peux pas utiliser PARENT_SCOPE, car le parent ne doit pas être le parent le plus haut, mais les dépendances doivent être connues en haut. J'ai essayé de paramétrer les propriétés GLOBAL comme PROJECT_BUILD_SOMELIBRARY sur on et j'ai essayé de les récupérer dans CMakeLists.txt de SOMELIBRARY pour décider de construire ou non, mais les propriétés ne sont pas passées à la bibliothèque, donc elles ne sont jamais construites si c'était le cas, car une autre bibliothèque ou application indiquait que cela dépendait de cette bibliothèque. L'utilisation d'un LISTE contenant le nom de chaque application ou cible de bibliothèque en fonction d'une bibliothèque et la mise en cache de celle-ci en interne ne fonctionnait pas non plus. Pour résumer ces nombreux mots, je cherche un moyen d'influencer un CMakeLists dans un sous-répertoire chargé de construire une bibliothèque par un CMakeLists dans un autre sous-répertoire (qui n'est pas nécessairement le même niveau de sous-répertoire que l'autre subdir) pour construire cette bibliothèque, même si l'utilisateur ne l'a pas explicitement spécifié via l'option de configuration sur l'invocation cmake.

Est-ce que quelqu'un sait comment cela pourrait être réalisé ou est-ce impossible avec CMake? Y a-t-il des suggestions pour d'autres approches à ce problème qui, cependant, incluent l'utilisation de CMake? Connaissez-vous un autre système de construction qui pourrait gérer ces exigences confortablement?

Un grand merci, Crispinus

Répondre

0

J'ai résolu le problème par moi-même entre-temps. En fait, il était assez simple de mettre en œuvre la configuration que j'ai expliqué ci-dessus. J'ai utilisé l'option EXCLUDE_FROM_ALL pour toutes les cibles selon qu'elles ont été explicitement sélectionnées par l'utilisateur (= omettez l'EXCLUDE_FROM_ALL) ou non. L'option EXCLUDE_FROM_ALL a pour effet qu'une cible n'est pas incluse dans la cible globale, sauf si une autre cible (qui n'est pas marquée comme EXCLUDE_FROM_ALL) dépend de cette cible. Cela fonctionne même sur les sous-répertoires, car les cibles CMake sont vraiment globales et même le parent le plus haut connaît la cible du sous-répertoire le plus bas, et même un sous-répertoire au même niveau connaît les cibles d'un autre sous-répertoire.

Dans ma mise en page, chaque partie séparée de mon projet contient son propre CMakeLists.txt et ajoute ses propres options dans le cache, de sorte qu'un échantillon sous-projet regarderait cette façon:


SET(PART_NAME SAMPLE_PART) 
SET(PART_TARGET_NAME samplepart) 

SET(BUILD_${PART_NAME} off CACHE BOOL "Build part ${PART_NAME}") 
SET(${PART_NAME}_FILES some_file.c another_file.c) 

IF(NOT BUILD_${PART_NAME}) 
SET(EXCLUDE_${PART_NAME} EXCLUDE_FROM_ALL) 
ENDIF(NOT BUILD_${PART_NAME}) 

ADD_LIBRARY(${PART_TARGET_NAME} SHARED ${EXCLUDE_SAMPLE_PART} ${PART_NAME}_FILES) 
TARGET_LINK_LIBRARY(${PART_TARGET_NAME} some_other_target) 
 

Donc, si l'utilisateur choisit à BUILD_SAMPLE_PART, la cible n'est pas définie sur EXCLUDE_FROM_ALL et sera incluse dans tous; sinon, la cible est définie sur EXCLUDE_FROM_ALL et ne sera créée que si une autre cible en dépend. Si cette cible est construite, le "some_other_target" sera aussi construit, qu'il soit inclus ou non dans le tout.

2

Une façon de rendre les variables globales CMake est:

set(EXAMPLE_INCLUDE_DIRS CACHE INTERNAL "include directories" FORCE) 

que lorsque vous voulez ajouter ou définir l'utilisation de la valeur:

set(EXAMPLE_INCLUDE_DIRS ${EXAMPLE_INCLUDE_DIRS } ${EXTRA_INCLUDE_DIRS } 
CACHE INTERNAL "include directories") 
0

J'ai créé un exemple en ligne qui tente de répondre à cette question. Vous devrait être en mesure de le télécharger mon référentiel GitHub au bgoodrs-CMake-Examples. Si vous cliquez sur ce lien , vous pouvez lire le document (README.markdown dans ce référentiel) qui essaie de faire le même genre de choses que je pense que vous voulez . Vous pouvez cliquer sur le bouton de téléchargement pour télécharger une copie de les exemples d'expérimentation locale.Si cela a manqué la note, puis commenter ma réponse, et je vais essayer d'améliorer l'exemple en conséquence.

+0

Merci pour votre réponse très élaborée. Autant que je vois, votre solution se dirige dans une direction différente, car je ne peux pas laisser de côté le répertoire add_subdirectory, parce que le CMakeLists.txt dans chaque sous-répertoire parts contient l'option de cache qui fera les cibles de cette partie. Chaque sous-répertoire doit être ajouté, quelles que soient les pièces à construire. – crispinus