Recientemente estuve trabajando en enviar mensajes de Protocol Buffers (protobuf) a través de Keryx. Necesitaba almacenar estos mensajes en memoria y en disco y descubrí que los mensajes no estaban comprimidos. Me alegró descubrir que el API de protobuf para C++ brinda compresión basada en zlib, ya que esta es una forma aceptable de rápidamente reducir el tamaño de almacenamiento y tiempo de envío.
Protobuf provee las clases GzipOutputStream y GzipInputStream en el espacio de nombre (namespace) google::protobuf::io. Estas clases están definidas en la cabecera google/protobuf/io/gzip_stream.h. Sin embargo, varios errores de enlace revelaron que mi compilación inicial de protobuf carecía soporte de zlib.
Windows es la principal plataforma de desarrollo y ejecución para Keryx, por lo tanto esta guía explicará como habilitar compresión con zlib en protobuf 3.5.1 compilado desde código fuente con Visual Studio 2015. El proceso para compilar con Visual Studio 2017 debe ser similar. Un método aún más sencillo es instalar protobuf with zlib support using vcpkg:
vcpkg install protobuf[zlib] protobuf[zlib]:x64-windows
Puedes aprender más acerca de vcpkg en la página de Microsoft y puedes obtenerlo en GitHub. En contraste, en esta guía explicaré cómo manualmente clonar y compilar el código fuente de protobuf de GitHub. Los siguientes pasos difieren un poco de los que brindan los desarrolladores de protobuf, pero aún así necesitarás:
- Git para clonar los repositorios de protobuf y zlib
- CMake y Visual Studio para compilar protobuf y zlib
Clone and build zlib
Las instrucciones para compilar protobuf 3.5.1 recomiendan usar zlib 1.2.8. Abre un símbolo de sistema (terminal de comandos, command prompt) en un directorio de trabajo (por ejemplo, C:\workspace). Obten el código fuente de zlib 1.2.8 clonando la etiqueta (tag) v1.2.8 del proyecto zlib en GitHub con el siguiente comando:
git clone -b v1.2.8 https://github.com/madler/zlib.git
Podemos reducir el número de confirmaciones (commits) clonando solo aquellos que conducen a la etiqueta v1.2.8 con el uso del argumento –single-branch argument:
git clone -b v1.2.8 --single-branch https://github.com/madler/zlib.git
y aún más al omitir toda historia de confirmaciones y clonar solo la confirmación etiquetada como v1.2.8 con el uso del argumento –depth=1:
git clone -b v1.2.8 --single-branch --depth=1 https://github.com/madler/zlib.git
El repositorio de zlib se encontrará en el directorio zlib. Ahora generemos un proyecto de Visual Studio con cmake en un nuevo directorio llamado build que instale los archivos generados en un directorio llamado install:
cd zlib
mkdir build
cd build
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_INSTALL_PREFIX=../install ..
Podemos manualmente compilar la solución generada abriendo zlib\build\zlib.sln con Visual Studio, o simplemente compilar desde la terminal de comando usando cmake. Los siguientes comandos compilan el proyecto ALL_BUILD de Visual Studio en modos de distribución (Release) y depuración (Debug):
cmake --build . --target ALL_BUILD --config Release
cmake --build . --target ALL_BUILD --config Debug
Compila el proyecto INSTALL de Visual Studio en modos de distribución y depuración para copiar al directorio de instalación las cabeceras, los archivos de configuración y los archivos binarios generados:
cmake --build . --target INSTALL --config Release
cmake --build . --target INSTALL --config Debug
El proyecto INSTALL generado por cmake para zlib no instala el the .pdb file generado en la compilación bajo modo de depuración, entonces es recomendable que lo copies manualmente por si necesitas depurar dentro de zlib:
copy Debug\zlibd.pdb ..\install\bin
Cómo clonar y compilar protobuf
Cambia el directorio en la terminal de comandos de nuevo al directorio de trabajo y clona protobuf 3.5.1 de GitHub:
cd ..\..
git clone -b v3.5.1 --single-branch https://github.com/protocolbuffers/protobuf.git
Crea un directorio dentro del repositorio clonado para generar la solución de Visual Studio con cmake, por ejemplo, builds (ya existe un archivo de configuración de Bazel llamado BUILD en el directorio principal del repositorio de protobuf):
cd protobuf
mkdir builds
cd builds
Entra al nuevo directorio y ejecuta cmake hacia el directorio cmake del repositorio de protobuf con las siguientes opciones de configuración:
- protobuf_BUILD_SHARED_LIBS=ON para habilitar la generación de libreros compartidos, es decir, libreros de enlace dinámico (DLL por sus siglas en inglés)
- protobuf_BUILD_TESTS=OFF para deshabilitar la compilación de pruebas unitarias para protobuf y por lo tanto evitar la introducción de una dependencia a gmock
- protobuf_WITH_ZLIB=ON para habilitar el uso de zlib en protobuf
- protobuf_DEBUG_POSTFIX=d para agregar la letra d al nombre base de archivos binarios generados en una compilación en modo de depuración
- protobuf_VERBOSE=ON para generar un registro detallado durante la compilación de protobuf
- protobuf_MSVC_STATIC_RUNTIME=OFF para usar libreros de ejecución enlazados dinámicamente en vez de enlazar los libreros de ejecución estáticamente
- CMAKE_DEBUG_POSTFIX=d para agregar la letra d al nombre base de archivos binarios generados en una compilación en modo de depuración, puede ser redundante o de otra manera duplicar la opción protobuf_DEBUG_POSTFIX
- CMAKE_INSTALL_PREFIX=../install para copiar cabeceras, archivos de configuración y archivos binarios generados en la compilación al archivo de instalación install cuando se compile el projecto INSTALL
- ZLIB_ROOT=../../zlib/install para sugerir al
módulo FindZLIB de cmake dónde buscar a zlib (las instrucciones en cmake/README.md son más complicadas de lo necesario y no me funcionaron bien)
cmake -G "Visual Studio 14 2015 Win64" ^
-Dprotobuf_BUILD_SHARED_LIBS=ON ^
-Dprotobuf_BUILD_TESTS=OFF ^
-Dprotobuf_WITH_ZLIB=ON ^
-Dprotobuf_DEBUG_POSTFIX=d ^
-Dprotobuf_VERBOSE=ON ^
-Dprotobuf_MSVC_STATIC_RUNTIME=OFF ^
-DCMAKE_DEBUG_POSTFIX=d ^
-DCMAKE_INSTALL_PREFIX=../install ^
-DZLIB_ROOT=../../zlib/install ^
../cmake
Podemos compilar e instalar la solución de Visual Studio para protobuf usando cmake, tal cómo lo hicimos para zlib:
cmake --build . --target ALL_BUILD --config Release
cmake --build . --target ALL_BUILD --config Debug
cmake --build . --target INSTALL --config Release
cmake --build . --target INSTALL --config Debug
Los archivos .pdb generados por la compilación en modo de depuración no son instaladas por el proyecto INSTALL, pero las puedes copiar manualmente al directorio install/bin:
copy Debug\*d.pdb ..\install\bin
Explicaré en un próximo artículo cómo serializar y deserializar un mensaje protobuf en C++ con flujos (streams) que usan zlib, además de cómo deserializar un mensaje protobuf con el API oficial para C# desde un arreglo de bytes con datos comprimidos usando zlib.
Esta obra de Simverge Software LLC está bajo una Licencia Creative Commons Atribución 4.0 Internacional.