web-dev-qa-db-fra.com

Comment créer une bibliothèque d'en-tête cmake uniquement qui dépend de fichiers d'en-tête externes?

J'ai un projet avec la structure de fichier suivante:

project
 |
 |-------> lib1
 |           |----> lib1.h
 |
 |-------> lib2
 |           |----> lib2.h
 |
 |-------> main.cc

Les deux bibliothèques lib1 et lib2 ne contiennent que des fichiers d'en-tête, alors que lib2.h inclut lib1.h et main.cc inclut lib2.h.

Comment puis-je écrire le fichier cmake pour ce projet maintenant? J'ai essayé de créer une bibliothèque interface pour lib2, mais le compilateur ne trouve pas lib1.h. Voici le contenu de mes fichiers cmake:

CMakeLists.txt pour lib2:

add_library(lib2 INTERFACE)
target_sources(lib2 INTERFACE lib2.h)
target_include_directories(lib2 INTERFACE ../lib1/lib1.h)

CMakeLists.txt pour l'ensemble du projet:

add_executable(project main.cc)
target_link_libraries(project lib2)

Quel est le problème dans les fichiers cmake?

7
X. Liu

Comme indiqué dans les commentaires, target_include_directories devrait recevoir un chemin d'accès à un répertoire, pas à un fichier.

De plus, si vous voulez créer une dépendance pour lib2 sur lib1, vous devriez le faire via target_link_libraries: une dépendance ne concerne pas seulement les répertoires d'inclusion, mais aussi les options de compilation, les définitions, les propriétés de la cible ...

target_sources ne fonctionne pas avec les bibliothèques d'interface. De cette réponse , Vous pouvez utiliser une cible personnalisée sans commande pour associer les sources à une cible sans impacter le processus de construction (pour msvc, QtCreator et d’autres outils basés sur une interface graphique, les sources sont accessibles via l’EDI; c'est inutile pour d'autres outils de construction).

Votre cmake peut ressembler à ceci:

add_library(lib1 INTERFACE)
target_sources(lib1 INTERFACE lib1.h)

target_include_directories(lib1 INTERFACE
    "${PROJECT_SOURCE_DIR}/lib1"
)

add_library(lib2 INTERFACE)
if(MSVC)
    add_custom_target(lib2.headers SOURCES lib2.h)
endif()

target_include_directories(lib2 INTERFACE
    "${PROJECT_SOURCE_DIR}/lib2"
)

target_link_libraries(lib2 INTERFACE lib1)

add_executable(project main.cc)
target_link_libraries(project lib2)

Conseil avancé: vous pouvez spécifier un répertoire différent dans target_include_directories pour l’arbre de construction et l’arborescence d’installation (voir documentation ):

target_include_directories(lib1 INTERFACE
    $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/lib1>
    $<INSTALL_INTERFACE:${YOUR_INSTALL_DIR}/lib1>
)
13
wasthishelpful

J'ai utilisé un fichier _only_for_compiling_the_lib.cpp vide comme solution de contournement la plus simple et la plus rapide, mais il est clair que la solution ci-dessus est vivement conseillée.

Je n'étais tout simplement pas au courant du mot clé INTERFACE.

1
Michał Kawiecki