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?
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>
)
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
.