Un aspecto clave al trabajar con bibliotecas de terceros en cualquier lenguaje de programación es la facilidad para administrar paquetes. En cuanto a C y C++ actualmente no hay un administrador incluido de manera predeterminada, sin embargo existen varias opciones externas entre las que destacan vcpkg, y Conan.

Conan es un administrador de paquetes multiplataforma, descentralizado, y de código abierto, que permite crear y compartir paquetes de software.

Usar bibliotecas de terceros

Tradicionalmente al escribir un programa en C++ que usa una biblioteca de terceros, por ejemplo Boost, los pasos a seguir son:

  1. Descargar el paquete (precompilado, o el código fuente)
  2. Vincular el paquete al proyecto (identificar las rutas)
  3. Vincular directorios requeridos
  4. Enlazar las bibliotecas a usar en el proyecto
  5. Incluir archivos de cabecera
  6. Usar la biblioteca en el programa
  7. Indicar las instrucciones de compilación requeridas.

Estos pasos se repiten para cada biblioteca que se quiera usar en el proyecto. Para cambiar de versión probablemente hace que desinstalar la anterior. Los pasos pueden variar dependiendo de la plataforma (Windows, Linux/Ubuntu, MacOS). Las instrucciones de compilación pueden ser complejas de entender. Si se descarga el código fuente del paquete es probable que tenga su propio sistema de compilación. Hay varias desventajas de que este proceso sea manual.

Con Conan los pasos son similares pero automatizados, centralizados en lo que han llamado Recetas a las cuales se accede por medio de una referencia a receta en donde se puede identificar de manera inmediata el nombre del paquete y la versión. La receta puede estar referenciada en un archivo plano conanfile.txt para mayor simplicidad. Por defecto Conan busca primero la existencia del archivo conanfile.py y luego del .txt pero se le puede indicar cuál es el archivo que contiene las recetas a usar.

Generadores de Conan

Son componentes que permiten identificar información del paquete para interactuar con el sistema de compilación. En el archivo plano se configuran en la sección [generators], y puede haber uno o varios generadores. Hay bastantes ejemplos que usan el generador cmake, sin embargo, desde Conan y desde la comunidad se está estimulando el uso del generador cmake_find_package que se integra directamente con la instrucción de CMake ampliamente conocida: find_package().

Ejemplos

Los siguientes ejemplos muestran la configuración requerida por Conan para utilizar algunas bibliotecas de terceros en un proyecto CMake:

googletest

Es el framework de pruebas de google. Es usado para crear pruebas unitarias, fixtures, mocks, entre otros. Tiene dos componentes principales: gtest y gmock. Los pasos a seguir son:

  1. Crear el archivo conanfile.txt. Se incluye la versión de gtest requerida, y el generador a usar.

     # conanfile.txt
     [requires]
       gtest/1.10.0
        
     [generators]
       cmake_find_package
    
  2. Ajustar el archivo CMakeLists.txt para buscar el paquete y enlazar las bibliotecas:

     set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_BINARY_DIR})
     find_package(GTest REQUIRED)
     target_link_libraries(${PROJECT_NAME} pthread GTest::gtest)
    
  3. Usar en el proyecto incluyendo el archivo de cabecera:

     #include "gtest/gtest.h"
        
     TEST(NombreDeLaPrueba, FuncionalidadAProbar)
     {
       EXPECT_TRUE(true);
     }
        
     int main(int argc, char* argv[])
     {
       testing::InitGoogleTest(&argc, argv);
       return RUN_ALL_TESTS();
     }
    

Catch2

Es otro framework de pruebas, liviano, nativo de C++ moderno, con opción de hacer micro-benchmarking, ideal para BDD y TDD. No hace falta enlazar la biblioteca ya que Catch2 es solo-cabecera. Los pasos para usar Catch2 son:

  1. Agregar la referencia a la receta de Catch2 al conanfile.txt

     # conanfile.txt
     [requires]
       catch2/2.13.3
        
     [generators]
       cmake_find_package
    
  2. Ajustar el CMakeLists.txt para que encuentre el paquete, y vincular los directorios include del paquete al proyecto:

     set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_BINARY_DIR})
     find_package(Catch2 REQUIRED)
     target_include_directories(${PROJECT_NAME} PRIVATE ${Catch2_INCLUDE_DIRS})
    
  3. En el programa, incluir el archivo de cabecera a usar:

     #define CATCH_CONFIG_MAIN
     #include "catch2/catch.hpp"
        
     TEST_CASE("foo")
     {
       REQUIRE( 1 == 1);
     }
    

Boost: Property Tree y Regex

Con Boost hay que tener algunas consideraciones adicionales ya que contiene bibliotecas solo-cabecera, por lo cual hay que identificar cuáles se deben enlazar y cuáles no. Por ejemplo al usar Boost.PropertyTree la cual es solo-cabecera no se debe enlazar sino solamente vincular sus directorios include; para Boost.Regex sí se debe enlazar la biblioteca correspondiente:

  1. Agregar Boost 1.69 al conanfile.txt:

     [requires]
       boost/1.69.0
        
     [generators]
       cmake_find_package
    
  2. Ajustar el CMakeLists.txt para que encuentre el paquete, enlazar Boost::regex al proyecto, y vincular los directorios include de Boost al proyecto:

     set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_BINARY_DIR})
     find_package(Boost COMPONENTS regex REQUIRED)
     target_link_libraries(${PROJECT_NAME} Boost::regex)
     target_include_directories(${PROJECT_NAME} PRIVATE ${Boost_INCLUDE_DIRS})
    
  3. Incluir los archivos de cabecera requeridos:

     #include "boost/property_tree/json_parser.hpp"
     #include "boost/property_tree/ptree.hpp"
     #include "boost/regex.h"
    

Consideraciones

  • Recordar que find_package distingue mayúsculas y minúsculas.

  • Conan se puede instalar localmente, y también se puede usar directamente en un CI, por ejemplo con TravisCI, AppVeyor CI, o Github Actions. Solo requiere que se soporte Python.

  • La instalación y configuración básica de Conan teniendo instalado python3 y pip3 se realiza por medio de los comandos:

pip3 install conan 
conan user

Nota: Es posible que en Travis CI se deba usar pip en lugar de pip3, de acuerdo a la versión de python que esté instalada en el job.

  • Después de tener Conan instalado se puede proceder a instalar los paquetes para un proyecto que ya tenga la configuración de bibliotecas manejadas por Conan. Por ejemplo para un proyecto en el que la compilación se hace desde el directorio build/ el comando es:
conan install ../conanfile.txt

Con el comando anterior se descargan y configuran los paquetes, y se copia el archivo conanbuildinfo.cmake al proyecto. Al usar el generador cmake_find_package se obtienen los archivos Find*.cmake de cada paquete. Después de este paso se puede continuar con los pasos regulares de compilación: cmake .., cmake --build, etc, teniendo en cuenta que se le debe indicar la ruta de CMAKE_MODULE_PATH que usualmente es el directorio de compilación.

  • Catch2 y googletest deben tener configurado el punto de entrada main.

  • Las versiones usadas en los ejemplos son:

Paquete Versión
CMake > 3.0
Conan > 1.28.1

Fuentes

Deja un comentario