12.07.2015 Views

Tutorial de CMake - csrg

Tutorial de CMake - csrg

Tutorial de CMake - csrg

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

1 Objetivo <strong>de</strong>l DocumentoEste documento tiene como objetivo servir <strong>de</strong> tutorial a la herramienta <strong>de</strong> construcción<strong>CMake</strong>.<strong>CMake</strong> es una herramienta <strong>de</strong>sarrollada inicialmente para po<strong>de</strong>r compilar<strong>de</strong> forma multiplataforma la librería VTK como un <strong>de</strong>sarrollo interno, pero queha sido publicada como herramienta <strong>de</strong> Software Libre, disponible en http://www.cmake.org.El objetivo <strong>de</strong> este documento no es el <strong>de</strong> servir como una referencia completaa la documentación <strong>de</strong>l sistema, ya que éste está perfectamente documentadoen la página anterior. Ni servir como documentación introductoria al uso.El objetivo es otro, es el <strong>de</strong>, partiendo <strong>de</strong> un conocimiento <strong>de</strong> la herramientabasada en la propia experiencia <strong>de</strong>l autor, ofrecer una guía para su aprendizaje.Por tanto, <strong>de</strong>stacaremos los aspectos que consi<strong>de</strong>ramos más esenciales, así comoofreceremos ejemplos propios. De esta forma, este documento pue<strong>de</strong> interpretarsecomo un documento complementario al resto <strong>de</strong> documentación adicionalexistente (no sólo se explica un conjunto <strong>de</strong> las distintas opciones posibles, sinoque, a<strong>de</strong>más, las opciones <strong>de</strong> las distintas directivas comentadas no son exhaustivas).El motivo es que aunque la herramienta está bien documentada, la docummentaciónse reduce a una explicación exhaustiva <strong>de</strong> las distintas directivas, sinestablecer un or<strong>de</strong>n <strong>de</strong> aprendizaje que permita ir avanzando poco a poco en suuso, tal y como se hace en este documento.Nótese que en todo el documento consi<strong>de</strong>raremos al lector como un <strong>de</strong>sarrolladorinteresado en aplicar el <strong>CMake</strong> en sus propios proyectos, perfil que <strong>de</strong>termina.Nota: Aunque haga referencia a Windows en el documento, adviertoque aunque tengo referencias <strong>de</strong> su buen comportamiento no lo he utilizado enese entorno (porque no tengo Windows instalado en ninguna <strong>de</strong> las máquinasque uso ;-) ).2 Configuración: <strong>CMake</strong>Lists.txtPara aplicar la herramienta para compilar un proyecto sólo es necesario generarun fichero <strong>CMake</strong>Lists.txt. Dicho fichero es el encargado <strong>de</strong> indicar toda lainformación necesaria:• Los ficheros a compilar.• Las librerías y ejecutables a generar.• Librerías <strong>de</strong> las que <strong>de</strong>pen<strong>de</strong>.• Parámetros adicionales.• Programas externos a utilizar (doxygen, . . . ).3


