CMake: Construir una librería estática y/o dinámica
Esta receta explica cómo construir librerías estáticas y dinámicas con CMake.
Software necesario
Los ejemplos que vamos a utilizar puedes descargarlos utilizando subversion desde:
Los directorios contienen una librería con una definición de la clase Dummy (dummy.h y dummy.cpp) con un único método. También se incluye el CMakeLists.txt correspondiente.
Librería estática
Para crear una librería estática nada más fácil que lo que sigue:
El comando INCLUDE_DIRECTORIES permite añadir los directorios donde se encuentran las cabeceras del proyecto. En este caso, el fichero dummy.h se encuentra en el mismo directorio donde están los fuentes (el mismo en el que se encuentra CMakeLists.txt). La variable global CMAKE_CURRENT_SOURCE_DIR tiene esta ruta.
De una forma similar a como se añadían ejecutables, para crear una librería se debe utilizar ADD_LIBRARY que acepta, entre muchos otros, los siguientes parámetros:
objetivo: se trata un nombre simbólico para el objetivo que representa el crear la librería. Si no se especifica otra cosa, este nombre se utilizará para crear el fichero final de la forma libobjetivo.a.
STATIC: modo de la librería.
dependencias: de qué ficheros u objetivos depende la librería para su construcción
Librería dinámica
A la vista de lo anterior, parece sencillo crear una librería dinámica. ¿Bastará cambiar STATIC por SHARED?. Sí, con eso bastaría. Pero vamos a añadir algo más para hacer que la librería sea más "distribuible":
En CMake, los targets (objetivos) tienen propiedades que, a priori, tienen ciertos valores por defecto. La propiedad SOVERSION de los objetivos que son librerías dinámicas, por defecto, no tiene valor. Sin embargo, es conveniente versionar las librerías para que aquellas plataformas que lo soporten (como por ejemplo, GNU) puedan gestionar las versiones.
Con el comando SET_PROPERTY se puede modificar las propiedades de las estructuras que se van creando en el programa. En este caso, para el objetivo 'dummy' se cambia el valor de la propiedad SOVERSION a 1.0. De esta forma, al compilar la librería CMake generará los enlaces simbólicos necesarios de forma automática.
Librería estática y dinámica
Es posible que para una misma librería quieras que pueda ser enlazada de forma estática y también dinámica. Veamos una posible solución:
No se puede utilizar dummy como objetivos de ambas librerías. Lo que se puede hacer, por tanto, es crear un objetivo por cada tipo de librería (dummy_shared y dummy_static). Si no decimos nada más, CMake nos generará los archivos libdummy_static.a, libdummy_shared.so,... Y eso, obviamente, no es lo deseable.
Por ello utilizamos SET_TARGET_PROPERTIES que sirve para configurar propiedades de objetivos (es un caso particular de SET_PROPERTY).
Referencias
Documentación CMake2.8: consultar las propiedades genéricas y de los diferentes tipos abstractos (directorios, objetivos, ficheros fuente...).