
Na parte anterior desta história divertida, falamos sobre a organização de uma biblioteca de cabeçalhos como parte do gerador do sistema de montagem do CMake.
Desta vez, adicionamos uma biblioteca compilada e também falamos sobre o layout dos módulos.
Como antes, quem não pode esperar pode ir imediatamente ao repositório atualizado e tocar em tudo com as próprias mãos.
Conteúdo
- Compartilhar
- Conquistar
A primeira coisa a fazer para alcançar nosso objetivo elevado é dividir o software em desenvolvimento em blocos isolados universais, uniformes do ponto de vista do usuário.
A primeira parte descreveu um bloco padrão - um projeto com uma biblioteca de cabeçalhos. Agora vamos adicionar uma biblioteca compilada ao nosso projeto.
Para fazer isso, retiramos a implementação da função myfunc
em um arquivo .cpp
separado:
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; + } +}
Em seguida, definimos a biblioteca compilada ( myfeature
), que consistirá no arquivo .cpp
obtido na etapa anterior. A nova biblioteca, obviamente, requer cabeçalhos existentes e, para garantir isso, é possível e necessário combiná-la com o objetivo existente do mylib
. Além disso, o link entre eles é público, o que significa que tudo o que o destino da myfeature
será conectado myfeature
automaticamente o destino do mylib
na carga ( mais sobre como se conectar ).
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 seguir, tornaremos a nova biblioteca também 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)
Deve-se notar que, para o propósito myfeature
, assim como para mylib
, um alias foi prefixado com o prefixo Mylib::
. O mesmo é afirmado para os dois propósitos ao exportá-los para instalação no sistema. Isso torna possível trabalhar de maneira uniforme com os objetivos de qualquer esquema de vinculação .
Depois disso, resta tricotar testes de unidade com a nova biblioteca (a função myfunc
foi myfunc
do cabeçalho, agora você precisa vincular):
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 )
Os cabeçalhos ( Mylib::mylib
) agora não precisam ser conectados separadamente, porque, como já mencionado, eles são automaticamente conectados juntos à biblioteca ( Mylib::myfeature
).
E adicione algumas nuances para garantir as medições da cobertura, levando em consideração a biblioteca recém-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 )
Você pode adicionar mais bibliotecas, executáveis, etc. Não importa exatamente como elas são unidas na estrutura do projeto. A única coisa importante é quais objetivos são a interface do nosso módulo, ou seja, se destacam.
Agora temos módulos-blocos padrão e podemos dominá-los: criar uma estrutura de qualquer complexidade a partir deles, instalando-os em um sistema ou interconectando-os em um único sistema de montagem.
Instalação do sistema
Uma das opções para usar o módulo é instalar nosso módulo no sistema.
cmake --build /// --target install
Depois disso, ele se conecta a qualquer outro projeto usando o find_package
.
find_package(Mylib 1.0 REQUIRED)
Conexão como um submódulo
Outra opção é conectar a pasta ao nosso projeto a outro projeto como um submódulo usando o add_subdirectory
.
Use
Os métodos de ligação são diferentes, mas o resultado é o mesmo. Nos dois casos, em um projeto usando nosso módulo, os objetivos Mylib::myfeature
e Mylib::mylib
estarão disponíveis, que podem ser usados, por exemplo, assim:
add_executable(some_executable some.cpp sources.cpp) target_link_libraries(some_executable PRIVATE Mylib::myfeature)
Especificamente, no nosso caso, a Mylib::myfeature
precisa estar conectada quando for necessário libmyfeature
biblioteca libmyfeature
. Se houver cabeçalhos suficientes, você deverá usar a biblioteca Mylib::mylib
.
Os destinos do CMake podem ser complicados, por exemplo, projetados apenas para encaminhar algumas propriedades, dependências etc. Ao mesmo tempo, o trabalho com eles ocorre de uma maneira única.
O que era necessário para receber.