jueves, 31 de marzo de 2016

Instalar FLTK en Ubuntu y poder compilar ejemplos de Programming: Principles and Practice Using C++

Pocas veces me topo con problemas en Ubuntu (Kubuntu en esta ocasión) de cosas que realmente me importen. ¿Juegos? Casi nunca se me da andar haciendo eso. ¿Aplicaciones específicas? Todas mis necesidades las puedo suplir con alguna del mundo GNU/Linux sin problema alguno. La mayoría de las veces cualquier problema se soluciona con una búsqueda rápida con Google (y muchs más en alguno de los sitios de Stack Exchange). Por eso este problema fue un poco más molesto de lo que debería haber sido.

Revisando el libro de Stroustrup Programming: Principles and Practice Using C++, 2nd Edition en el capítulo 12 me topo con una introducción de gráficos, que en principio no debería causar dolores de cabeza. Como se usa FLTK (que en su versión Linux es un tanto feo, pero para lo que es está más que bien), busqué rápido cómo instalarlo rápido y encontré que lo más fácil es
$ sudo apt install libfltk1.3-dev
que instala la versión 1.3.2, suficientemente nueva para los requerimientos. Luego viene el problema de cómo generar el ejecutable del ejemplo sencillo que viene en el Apéndice D del libro. Otra búsqueda da que basta con
$ fltk-config --compile fltkTest.cpp
que genera un código un tanto grande (y para mi nivel bastante incomprensible, aunque en realidad cualquiera a estas alturas del libro puede darse una idea de lo que sucede). No obstante, funcionó y como siempre: si no está roto, no lo arregles.

El problema comenzó cuando quise usar las pequeñas facilidades que Stroustrup pone en su sitio http://www.stroustrup.com/Programming/PPP2code/ , que son clases de interfaz. Para empezar, el código que genera fltk-config no pasa del inicio, además de que dicho comando no usa el estándar C++11. Por supuesto, lo que sucedió primero es que no coloqué los archivos .cpp de la interfaz junto al código del primer ejemplo del capítulo 12. Gracias a lo que encontré en stackoverflow.com/questions/7134049/stroustrups-simple-window-h/36322596
modifiqué el comando generado por fltk-config añadiendo -lfltk_images y -std=c++11 y usando clang++ pues encuentro más accesible sus mensajes de error:
$ clang++ -I/usr/include/cairo -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng12 -I/usr/include/freetype2 -I/usr/include/cairo -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng12 -g -O2 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_THREAD_SAFE -D_REENTRANT -Wl,-Bsymbolic-functions -lfltk_images -lfltk -lX11 -std=c++11 -o 's12_3_first' 's12_3_first.cpp' Simple_window.cpp Graph.cpp GUI.cpp Window.cpp
y eso me dejó con problemas de compilación "normales", que cazándolos pude aislar a los archivos de facilidades de Stroustrup.

  1. Primero, descomenté std_lib_facilities.h en Graph.h
  2. Para resolver una ambigüedad de Window, hay que especificar Graph_lib::Window en la línea 9 de Simple_window.h
  3. El archivo de cabecera std_lib_facilities.h genera unos warnings en las líneas 107 y 113 ya que se usa i<0 cuando i es unsigned. 
  4. En la línea 159 de Graph.h se usa fl_color(), que el compilador dice debería ser Fl_Color()
  5. Necesité descomentar los contructores de Point en Point.h
  6. Hay varias redefiniciones en Simple_window.cpp de métodos de Simple_window.h En Simple_window.cpp comenté (para no borrar) las definiciones del constructor, cb_next y wait_for_button (que además tiene una definición diferente a la que está en Simple_window.h). En Simple_window.h cambié la definición de wait_for_button para que sólo llamé a Fl::run(). Por cierto, ambas definiciones de este método no eran funcionales pues provocaban que la ventana (cuando por fin se generó) no se pudiera cerrar con el botón correspondiente, sólo con el botón "Next"; incluso la ventana se "colgaba" si se daba click al botón de cerrar, y el botón "Next" ya no estaba disponible.
  7. En GUI.cpp hay una redefinición para el constructor de Menu, que lo puse como comentario.

Con esto la compilación/enlace se consiguió y el ejecutable se generó.

Pero fue momento de revisar el comandote usado para esto. -I<carpeta> hace que se considere una carpeta para la acción (tanto de g++ como de clang++), pero revisando el comando no sólo se tienen duplicadas las carpetas, sino que ninguna está en el sistema (y el compilador no me avisó). Además, al compilar las facilidades para acelerar las cosas un poco, el compilador mencionó que -lftk_images, -lftk y -lX11 no eran necesarios. Al final, terminé con el siguiente comando para compilar a objeto cada archivo de facilidad:
$ clang++ -O2 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_THREAD_SAFE -D_REENTRANT -g -std=c++11 -c Simple_window.cpp
mientras que para generar el ejecutable ya se puede usar
% clang++ -O2 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_THREAD_SAFE -D_REENTRANT -Wl,-Bsymbolic-functions -lfltk_images -lfltk -lX11 -g -std=c++11 ../PPP2code/Simple_window.o ../PPP2code/Graph.o ../PPP2code/GUI.o ../PPP2code/Window.o -o z s12_3_first.cpp
(luego de reorganizar dichos archivos en una carpeta en una hermana de la de trabajo) y genera un ejecutable llamado z. Ambos comandos son mucho más simples y cortos. Falta revisar si se pueden eliminar más opciones de ambos comandos y que todavía se obtenga el ejecutable, pero para eso debo tomarme más tiempo para hacer pruebas.

Por cierto, para compilar el ejemplo del Apéndice D, basta con
% clang++ -O2 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_THREAD_SAFE -D_REENTRANT -Wl,-Bsymbolic-functions -lfltk -lX11 -g -std=c++11 -o z0 fltkTest.cpp


No hay comentarios.:

Publicar un comentario