Toda esta información se concentra en un único fichero por proyecto, y conuna sintaxis que se planteó para que fuese sencilla, pero potente. Sin embargo,se pue<strong>de</strong> dividir.Es <strong>de</strong>cir, si tenemos el proyecto dividido <strong>de</strong> forma jerárquica en varios directoriospo<strong>de</strong>mos crear un <strong>CMake</strong>Lists.txt por cada directorio, y hacer que un<strong>CMake</strong>Lists.txt llame a los <strong>CMake</strong>Lists.txt <strong>de</strong> sus subdirectorios (mediante lainstrucción ADD SUBDIRECTORY ).A continuación <strong>de</strong>scribimos los parámetros más importantes.Notación: El uso <strong>de</strong> i<strong>de</strong>ntifica un parámetro. El uso <strong>de</strong> corchetes<strong>de</strong>termina que dicho parámetro es opcional3 Configuración MínimaPara crear un <strong>CMake</strong>Lists.txt, el formato mínimo suele ser:• <strong>CMake</strong>Lists.txt mínimo:PROJECT( h e l l o )ADD EXECUTABLE( h e l l o h e l l o . c )– PROJECT(< proyecto > [lenguaje]) : Definición <strong>de</strong>l proyecto.∗ < proyecto > es el nombre <strong>de</strong>l proyecto. Asociado a dicho nombrese generarán un conjunto <strong>de</strong> variables que i<strong>de</strong>ntifican losdistintos directorios. Es un requisito necesario.∗ lenguaje es el lenguaje <strong>de</strong>l proyecto. Aunque no es necesariopue<strong>de</strong> ser muy conveniente, si se especifica CXX, por ejemplo,usa el compilador <strong>de</strong> c++ incluso aunque los ficheros sean .c.Este parámetro presupone el mismo lenguaje para todos los ficherosa compilar. Si hay ficheros en distintos formatos, no <strong>de</strong>be <strong>de</strong> indicarse.– ADD EXECUTABLE(< ejecutable > < fichero1 > [. . .< ficheros >]: Define un ejecutable.∗ < ejecutable >, nombre <strong>de</strong>l ejecutable resultante <strong>de</strong> la compilación,sin ruta. Lo crea en el mismo directorio <strong>de</strong>s<strong>de</strong> el que sehay ejecutado cmake < arg >. Sin embargo, posteriormentese pue<strong>de</strong> indicar el directorio en el que instalarlo, mediante lainstrucción INSTALL.∗ < ficheros >, nombre <strong>de</strong> los ficheros <strong>de</strong> los que <strong>de</strong>pen<strong>de</strong> paracompilar. Dado que a veces el ejecutable coinci<strong>de</strong> en nombrecon uno <strong>de</strong> los ficheros, dicho fichero main se suele indicar enesta línea indicando su extensión. Los ficheros son una lista <strong>de</strong>nombres separados por espacio en blanco, pue<strong>de</strong>n tener extensióno no.Para el resto <strong>de</strong> ficheros, se suele usar una variable SRC,para mayor comodidad.4


– SET (< variable > [< ficheros >]): Define variable. Este es una<strong>de</strong> las directivas más útiles para hacer el fichero legible.∗ < variable >, nombre <strong>de</strong> la variable. Existen varias convencionesque se recomienda seguir. Si contiene ficheros a compilar, <strong>de</strong>beterminar en SRC. Una vez que se haya <strong>de</strong>finido, para usarla se<strong>de</strong>be <strong>de</strong> indicar $ < variable > $.∗ < ficheros > indica el conjunto <strong>de</strong> ficheros a utilizar, separadospor espacios (o retornos <strong>de</strong> carro, para mayor legibilidad).También se utiliza para <strong>de</strong>finir variables propias <strong>de</strong>l <strong>CMake</strong>, verApartado 10.Pue<strong>de</strong> usarsen variables para <strong>de</strong>finir otras variables. Ejemplo:SET (PROBLEM SRCf u n c t i o n su t i l sproblem common)SET (CEC SRC${PROBLEM SRC}problemcec2005).• cmake minimum version(V ERSION < numero version >): Definela versión <strong>de</strong> <strong>CMake</strong> requerida.A menudo, el <strong>CMake</strong> exige que aparezca una línea equivalente a esta alprincipio <strong>de</strong>l fichero <strong>CMake</strong>Lists.txt. El objetivo es verificar que la versión<strong>de</strong>l <strong>CMake</strong> usada es igual o superior a la exigida. Esto se hace ya que elcomportamiento <strong>de</strong>l <strong>CMake</strong> pue<strong>de</strong> variar entre versiones.– < numero version >: Número <strong>de</strong> versión. La versión actual es la2.6, por lo que lo normal es poner ese número. Sin embargo, la versiónanterior, la 2.4, es bastante usada y son muy compatibles, por lo quepue<strong>de</strong> usarse también.4 Primer ejemploHaciendo uso <strong>de</strong> las directivas anteriores, vamos a crear el <strong>CMake</strong>Lists.txt<strong>de</strong> un proyecto real, pero sencillo. Copiamos el fichero cma.tgz, y crearemosun <strong>CMake</strong>Lists.txt para po<strong>de</strong>r compilarlo. Consejo: Usar la directiveCMAKE VERBOSE MAKEFILE <strong>de</strong>l apartado 10.5


5 Usando y <strong>de</strong>finiendo libreríasHasta ahora hemos utilizado <strong>CMake</strong> para construir programas en los que nohabía implicada ninguna librería. Vamos a ver ahora cómo tratar con librerías.El primer paso es po<strong>de</strong>r enlazar con librerías existentes. Ahora mismo nonos vamos a preocupar en buscarlas instaladas, eso se enseña en el apartado ??.El primer paso es indicarle que para crear el ejecutable <strong>de</strong>be <strong>de</strong> enlazar conlas librerías.• TARGET LINK LIBRARIES(< ejecutable > [< librerias >]): Indicalas librerías con las que enlazar.– < ejecutable >: Nombre <strong>de</strong>l ejecutable utilizado en ADD EXECUTABLE.– < librerias >. En Unix/Linux por convención las librerías empiezanpor libxxx.so ó libxxx.a, por lo que ni prefijo lib ni la extensión hayque añadirlo. Ejemplo, para compilar el programa distancia eucli<strong>de</strong>acon la librería matemática libm, se usaríaTARGET LINK LIBRARIES(distancia eucli<strong>de</strong>a m).Mediante esta instrucción se indica que enlace con una librería. Las libreríasserán DLL (Windows), librerías dinámicas (Unix/Linux) o estáticas.Normalmente se hace uso <strong>de</strong> una variable LIBS en la que se aña<strong>de</strong>n el total<strong>de</strong> librerías <strong>de</strong> las que <strong>de</strong>pen<strong>de</strong>.Otro uso <strong>de</strong> librerías es el <strong>de</strong> crear vuestras propias librerías. Esta es unatarea que suele ser muy difícil con otros entornos. Con <strong>CMake</strong> es muy fácil.Simplemente se usa la directiva• ADD LIBRARY(< nombre libreria > SHARED|ST AT IC < ficheros >):Define una librería.– < nombre libreria > <strong>de</strong>fine el nombre <strong>de</strong> la librería (sin prefijo lib niextensión).– SHARED|ST AT IC <strong>de</strong>fine el tipo <strong>de</strong> librería. SHARED <strong>de</strong>fine unalibrería dinámica (.so en Unix/Linux, DLL en Windows), mientrasque ST AT IC <strong>de</strong>finiria una librería .a. Dada la nula dificultad enhacer la librería dinámica, recomiendo crearlas dinámicas.PROJECT( h e l l o C)SET(LIBSRCh e l l o l i b )SET(SRCh e l l o )ADD LIBRARY( h e l l o l i b SHARED ${LIBSRC})ADD EXECUTABLE( h e l l o ${SRC})TARGET LINK LIBRARIES( h e l l o h e l l o l i b )6


6 Búsqueda <strong>de</strong> LibreríasUn aspectos que hace las herramientas autotools muy bien es el <strong>de</strong> buscar libreríasnecesarias para compilar. Antes <strong>de</strong> compilar, i<strong>de</strong>ntifica el compilador, ylas distintas librerías (ej: Qt). En el caso <strong>de</strong> no encontrarlo, termina el procesoavisando al usuario con un mensaje a<strong>de</strong>cuado, <strong>de</strong> esta forma sabe que <strong>de</strong>be <strong>de</strong>instalar dicha librería antes <strong>de</strong> reintentarlo. Usando un simple Makefile daríaun error en el enlazado, pero sin avisar convenientemente al usuario <strong>de</strong>l motivo<strong>de</strong>l error.<strong>CMake</strong> también permite realizar este tipo <strong>de</strong> operaciones, tanto para búsqueda<strong>de</strong> ejecutables como para búsqueda <strong>de</strong> librerías. Aunque posee instruccionespara realizar búsquedas personalizadas <strong>de</strong> librerías, por comodidad permitenficheros <strong>de</strong> extensiones que permiten buscar cómodamente una librería o programa.Para ello se hace uso <strong>de</strong> la directiva INCLUDE conjuntamente con un ficheroFind existente. En el siguiente apartado pongo un ejemplo.6.1 Incluyendo generación <strong>de</strong> código mediante DoxygenPara añadir a makefile la opción <strong>de</strong> generar la documentación en doxygen, esnecesario hacer uso <strong>de</strong> la directiva INCLUDE.• INCLUDE(FindDoxygen) [REQUIRED]: Busca el software Doxygen.Una vez indicado, <strong>de</strong>fine (si existe) en la variable DOXY GEN E XECUT ABLEla ruta <strong>de</strong>l ejecutable Doxygen. La <strong>de</strong>ja en blanco si no lo encontró.# Busca e l DoxygenINCLUDE( FindDoxygen )# Comprueba s i l o ha encontrado , s i no no hace nada ( no da e r r o r )IF (DOXYGEN EXECUTABLE)# Avisa <strong>de</strong> que l o ha encontradoMESSAGE( STATUS ” S e t t i n g Doxygen Generator ” )# Define l a nueva s a l i d a ” doc ” como r e s u l t a d o <strong>de</strong> e j e c u t a r Doxygen sobre e l# d i r e c t o r i o a c t u a l ( Doxygen <strong>de</strong>be <strong>de</strong> e s t a r perfectamente c o n f i g u r a d o )ADD CUSTOM TARGET(docCOMMAND ${DOXYGEN EXECUTABLE}VERBATIM)ENDIF(DOXYGEN EXECUTABLE)6.2 Buscando una libreríaEn el apartado anterior se buscaba un ejecutable, pero el caso más habitual esla búsqueda <strong>de</strong> librerías <strong>de</strong> <strong>de</strong>sarrollo. Se realiza <strong>de</strong> la misma forma, mediantela directiva INCLUDE.Ejemplo:7


• INCLUDE(FindQt4).Esta directiva permite buscar la librería Qt4 para po<strong>de</strong>r enlazarla.La acción <strong>de</strong> cada Find pue<strong>de</strong> diferir, pero por convención utilizan la mayoríael mismo esquema. Una vez incluida, <strong>de</strong>fine una serie <strong>de</strong> variables si la encontró(don<strong>de</strong> < P KG > es el nombre <strong>de</strong>l paquete/librería):• < P KG > INCLUDE DIRS: Define la ruta <strong>de</strong> los inclu<strong>de</strong>s. Usualmentese ha añadido automáticamente a INCLUDE D IRECT ORIES,pero en algún caso pue<strong>de</strong> ser necesario incluirlo.• < P KG > LIBRARIES: Librerías a incluir. Se <strong>de</strong>ben <strong>de</strong> especificar enla instrucción TARGET LINK LIBRARIES.• < P KG > DEFINITIONS: Definición <strong>de</strong> la librería.Admite el parámetro adicional REQUIRED. Si está <strong>de</strong>finido y no encuentratermina, si no está <strong>de</strong>finido, simplemente no hace nada, pero se pue<strong>de</strong> comprobarque tras el INCLUDE una <strong>de</strong> estas variables esté <strong>de</strong>finida. Si no es el caso, sepue<strong>de</strong> escribir un mensaje <strong>de</strong> advertencia con MESSAGE• MESSAGE(“Mensaje”): Permite escribir un mensaje.Esta directiva permite escribir un mensaje <strong>de</strong> texto al usuario.• MESSAGE(FATAL ERROR “Mensaje”): Permite escribir un mensaje<strong>de</strong> error, y terminar.Esta directiva permite escribir un mensaje <strong>de</strong> texto al usuario avisando <strong>de</strong>un error, y terminar <strong>de</strong> procesar el fichero <strong>CMake</strong>Lists.txt.6.3 Buscando una librería a manoComo ya comenté, en el caso <strong>de</strong> que no exista ningún módulo para la libreríaque queremos usar, tenemos dos opciones.• Definir el módulo, y contribuir a la sociedad :-).• Hacer uso <strong>de</strong> la directiva FIND LIBRARY.• FIND LIBRARY(< variable > NAMES < nombre lib > PATHS< rutas busqueda >): Busca una librería.– < variable > Nombre <strong>de</strong> la variable.– < nombre lib > Lista <strong>de</strong> nombres <strong>de</strong> la librería (sin extensión y sinprefijo lib).– < rutas busqueda >, conjunto <strong>de</strong> rutas (path) en el que buscar lalibrería.8


