
Esta entretida historia falou sobre a organización dunha biblioteca de cabeceiras dentro do xerador do sistema de compilación CMake.
Nesta ocasión engadirémoslle unha biblioteca compilada, e tamén falaremos de vincular módulos entre si.
Como antes, os que están impacientes poden inmediatamente e toca todo coas túas propias mans.
Contido
O primeiro que debemos facer para acadar o noso elevado obxectivo é dividir o software que desenvolvemos en bloques universais, illados e uniformes desde o punto de vista do usuario.
Na primeira parte, describiuse un bloque estándar deste tipo: un proxecto cunha biblioteca de cabeceiras. Agora imos engadir unha biblioteca compilada ao noso proxecto.
Para iso, imos sacar a implementación da función myfunc nun separado .cpp- arquivo:
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;
+ }
+}Despois definimos a biblioteca a compilar (myfeature), que consistirá no obtido no paso anterior .cpp- arquivo. Obviamente, a nova biblioteca require cabeceiras existentes e, para proporcionar isto, pode e debe estar ligada ao propósito existente. mylib. Ademais, a conexión entre eles é pública, o que significa que todo o que se conectará o obxectivo myfeature, recibirá automaticamente a carga e o destino 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)
+###################################################################################################
+##
+## Компилируемая библиотека
+##
+###################################################################################################
+
+add_library(myfeature src/mylib/myfeature.cpp)
+target_link_libraries(myfeature PUBLIC mylib)
+
+add_library(Mylib::myfeature ALIAS myfeature)
+A continuación, asegurarémonos de que a nova biblioteca tamén estea instalada no 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)Cómpre sinalar que para o efecto myfeature, como para mylib creouse un alias cun prefixo Mylib::. O mesmo escríbese para ambos os efectos ao exportalos para a súa instalación no sistema. Isto fai posible traballar uniformemente con obxectivos para calquera .
Despois disto, só queda vincular as probas unitarias coa nova biblioteca (función myfunc eliminado do título, agora tes que enlazar):
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
)Títulos (Mylib::mylib) agora non precisa conectarse por separado, porque, como xa se mencionou, están conectados automaticamente xunto coa biblioteca (Mylib::myfeature).
E engademos un par de matices para garantir as medidas de cobertura tendo en conta a biblioteca recentemente chegada:
@@ -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
)Podes engadir máis bibliotecas, executables, etc. Non importa como estean exactamente conectados entre si dentro do proxecto. O único importante é que obxectivos son a interface do noso módulo, é dicir, que sobresaen.
Agora temos módulos de bloque estándar, e podemos dominalos: compoñelos nunha estrutura de calquera complexidade, instalándoos nun sistema ou ligándoos entre si nun único sistema de montaxe.
Instalación no sistema
Unha das opcións para usar o módulo é instalar o noso módulo no sistema.
cmake --build путь/к/сборочной/директории --target installDespois diso, conéctase a calquera outro proxecto mediante o comando .
find_package(Mylib 1.0 REQUIRED)Conexión como submódulo
Outra opción é conectar o cartafol co noso proxecto a outro proxecto como submódulo mediante o comando .
Usar
Os métodos de unión son diferentes, pero o resultado é o mesmo. En ambos os casos, os obxectivos estarán dispoñibles no proxecto mediante o noso módulo Mylib::myfeature и Mylib::mylib, que se pode usar, por exemplo, así:
add_executable(some_executable some.cpp sources.cpp)
target_link_libraries(some_executable PRIVATE Mylib::myfeature)Concretamente no noso caso, a biblioteca Mylib::myfeature debe estar conectado cando sexa necesario enlazar coa biblioteca libmyfeature. Se hai cabeceiras suficientes, paga a pena usar a biblioteca Mylib::mylib.
Os obxectivos de CMake poden ser complicados, por exemplo, destinados só a reenviar algunhas propiedades, dependencias, etc. Ao mesmo tempo, o traballo con eles ocorre do mesmo xeito.
Iso era o que necesitabamos conseguir.
Fonte: www.habr.com
