
Dans la partie précédente de cette histoire divertissante, nous avons parlé d'organiser une bibliothèque d'en-tête dans le cadre du générateur de système d'assemblage CMake.
Cette fois, nous y ajoutons une bibliothèque compilée et parlons également de la disposition des modules entre eux.
Comme précédemment, ceux qui ne peuvent pas attendre peuvent immédiatement accéder au référentiel mis à jour et toucher tout de leurs propres mains.
Table des matières
- Partagez
- Conquérir
La première chose à faire pour atteindre notre noble objectif est de diviser le logiciel en cours de développement en blocs universels isolés qui sont uniformes du point de vue de l'utilisateur.
La première partie décrit un tel bloc standard - un projet avec une bibliothèque d'en-tête. Ajoutons maintenant une bibliothèque compilée à notre projet.
Pour ce faire, nous myfunc
l'implémentation de la fonction myfunc
dans un fichier .cpp
distinct:
diff --git a/include/mylib/myfeature.hpp b/include/mylib/myfeature.hpp index 43db388..ba62b4f 100644 --- a/include/mylib/myfeature.hpp +++ b/include/mylib/myfeature.hpp @@ -46,8 +46,5 @@ namespace mylib \~ \see mystruct */ - inline bool myfunc (mystruct) - { - return true; - } + bool myfunc (mystruct); } diff --git a/src/mylib/myfeature.cpp b/src/mylib/myfeature.cpp new file mode 100644 index 0000000..abb5004 --- /dev/null +++ b/src/mylib/myfeature.cpp @@ -0,0 +1,9 @@ +#include <mylib/myfeature.hpp> + +namespace mylib +{ + bool myfunc (mystruct) + { + return true; + } +}
Ensuite, nous définissons la bibliothèque compilée ( myfeature
), qui sera constituée du fichier .cpp
obtenu à l'étape précédente. La nouvelle bibliothèque, évidemment, nécessite des en-têtes existants, et pour garantir cela, il est possible et nécessaire de la tricoter avec le but existant de mylib
. De plus, le lien entre eux est public, ce qui signifie que tout ce à myfeature
cible myfeature
sera connectée myfeature
automatiquement la cible mylib
dans la charge (en savoir plus sur les façons de se connecter ).
diff --git a/CMakeLists.txt b/CMakeLists.txt index 108045c..0de77b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,6 +64,17 @@ target_compile_features(mylib INTERFACE cxx_std_17) add_library(Mylib::mylib ALIAS mylib) +################################################################################################### +## +## +## +################################################################################################### + +add_library(myfeature src/mylib/myfeature.cpp) +target_link_libraries(myfeature PUBLIC mylib) + +add_library(Mylib::myfeature ALIAS myfeature) +
Ensuite, nous ferons la nouvelle bibliothèque également installée sur le système:
@@ -72,7 +83,7 @@ add_library(Mylib::mylib ALIAS mylib) install(DIRECTORY include/mylib DESTINATION include) -install(TARGETS mylib EXPORT MylibConfig) +install(TARGETS mylib myfeature EXPORT MylibConfig) install(EXPORT MylibConfig NAMESPACE Mylib:: DESTINATION share/Mylib/cmake) include(CMakePackageConfigHelpers)
Il convient de noter que dans le but myfeature
, ainsi que pour mylib
, un alias a été préfixé avec le préfixe Mylib::
. La même chose est indiquée dans les deux cas lors de leur exportation pour une installation dans le système. Cela permet de travailler uniformément avec les objectifs de tout schéma de liaison .
Après cela, il reste à tricoter les tests unitaires avec la nouvelle bibliothèque (la fonction myfunc
a été myfunc
de l'en-tête, alors maintenant vous devez lier):
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 5620be4..bc1266c 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -4,7 +4,7 @@ add_executable(mylib-unit-tests test_main.cpp) target_sources(mylib-unit-tests PRIVATE mylib/myfeature.cpp) target_link_libraries(mylib-unit-tests PRIVATE - Mylib::mylib + Mylib::myfeature doctest::doctest )
Les en-têtes ( Mylib::mylib
) n'ont désormais plus besoin d'être connectés séparément, car, comme déjà mentionné, ils sont automatiquement connectés avec la bibliothèque ( Mylib::myfeature
).
Et ajoutez quelques nuances pour assurer des mesures de couverture en tenant compte de la bibliothèque nouvellement arrivée:
@@ -15,11 +15,16 @@ if(MYLIB_COVERAGE AND GCOVR_EXECUTABLE) target_compile_options(mylib-unit-tests PRIVATE --coverage) target_link_libraries(mylib-unit-tests PRIVATE gcov) + target_compile_options(myfeature PRIVATE --coverage) + target_link_libraries(myfeature PRIVATE gcov) + add_custom_target(coverage COMMAND ${GCOVR_EXECUTABLE} - --root=${PROJECT_SOURCE_DIR}/include/ - --object-directory=${CMAKE_CURRENT_BINARY_DIR} + --root=${PROJECT_SOURCE_DIR}/ + --filter=${PROJECT_SOURCE_DIR}/include + --filter=${PROJECT_SOURCE_DIR}/src + --object-directory=${PROJECT_BINARY_DIR} DEPENDS check )
Vous pouvez ajouter plus de bibliothèques, d'exécutables, etc. Peu importe comment exactement ils sont assemblés dans le cadre du projet. La seule chose importante est de savoir quels sont les objectifs de l'interface de notre module, c'est-à-dire de rester en place.
Nous avons maintenant des modules-blocs standard, et nous pouvons les dominer: en faire une structure de toute complexité, en les installant dans un système ou en les interconnectant au sein d'un système d'assemblage unique.
Installation du système
L'une des options pour utiliser le module est d'installer notre module dans le système.
cmake --build /// --target install
Après cela, il se connecte à tout autre projet à l'aide de la find_package
.
find_package(Mylib 1.0 REQUIRED)
Connexion en tant que sous-module
Une autre option consiste à connecter le dossier avec notre projet à un autre projet en tant que sous-module à l'aide de la add_subdirectory
.
Utiliser
Les méthodes de liaison sont différentes, mais le résultat est le même. Dans les deux cas, dans un projet utilisant notre module, les objectifs Mylib::myfeature
et Mylib::mylib
seront disponibles, qui peuvent être utilisés, par exemple, comme ceci:
add_executable(some_executable some.cpp sources.cpp) target_link_libraries(some_executable PRIVATE Mylib::myfeature)
Plus précisément, dans notre cas, la Mylib::myfeature
doit être connectée lorsqu'il est nécessaire de se libmyfeature
bibliothèque libmyfeature
. S'il y a suffisamment d'en-têtes, vous devez utiliser la bibliothèque Mylib::mylib
.
Les cibles CMake peuvent être délicates, par exemple, conçues uniquement pour transmettre certaines propriétés, dépendances, etc. Dans le même temps, travailler avec eux se fait de manière unique.
Ce qui était nécessaire pour recevoir.