web-dev-qa-db-fra.com

CMake et liaison dépendante de l'ordre des bibliothèques partagées

J'ai quelques petits composants que je construis en tant que bibliothèques partagées pour mon application principale. Utilisons un exemple de liba et libb. Chacun est construit dans leur propre sous-répertoire comme suit:

add_library(liba SHARED a.cpp)

Ensuite, dans le dossier racine du projet, je dois lier mon application principale aux deux.

include_directories(a)
include_directories(b)
add_executable(dummy dummy.cpp)
target_link_libraries(dummy a b)

CMake fonctionne bien avec cela, et mon application compile mais ne parvient pas à se lier. Le problème est que b fait référence à a. Si je fournis l'ordre des bibliothèques lors de la liaison en tant que

target_link_libraries(dummy b a)

Le programme compile et relie très bien

Lorsque ce type de système commence à impliquer une interdépendance plus complexe des bibliothèques, il commence à être impossible même si les dépendances sont acycliques. Comment gérer l'étape de liaison ici? Existe-t-il une astuce pour commander des bibliothèques à lier dans CMake?

34
dusktreader

Vous pouvez spécifier la relation entre a et b en ajoutant

target_link_libraries(b a)


Dans le docs :

Les dépendances de bibliothèque sont transitives par défaut. Lorsque cette cible est liée à une autre cible, les bibliothèques liées à cette cible apparaîtront également sur la ligne de lien de l'autre cible.

Ainsi, si vous spécifiez a comme une dépendance de b de cette manière, vous n'avez même pas besoin de répertorier explicitement a dans une cible qui dépend de b, c'est-à-dire que votre autre commande peut être simplement:

target_link_libraries(dummy b)

bien que cela ne nuise pas à la liste de a également.

33
Fraser

Une solution facile (en particulier pour les dépendances circulaires) peut être de simplement mettre toutes vos bibliothèques dans une variable de liste, puis d'ajouter cette liste deux fois (ou plus si nécessaire), comme:

set(LINK_LIBS "liba libb libc")
target_link_libraries(app ${LINK_LIBS} ${LINK_LIBS})

(ou tapez simplement la liste deux fois de suite dans le target_link_libraries fonction)

Cela a fonctionné pour moi plusieurs fois, mais je dois admettre qu'il pourrait y avoir des inconvénients possibles que je ne connais pas (à part cela, cela semble être un peu un hack).

14
sonicwave