El proceso es muy sencillo, busca para cada una <strong>de</strong> las rutas la libreríaindicada un fichero con el nombre indicado, y si lo encuentra almacena endicha variable la ruta completa <strong>de</strong> la librería. Si no la encuentra <strong>de</strong>ja lavariable sin <strong>de</strong>finir (se pue<strong>de</strong> comprobar con IF (NOT < variable >).Ejemplo:FIND LIBRARY(TCL LIBNAMES t c lPATHS / usr / l i b / usr / l o c a l / l i b )IF (TCL LIB)TARGET ADD LIBRARY( H e l l oENDIF (TCL LIB)TCL LIB)6.4 Ejercicio: Compilar un programa QtVamos a compilar un programa Qt, para ello vamos a tener que buscar el paqueteantes <strong>de</strong> compilarlo.7 Instalando el softwareHasta ahora el make tendría la información necesaria para compilar los programasy librerías configurados, pero no tendría información <strong>de</strong> instalación. Siqueremos po<strong>de</strong>r usar una or<strong>de</strong>n make install y que se instalen los programasy/o librerías, es necesario configurarlo a<strong>de</strong>cuadamente, mediante las directivassiguientes.• INSTALL(FILES < nombre libreria > DESTINATION lib): Permiteinstalar una librería.– < nombre libreria >: Define el fichero <strong>de</strong> la librería instalar (con suruta, si se encuentra en otro directorio).• INSTALL(FILES < nombre ejecutable > DESTINATION bin):Permite instalar un ejecutable.– < nombre ejecutable >: Define el programa a instalar (con su ruta,si se encuentra en otro directorio).En ambos casos, se pue<strong>de</strong> especificar un único ejecutable o librería o una lista<strong>de</strong> ellos (separados por espacio en blanco). Sin mayor configuración, instalará en/usr/local/bin y /usr/local/lib, respectivamente. Si se <strong>de</strong>sea cambiar el prefijose pue<strong>de</strong> usar la variable CMAKE INSTALL PREFIX.9


8 Información <strong>de</strong>l makeUn problema importante <strong>de</strong>l <strong>CMake</strong> es que, a diferencia <strong>de</strong> las autotools, requieretener instalado el cmake para compilar. Aunque a primera vista puedaparecer un problema importante, ya <strong>de</strong> antemano le exigimos al usuario quecompila el gcc/g++, make, todas las librerías dinámicas necesarias, . . . por loque consi<strong>de</strong>ramos que no es un problema tan importante.El Makefile generado admite varias opciones. Usando make help se indicanlas distintas opciones. Las más importantes son:• all: Permite compilar todo el sistema, tanto los ejecutables indicados conADD EXECUTABLE como las librerías ADD LIBRARY.• clean: Borra todos los ficheros generados (no elimina los ficheros <strong>CMake</strong>xxxgenerados por cmake).• rebuild cache: Compila todo, ignorando la caché.• <strong>de</strong>pend: Comprueba las <strong>de</strong>pen<strong>de</strong>ncias, no hace nada más.A<strong>de</strong>más, por cada programa(ejecutable, librería, fichero objeto) existe unadirectiva para compilarlo por separado, si se <strong>de</strong>sea. A<strong>de</strong>más <strong>de</strong> este comportamientopor <strong>de</strong>fecto, se pue<strong>de</strong>n añadir opciones mediante la directivaSin embargo, se pue<strong>de</strong>n añadir nuestras instrucciones, mediante la instrucciónADD CUSTOM TARGET.• ADD CUSTOM TARGET(< nombre > COMMAND < or<strong>de</strong>n >[V ERBAT IM]): Permite añadir opción al make.– < nombre >: nombre <strong>de</strong> la opción. Para ejecutar la or<strong>de</strong>n se haríamake < nombre >.– < or<strong>de</strong>n >: Sentencia shell a ejecutar, a menudo es necesario usar laruta. Por portabilidad, es conveniente hacer uso <strong>de</strong> Find.– V ERBAT IM: Parámetro adicional que activa la información.También se pue<strong>de</strong>n <strong>de</strong>finir opciones propias, leídas mediante la expresióncmake -DVAR=valor, mediante la directiva.• OPTION(< variable > < <strong>de</strong>scripcion > [valor <strong>de</strong>fecto]): Define unparámetro.– < variable > nombre <strong>de</strong>l la variable.– < <strong>de</strong>scripcion > Ca<strong>de</strong>na con la <strong>de</strong>scripción <strong>de</strong>l parámetro.– valor <strong>de</strong>fecto valor por <strong>de</strong>fecto.Ejemplo: OPTION(INSTALL DOC “Set to OFF to skip build/installDocumentation” ON), permite especificar si se <strong>de</strong>sea instalar la documentación(la instala por <strong>de</strong>fecto).10


9 Configuración <strong>de</strong> DirectoriosEn primer lugar, es muy usual que un directorio <strong>de</strong> código fuente a su vez sedivida en otros directorios (que <strong>de</strong>finan librerías, por ejemplo). En este caso,se pue<strong>de</strong> <strong>de</strong>finir para cada uno <strong>de</strong> esos directorios un fichero <strong>CMake</strong>Lists.txt yestablecer que el directorio padre llame a los <strong>CMake</strong>Lists.txt <strong>de</strong> sus subdirectorios.• ADD SUBDIRECTORY(< directorio >): Aña<strong>de</strong> un subdirectorio.– < directorio > directorio a añadir, con la ruta relativa.Permite añadir un subdirectorio. Antes <strong>de</strong> procesar el directorio actual, seprocesará cada uno <strong>de</strong> los subdirectorios indicado. Toda variable <strong>de</strong>finidaen el directorio padre mantendrá su valor para cada uno <strong>de</strong> los <strong>CMake</strong>-Lists.txt <strong>de</strong> sus subdirectorios indicados. Sin embargo, es conveniente evitar<strong>de</strong>pen<strong>de</strong>r <strong>de</strong>masiado <strong>de</strong> dichas variables, ya que generan <strong>de</strong>pen<strong>de</strong>nciasinnecesarias.• INCLUDE DIRECTORIES( < directorios > ): Permite insertar directoriospara los inclu<strong>de</strong>.Mediante esta variable se pue<strong>de</strong>n añadir nuevas rutas para buscar losficheros .h. Si se hace uso <strong>de</strong> una sentencia #inclu<strong>de</strong> ¡name.h¿ <strong>de</strong>bería <strong>de</strong>encontrarse el fichero name.h o bien en una ruta <strong>de</strong>l sistema (usualmente:/usr/inclu<strong>de</strong>/, /usr/local/inclu<strong>de</strong>, . . . ) o bien en una ruta asignada a estavariable.• LINK DIRECTORIES( < directorios > ): Permite insertar directoriosen don<strong>de</strong> buscar las librerías. Mediante esta variable se pue<strong>de</strong>n añadirnuevas rutas para buscar las librerías.• AUX SOURCE DIRECTORIES( < directorio > < variable > ):Permite añadir en la variable < variable > todos los ficheros almacenadosen el directorio < directorio >.– < directorio > directorio (usualmente subdirectorio) en don<strong>de</strong> seencuentran código fuente.– < variable > variable en don<strong>de</strong> se almacenan todos los ficheros fuente<strong>de</strong>l directorio indicado.Existe una serie <strong>de</strong> variables que permite especificar las rutas para cadaelemento. Aunque no suele ser necesario suele ser conveniente <strong>de</strong>finirlas si elsoftware posee una estructura compleja.• CMAKE INSTALL PREFIX: Ruta <strong>de</strong> instalación.• PROJECT BINARY DIR: Directorio en don<strong>de</strong> se guarda el binario(no modificar).11


• PROJECT SOURCE DIR: Directorio en don<strong>de</strong> se encuentra el códigofuente (no modificar).10 Variable <strong>de</strong> Entorno <strong>de</strong> <strong>CMake</strong><strong>CMake</strong> usa una serie <strong>de</strong> variables <strong>de</strong> entorno que <strong>de</strong>terminan su comportamiento.Todas ellas poseen un valor por <strong>de</strong>fecto, pero que pue<strong>de</strong>n modificarse <strong>de</strong> dosformas:• Mediante la directiva SET(< variable > < valor >), don<strong>de</strong> valor pue<strong>de</strong>ser una ca<strong>de</strong>na, una lista <strong>de</strong> ficheros, o un valor numérico. Todo <strong>de</strong>pen<strong>de</strong><strong>de</strong> la variable utilizada.• Mediante la línea <strong>de</strong> comando cmake -D< variable >=< valor >. Medianteeste formato se pue<strong>de</strong> <strong>de</strong>finir sin necesidad <strong>de</strong> reescribirlo en el<strong>CMake</strong>Lists.txt. Es una opción válida para re<strong>de</strong>finir una variable máspuntualmente (como CMAKE VERBOSE MAKEFILEo CMAKE BUILD TYPE), pero no para aplicarlo <strong>de</strong> forma general.A continuación <strong>de</strong>tallo las variables que consi<strong>de</strong>ro más importantes:• CMAKE VERBOSE MAKEFILE OF F |ON: Activa mensajes <strong>de</strong> informaciónpor pantalla.A la hora <strong>de</strong> <strong>de</strong>finir, a veces pue<strong>de</strong>n producirse errores como no encontrarel código <strong>de</strong> una función. Con esta línea muestra lo que hace (los ficherosque compila, los parámetros que usa). Suele ser muy recomendable usarlo.• CMAKE BUILD TYPE Release|Debug: Selecciona el modo <strong>de</strong> <strong>de</strong>puración.– Release: Activa todas las opciones <strong>de</strong> optimización (sin información<strong>de</strong> <strong>de</strong>puración). Nota: Desactiva también las instrucciones asserten C/C++.– Debug: Activa la información <strong>de</strong>l <strong>de</strong>purador (para po<strong>de</strong>r usar <strong>de</strong>spués).No optimiza.Ver apartado 11 para más información.11 Modos <strong>de</strong> CompilaciónA la hora <strong>de</strong> trabajar con el compilador existen dos modos <strong>de</strong> compilación,<strong>de</strong>finidos en la variable CMAKE BUILD TYPE: Depuración (Debug) y <strong>de</strong>spliegue(Release).Es recomendable trabajar en modo Debug y emplear el modo release cuandose realice la versión final, o para hacer pruebas <strong>de</strong> rendimiento (si se usan lasSTL <strong>de</strong> C++, hay gran diferencias <strong>de</strong> rendimiento entre un modo u otro).12


Dado que supongo que usáis un sistema <strong>de</strong> repositorio para confirmar queel <strong>CMake</strong>Lists.txt <strong>de</strong> <strong>de</strong>sarrollo y <strong>de</strong> implantación coincidan, el convenienteespecificar el modo <strong>de</strong> compilación <strong>de</strong>s<strong>de</strong> la linea <strong>de</strong> comandos (al menos en lasfases iniciales d <strong>de</strong>sarrollo).A continuación muestro algunos trucos que pue<strong>de</strong>n seros interesantes.11.1 Activar las instrucciones assert en modo ReleaseA pesar <strong>de</strong> lo comentado anteriormente, es posible hacer que las instruccionesassert funcionen en modo Release.# d e f i n e macro ∗DEBUG macro en modo ReleaseSTRING(TOLOWER ${CMAKE BUILD TYPE} CMAKE BUILD TYPE TOLOWER)i f (CMAKE BUILD TYPE TOLOWER MATCHES r e l e a s e )s e t (NDEBUG 1)e n d i f (CMAKE BUILD TYPE TOLOWER MATCHES r e l e a s e )11.2 Definir vuestro propio modoEn este ejemplo <strong>de</strong>fino un modo Profile, en el que se activará la directiva “-pg”necesaria para po<strong>de</strong>r usar la aplicación <strong>de</strong> profile <strong>de</strong> C++ (si no sabeis a lo queme refiero, <strong>de</strong>beríais echarle un vistado al programa cprof ).# d e f i n e macro ∗DEBUG macro en modo ReleaseSTRING(TOLOWER ${CMAKE BUILD TYPE} CMAKE BUILD TYPE TOLOWER)IF (CMAKE BUILD TYPE TOLOWER MATCHES p r o f i l e )SET (GPROF FLAGS ”−pg ”)SET (FLAGS ”${SHARED FLAGS} −Wall −O −DNDEBUG ${GPROF FLAGS}”)SET (CMAKE CXX FLAGS ”${FLAGS} ${GPROF FLAGS}”)SET (CMAKE EXE LINKER FLAGS ”${GPROF FLAGS}”)MESSAGE(STATUS ” P r o f i l e ”)ENDIF (CMAKE BUILD TYPE TOLOWER MATCHES p r o f i l e )11.3 Activas todos los avisos <strong>de</strong> compilaciónExisten una serie <strong>de</strong> directivas que indican al compilador que active todos losposibles mensajes <strong>de</strong> advertencia (warnings), que pue<strong>de</strong>n utilizarse en todos losmodos. Lamentablemente, no se especifica por <strong>de</strong>fecto. Para activarlo se pue<strong>de</strong>utilizar la directiva:L• SET(CMAKE CXX FLAGS “-Wall”) para C++.• SET(CMAKE C FLAGS “-Wall”) para ansi C.Otra opción más portable sería:• ADD DEFINITIONS(“-Wall”), pero en el caso <strong>de</strong> que queramos <strong>de</strong>finirdirectivas distintas para C y para C++ tendríamos que usar las variablesanteriores).13


12 Opciones AvanzadasTal y como se ha podido ver en algunos ejemplos, se pue<strong>de</strong>n ejecutar las directivasen función <strong>de</strong> condiciones. Se ha intentado que sea lo suficientementeflexible para adaptarse a las distintas necesida<strong>de</strong>s, pero no a costa <strong>de</strong> hacerlo<strong>de</strong>masiado complejo.12.1 Tipos <strong>de</strong> CondicionesA continuación presentamos los principales tipos <strong>de</strong> condiciones:• DEFINED( < var > ): Comprueba si la variable < var > está <strong>de</strong>finida.• < variable > STREQUAL < ca<strong>de</strong>na >: Devuelve si el contenido <strong>de</strong> lavariable es la ca<strong>de</strong>na indicada.• NOT < CONDICION >: Devuelve verda<strong>de</strong>ro si la condición indicadaes falsa.• < variable > < valor >: Devuelve verda<strong>de</strong>ro si la variable < variable >es numérica o lógica (ON—OFF) y su valor coinci<strong>de</strong> con el indicado en< valor >.12.2 Directivas CondicionalesExiste directiva condicional, que permite modificar la construcción en función<strong>de</strong> alguna información (generar documentación mediante doxygen sólo si estáinstalado)• IF( < CONDICION > ).ENDIF( < CONDICION > )La interpretación <strong>de</strong> la ca<strong>de</strong>na es evi<strong>de</strong>nte. Las directivas situadas <strong>de</strong>ntro<strong>de</strong>l IF sólo se evaluará si la condición indicada es cierta, pero en todo caso <strong>de</strong>be<strong>de</strong> ser sintácticamente correctas.Dado que a menudo es muy molesto tener que repetir la condición dos veces(en el IF y en el ENDIF), se pue<strong>de</strong> hacer uso <strong>de</strong> la condición• SET (CMAKE ALLOW LOOSE LOOP CONSTRUCTS TRUE):Permite <strong>de</strong>finir las sentencias ENDIF sin la condición.12.3 Directivas IterativasAunque el uso <strong>de</strong> instrucciones iterativas no sea realmente necesario, hay ocasionesen las que pue<strong>de</strong> rsultar muy cómodo su uso.14


• FOREACH (< variable > < valores >).ENDFOREACH(< variable >)Con la instrucción FOREACH se pue<strong>de</strong> <strong>de</strong>finir aplicar un conjunto <strong>de</strong>directivas sucesivas veces, cada vez con un valor <strong>de</strong> la variable < variable >distinto.Ejemplo <strong>de</strong> su uso:SET(REALEALIBSr e a l e anewmatr e a l p e a s ybbob2009r e a l l s )SET ( LIBS m newmat ${REALEALIBS})SET (EAschc<strong>de</strong>s s g apso)FOREACH(EA ${EAs})ADD EXECUTABLE( ${EA} main $ {EA} . cc )TARGET LINK LIBRARIES( ${EA} ${LIBS} r e a l $ {EA} r e a l p c e c 2 0 0 5 m)INSTALL(TARGETS ${EA} DESTINATION bin )INSTALL( FILES l i b / l i b r e a l $ {EA} . so DESTINATION l i b )ENDFOREACH(EA)13 Compilando un proyecto QtTal y como se ha comentado, <strong>CMake</strong> es actualmente la herramienta <strong>de</strong> construcciónpara proyectos KDE, y, por tanto, para Qt.El principal problema para el uso <strong>de</strong> Qt era la necesidad <strong>de</strong>l sistema moc (unaespecie <strong>de</strong> preprocesador especial), que se aborda mediante el uso <strong>de</strong>l módulo<strong>de</strong> Qt4.q t p r o j e c t / <strong>CMake</strong>Lists . t x t :p r o j e c t ( q t p r o j e c t ) # the name o f your p r o j e c tcmake minimum required (VERSION 2 . 4 . 0 )f i n d p a c k a g e ( Qt4 REQUIRED) # f i n d and setup Qt4 f o r t h i s p r o j e c t15


# t e l l cmake to p r o c e s s <strong>CMake</strong>Lists . t x t in that s u b d i r e c t o r ya d d s u b d i r e c t o r y ( s r c )q t p r o j e c t / s r c / <strong>CMake</strong>Lists . t x t :# the next l i n e s e t s up i n c l u d e and l i n k d i r e c t o r i e s and d e f i n e s some v a r i a b l e s that# you can modify the behavior by s e t t i n g some v a r i a b l e s , e . g .# s e t (QT USE OPENGL TRUE)# −> t h i s w i l l cause cmake to i n c l u d e and l i n k a g a i n s t the OpenGL modulei n c l u d e ( ${QT USE FILE})# the v a r i a b l e ” qtproject SRCS ” c o n t a i n s a l l . cpp f i l e s o f t h i s p r o j e c ts e t ( qtproject SRCSmain . cpptop . cpp)# t e l l cmake to c r e a t e . moc f i l e s f o r a l l f i l e s i n the v a r i a b l e qtproject SRCS that# note : t h i s assumes that you use #i n c l u d e ” hea<strong>de</strong>r . moc” i n your f i l e sqt4 automoc ( ${ qtproject SRCS })# c r e a t e an e x e c u t a b l e f i l e named ” q t p r o j e c t ” from the s o u r c e f i l e s i n the v a r i a b l ea d d e x e c u t a b l e ( q t p r o j e c t ${ qtproject SRCS })# l i n k the ” q t p r o j e c t ” t a r g e t a g a i n s t the Qt l i b r a r i e s . which l i b r a r i e s e xactly , i st a r g e t l i n k l i b r a r i e s ( q t p r o j e c t ${QT LIBRARIES})14 ConclusionesEspero que esta guía dirigida les haya servido, y que se animen a utilizar el<strong>CMake</strong> :-).16

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!