
di questo affascinante racconto si parlava dell'organizzazione di una libreria di intestazione nel contesto del generatore di sistemi di compilazione CMake.
Questa volta aggiungeremo una libreria compilabile e discuteremo dell'organizzazione dei moduli tra loro.
Come sempre, quelli che non possono attendere possono subito e mettere tutto alla prova con le proprie mani.
Contenuto
La prima cosa da fare per raggiungere il nostro obiettivo ambizioso è dividere il software in blocchi isolati e universali, uniformi dal punto di vista dell'utente.
Nella prima parte è stato descritto un blocco standard: un progetto con una libreria di intestazione. Ora aggiungeremo al nostro progetto una libreria compilabile.
Per questo pero, estrarremo l'implementazione della funzione myfunc in un separato .cpp-file:
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
+
+namespace mylib
+{
+ bool myfunc (mystruct)
+ {
+ return true;
+ }
+}Poi definiremo la libreria compilabile (myfeature), che consisterà nel file appena ottenuto. .cppOvviamente, alla nuova libreria servono già le intestazioni esistenti, e per garantirlo è possibile e necessario collegarla con l'obiettivo esistente mylib. Il collegamento tra di loro sarà pubblico, il che significa che tutto a cui sarà collegato l'obiettivo myfeature, riceverà automaticamente anche l'obiettivo mylib ().
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)
+###################################################################################################
+##
+## Libreria Compilabile
+##
+###################################################################################################
+
+add_library(myfeature src/mylib/myfeature.cpp)
+target_link_libraries(myfeature PUBLIC mylib)
+
+add_library(Mylib::myfeature ALIAS myfeature)
+Successivamente faremo sì che la nuova libreria venga installata nel sistema:
@@ -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)È importante notare che per l'obiettivo myfeature, come per mylib è stato creato uno pseudonimo con il prefisso Mylib::. La stessa cosa è stata specificata per entrambi gli obiettivi durante l'esportazione per l'installazione nel sistema. Questo consente un lavoro uniforme con gli obiettivi in qualsiasi .
Dopo di che, è rimasto da legare i test modulari con la nuova libreria (la funzione myfunc è stata estratta dall'intestazione, quindi ora è necessario collegarsi):
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
)Intestazioni (Mylib::mylib) ora non è più necessario collegarle separatamente, poiché, come già detto, si collegano automaticamente insieme alla libreria (Mylib::myfeature).
E aggiungeremo un paio di dettagli per garantire le misurazioni della copertura tenendo conto della nuova libreria introdotta:
@@ -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
)Si possono aggiungere più librerie, file eseguibili e così via. Non importa come sono collegati tra loro nel progetto. L'importante è solo quali obiettivi rappresentano l'interfaccia del nostro modulo, cioè quelli accessibili esternamente.
Ora abbiamo moduli standard e possiamo gestirli: costruire da essi strutture di qualsiasi complessità, installandoli nel sistema o collegandoli tra loro all'interno di un unico sistema di build.
Installazione nel sistema
Una delle opzioni per utilizzare il modulo è installare il nostro modulo nel sistema.
cmake --build percorso/alla/directory/di/build --target installDopo di ciò, può essere collegato in qualsiasi altro progetto con il comando .
find_package(Mylib 1.0 REQUIRED)Collegamento come sottomodulo
Un'altra opzione è collegare la cartella del nostro progetto a un altro progetto come sottomodulo con il comando .
Utilizzo
I metodi di collegamento sono diversi, ma il risultato è lo stesso. In entrambi i casi, nel progetto che utilizza il nostro modulo, saranno disponibili gli obiettivi Mylib::myfeature e Mylib::mylib, che possono essere utilizzati, ad esempio, in questo modo:
add_executable(some_executable some.cpp sources.cpp)
target_link_libraries(some_executable PRIVATE Mylib::myfeature)Nel nostro caso specifico, la libreria Mylib::myfeature deve essere inclusa quando è necessario collegarsi con la libreria libmyfeature. Se sono sufficienti solo gli header, allora si può tornare a utilizzare la libreria Mylib::mylib.
Gli obiettivi di CMake possono essere astuti, ad esempio, progettati solo per passare alcune proprietà, dipendenze, ecc. In questo modo, il lavoro con essi avviene in modo uniforme.
Questo è ciò che si voleva ottenere.
Fonte: habr.com
